B wÏ1`ùnã@s^ddlZddlZddlmZddlmZmZddddd d d d œZe d ¡Z Gdd„deƒZ dS)éNé)ÚJsonSchemaDefinitionException)Ú CodeGeneratorÚ enforce_listZNoneTypeÚboolz int, floatÚintÚstrz list, tupleÚdict)ÚnullÚbooleanÚnumberÚintegerÚstringÚarrayÚobjectz (?d?„Z‡Z S)@ÚCodeGeneratorDraft04zX^\d{4}-[01]\d-[0-3]\d(t|T)[0-2]\d:[0-5]\d:[0-5]\d(?:\.\d+)?(?:[+-][0-2]\d:[0-5]\d|z|Z)\Zz^[^@]+@[^@]+\.[^@]+\Zzv^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9])\ZzV^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\Zaå^(?:(?:[0-9A-Fa-f]{1,4}:){6}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|::(?:[0-9A-Fa-f]{1,4}:){5}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,4}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))|(?:(?:[0-9A-Fa-f]{1,4}:){,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|(?:(?:[0-9A-Fa-f]{1,4}:){,6}[0-9A-Fa-f]{1,4})?::)\Zz^\w+:(\/?\/?)[^\s]+\Z)z date-timeÚemailÚhostnameZipv4Zipv6ÚuriNTcsêtƒ ||¡||_||_|j d|jfd|jfd|jfd|j fd|j fd|j fd|j fd|j fd |jfd |jfd |jfd |jfd |jfd|jfd|jfd|jfd|jfd|jfd|jfd|jfd|jfd|jfd|jfd|jff¡dS)NÚtypeÚenumÚallOfÚanyOfÚoneOfÚnotÚ minLengthÚ maxLengthÚpatternÚformatÚminimumÚmaximumÚ multipleOfÚminItemsÚmaxItemsÚ uniqueItemsÚitemsÚ minPropertiesÚ maxPropertiesÚrequiredÚ dependenciesÚ propertiesÚpatternPropertiesÚadditionalProperties)ÚsuperÚ__init__Ú_custom_formatsÚ _use_defaultZ_json_keywords_to_functionÚupdateÚ generate_typeÚ generate_enumÚgenerate_all_ofÚgenerate_any_ofÚgenerate_one_ofÚ generate_notÚgenerate_min_lengthÚgenerate_max_lengthÚgenerate_patternÚgenerate_formatÚgenerate_minimumÚgenerate_maximumÚgenerate_multiple_ofÚgenerate_min_itemsÚgenerate_max_itemsÚgenerate_unique_itemsÚgenerate_itemsÚgenerate_min_propertiesÚgenerate_max_propertiesÚgenerate_requiredÚgenerate_dependenciesÚgenerate_propertiesÚgenerate_pattern_propertiesÚgenerate_additional_properties)ÚselfÚ definitionÚresolverÚformatsZ use_default)Ú __class__©ú:/tmp/pip-unpacked-wheel-vlg95h98/fastjsonschema/draft04.pyr.%s8zCodeGeneratorDraft04.__init__cstƒj}|j|d<|S)NZcustom_formats)r-Ú global_stater/)rJÚres)rNrOrPrQEs z!CodeGeneratorDraft04.global_statec Cs¶t|jdƒ}yd dd„|Dƒ¡}Wn0tk rV}ztd |¡ƒ‚Wdd}~XYnXd}d|ksld |kr‚d |kr‚d j|jd }| d ||¡|jdd |¡ddWdQRXdS)z² Validation of type. Can be one type or list of types. .. code-block:: python {'type': 'string'} {'type': ['string', 'number']} rz, css|]}t|VqdS)N)ÚJSON_TYPE_TO_PYTHON_TYPE)Ú.0ÚtrOrOrPú Vsz5CodeGeneratorDraft04.generate_type..zUnknown type: {}NÚr r r z or isinstance({variable}, bool))Úvariablez&if not isinstance({variable}, ({})){}:z{name} must be {}z or )Úrule) rÚ _definitionÚjoinÚKeyErrorrrÚ _variableÚlÚexc)rJÚtypesZ python_typesr_ÚextrarOrOrPr2Ks  z"CodeGeneratorDraft04.generate_typec CsP|jd}t|ttfƒs tdƒ‚| d¡|jd| |¡ddWdQRXdS)z¨ Means that only value specified in the enum is valid. .. code-block:: python { 'enum': ['a', 'b'], } rzenum must be an arrayzif {variable} not in {enum}:z{name} must be one of {})rYN)rZÚ isinstanceÚlistÚtuplerr^r_Úe)rJrrOrOrPr3as  z"CodeGeneratorDraft04.generate_enumcCs.x(|jdD]}|j||j|jddq WdS)a’ Means that value have to be valid by all of those definitions. It's like put it in one big definition. .. code-block:: python { 'allOf': [ {'type': 'number'}, {'minimum': 5}, ], } Valid values for this definition are 5, 6, 7, ... but not 4 or 'abc' for example. rT)Úclear_variablesN)rZÚgenerate_func_code_blockr]Ú_variable_name)rJÚdefinition_itemrOrOrPr4qsz$CodeGeneratorDraft04.generate_all_ofc Cs¨| d¡xp|jdD]b}|jdddJ|jddd&|j||j|jdd| d ¡Wd QRX| d ¡Wd QRXqW|jddd|jd dd Wd QRXd S)a¯ Means that value have to be valid by any of those definitions. It can also be valid by all of them. .. code-block:: python { 'anyOf': [ {'type': 'number', 'minimum': 10}, {'type': 'number', 'maximum': 5}, ], } Valid values for this definition are 3, 4, 5, 10, 11, ... but not 8 for example. z{variable}_any_of_count = 0rzif not {variable}_any_of_count:F)Úoptimizeztry:T)rfz{variable}_any_of_count += 1Nz%except JsonSchemaValueException: passz/{name} must be valid by one of anyOf definition)rY)r^rZrgr]rhr_)rJrirOrOrPr5„s z$CodeGeneratorDraft04.generate_any_ofc Cs¤| d¡xp|jdD]b}|jdddJ|jddd&|j||j|jdd| d ¡Wd QRX| d ¡Wd QRXqW| d ¡|jd ddWd QRXd S)a· Means that value have to be valid by only one of those definitions. It can't be valid by two or more of them. .. code-block:: python { 'oneOf': [ {'type': 'number', 'multipleOf': 3}, {'type': 'number', 'multipleOf': 5}, ], } Valid values for this definition are 3, 5, 6, ... but not 15 for example. z{variable}_one_of_count = 0rzif {variable}_one_of_count < 2:F)rjztry:T)rfz{variable}_one_of_count += 1Nz%except JsonSchemaValueException: passz if {variable}_one_of_count != 1:z7{name} must be valid exactly by one of oneOf definition)rY)r^rZrgr]rhr_)rJrirOrOrPr6 s  z$CodeGeneratorDraft04.generate_one_ofc Csº|jd}|dkr"|jdddn”|dkr.dS|s\| d|j¡|jdddWdQRXnZ|jd dd | ||j|j¡WdQRX| d ¡| d ¡|jdddWdQRXdS) aT Means that value have not to be valid by this definition. .. code-block:: python {'not': {'type': 'null'}} Valid values for this definition are 'hello', 42, {} ... but not None. Since draft 06 definition can be boolean. False means nothing, True means everything is invalid. rTz{name} must not be there)rYFNzif {}:z*{name} must not be valid by not definitionztry:)rjz%except JsonSchemaValueException: passzelse:)rZr_r^r]rgrh)rJZnot_definitionrOrOrPr7¼s   z!CodeGeneratorDraft04.generate_notc Cs^| d¡J| ¡t|jdtƒs,tdƒ‚| d¡|jdddWdQRXWdQRXdS)Nzif isinstance({variable}, str):rzminLength must be a numberz if {variable}_len < {minLength}:z={name} must be longer than or equal to {minLength} characters)rY)r^Úcreate_variable_with_lengthrbrZrrr_)rJrOrOrPr8Øs   z(CodeGeneratorDraft04.generate_min_lengthc Cs^| d¡J| ¡t|jdtƒs,tdƒ‚| d¡|jdddWdQRXWdQRXdS)Nzif isinstance({variable}, str):rzmaxLength must be a numberz if {variable}_len > {maxLength}:z>{name} must be shorter than or equal to {maxLength} characters)rY)r^rkrbrZrrr_)rJrOrOrPr9às   z(CodeGeneratorDraft04.generate_max_lengthc Cs€| d¡l|jd}| dd¡ dd¡}t d|¡}t |¡|j|<| dt|ƒ¡|j d |dd WdQRXWdQRXdS) Nzif isinstance({variable}, str):rú\z\\ú"z\"z\\Zz-if not REGEX_PATTERNS[{}].search({variable}):z{name} must match pattern {})rY) r^rZÚreplaceÚ DOLLAR_FINDERÚsubÚreÚcompileÚ_compile_regexpsÚreprr_)rJrZ safe_patternZend_of_string_fixed_patternrOrOrPr:ès   z%CodeGeneratorDraft04.generate_patternc Cs| d¡ô|jd}||jkrr|j|}t|tƒrH| ||d|¡qú| d|¡|jd|ddWdQRXnˆ||jkrš|j|}| ||d|¡n`|dkrì|jd d d | d ¡WdQRX| d ¡|jdddWdQRXntd  |¡ƒ‚WdQRXdS)zô Means that value have to be in specified format. For example date, email or other. .. code-block:: python {'format': 'email'} Valid value for this definition is user@example.com but not @username zif isinstance({variable}, str):rZ _re_patternz(if not custom_formats["{}"]({variable}):z{name} must be {})rYNÚregexztry:F)rjzre.compile({variable})zexcept Exception:z{name} must be a valid regexzUnknown format: {}) r^rZr/rbrÚ_generate_formatr_Ú FORMAT_REGEXSrr)rJZformat_Z custom_formatZ format_regexrOrOrPr;ñs"        z$CodeGeneratorDraft04.generate_formatc CsT|jd|krP||jkr(t |¡|j|<| d|¡|jd|ddWdQRXdS)Nrz.if not REGEX_PATTERNS["{}"].match({variable}):z{name} must be {})rY)rZrsrqrrr^r_)rJZ format_nameZ regexp_nameÚregexprOrOrPrvs  z%CodeGeneratorDraft04._generate_formatc CsŽ| d¡zt|jdttfƒs(tdƒ‚|j dd¡r\| d¡|jdddWdQRXn$| d ¡|jd ddWdQRXWdQRXdS) Nz(if isinstance({variable}, (int, float)):rzminimum must be a numberZexclusiveMinimumFzif {variable} <= {minimum}:z${name} must be bigger than {minimum})rYzif {variable} < {minimum}:z0{name} must be bigger than or equal to {minimum})r^rbrZrÚfloatrÚgetr_)rJrOrOrPr<s   z%CodeGeneratorDraft04.generate_minimumc CsŽ| d¡zt|jdttfƒs(tdƒ‚|j dd¡r\| d¡|jdddWdQRXn$| d ¡|jd ddWdQRXWdQRXdS) Nz(if isinstance({variable}, (int, float)):r zmaximum must be a numberZexclusiveMaximumFzif {variable} >= {maximum}:z%{name} must be smaller than {maximum})rYzif {variable} > {maximum}:z1{name} must be smaller than or equal to {maximum})r^rbrZrryrrzr_)rJrOrOrPr=$s   z%CodeGeneratorDraft04.generate_maximumc Cs˜| d¡„t|jdttfƒs(tdƒ‚t|jdtƒr\|j d¡tj |j d<| d¡n | d¡| d¡|j d dd WdQRXWdQRXdS) Nz(if isinstance({variable}, (int, float)):r!zmultipleOf must be a numberzfrom decimal import DecimalÚDecimalzBquotient = Decimal(repr({variable})) / Decimal(repr({multipleOf}))z$quotient = {variable} / {multipleOf}zif int(quotient) != quotient:z'{name} must be multiple of {multipleOf})rY) r^rbrZrryrZ_extra_imports_linesÚappendÚdecimalr{Z_extra_imports_objectsr_)rJrOrOrPr>/s      z)CodeGeneratorDraft04.generate_multiple_ofc Csf| ¡| d¡Jt|jdtƒs,tdƒ‚| ¡| d¡|jdddWdQRXWdQRXdS)Nzif {variable}_is_list:r"zminItems must be a numberzif {variable}_len < {minItems}:z-{name} must contain at least {minItems} items)rY)Úcreate_variable_is_listr^rbrZrrrkr_)rJrOrOrPr?>s  z'CodeGeneratorDraft04.generate_min_itemsc Csf| ¡| d¡Jt|jdtƒs,tdƒ‚| ¡| d¡|jdddWdQRXWdQRXdS)Nzif {variable}_is_list:r#zmaxItems must be a numberzif {variable}_len > {maxItems}:z:{name} must contain less than or equal to {maxItems} items)rY)r~r^rbrZrrrkr_)rJrOrOrPr@Gs  z'CodeGeneratorDraft04.generate_max_itemsc CsN| ¡| d¡2| ¡| d¡|jdddWdQRXWdQRXdS)a² With Python 3.4 module ``timeit`` recommended this solutions: .. code-block:: python >>> timeit.timeit("len(x) > len(set(x))", "x=range(100)+range(100)", number=100000) 0.5839540958404541 >>> timeit.timeit("len({}.fromkeys(x)) == len(x)", "x=range(100)+range(100)", number=100000) 0.7094449996948242 >>> timeit.timeit("seen = set(); any(i in seen or seen.add(i) for i in x)", "x=range(100)+range(100)", number=100000) 2.0819358825683594 >>> timeit.timeit("np.unique(x).size == len(x)", "x=range(100)+range(100); import numpy as np", number=100000) 2.1439831256866455 zif {variable}_is_list:zOif {variable}_len > len(set(str({variable}_x) for {variable}_x in {variable})):z {name} must contain unique itemsr$)rYN)r~r^rkr_)rJrOrOrPrAPs   z*CodeGeneratorDraft04.generate_unique_itemsc CsÒ|jd}|dkrdS| ¡| d¡ž| ¡|dkrd| d¡|jdddWdQRXn`t|tƒr†x†t|ƒD]z\}}| d |¡4| d |¡| |d   |j |¡d   |j |¡¡WdQRX|j rzt|t ƒrzd |krz| dt|d ƒ¡qzWd|jkrÄ|jddkr@| d t|ƒ¡|jdddWdQRXnD| dt|ƒ¡.| |jdd  |j ¡d  |j |j ¡¡WdQRXn>|rÄ| d¡(| |d  |j ¡d  |j |j ¡¡WdQRXWdQRXdS)aÓ Means array is valid only when all items are valid by this definition. .. code-block:: python { 'items': [ {'type': 'integer'}, {'type': 'string'}, ], } Valid arrays are those with integers or strings, nothing else. Since draft 06 definition can be also boolean. True means nothing, False means everything is invalid. r%TNzif {variable}_is_list:Fzif {variable}:z{name} must not be there)rYzif {variable}_len > {}:z!{variable}__{0} = {variable}[{0}]z{}__{}z{}[{}]Údefaultzelse: {variable}.append({})ZadditionalItemsz({name} must contain only specified itemszFfor {variable}_x, {variable}_item in enumerate({variable}[{0}:], {0}):z{}_itemz {}[{{{}_x}}]z;for {variable}_x, {variable}_item in enumerate({variable}):)rZr~r^rkr_rbrcÚ enumeratergrr]rhr0r rtÚlen)rJZitems_definitionÚidxZitem_definitionrOrOrPrBesD         z#CodeGeneratorDraft04.generate_itemsc Csf| ¡| d¡Jt|jdtƒs,tdƒ‚| ¡| d¡|jdddWdQRXWdQRXdS)Nzif {variable}_is_dict:r&zminProperties must be a numberz$if {variable}_len < {minProperties}:z7{name} must contain at least {minProperties} properties)rY)Úcreate_variable_is_dictr^rbrZrrrkr_)rJrOrOrPrC¡s  z,CodeGeneratorDraft04.generate_min_propertiesc Csf| ¡| d¡Jt|jdtƒs,tdƒ‚| ¡| d¡|jdddWdQRXWdQRXdS)Nzif {variable}_is_dict:r'zmaxProperties must be a numberz$if {variable}_len > {maxProperties}:zD{name} must contain less than or equal to {maxProperties} properties)rY)rƒr^rbrZrrrkr_)rJrOrOrPrDªs  z,CodeGeneratorDraft04.generate_max_propertiesc Csx| ¡| d¡\t|jdttfƒs0tdƒ‚| ¡| d¡"|jd|  |jd¡ddWdQRXWdQRXdS)Nzif {variable}_is_dict:r(zrequired must be an arrayz6if not all(prop in {variable} for prop in {required}):z!{name} must contain {} properties)rY) rƒr^rbrZrcrdrrkr_re)rJrOrOrPrE³s  z&CodeGeneratorDraft04.generate_requiredc Cs| ¡| d¡ü| ¡xì|jd ¡D]Ú\}}t dd|¡}t|tt fƒsdt d  |j |¡ƒ‚| d|  |¡¡X| d|  |¡¡| d||  |¡¡|j|d   |j |¡d   |j|  |¡¡d d Wd QRX|jr.t|tƒr.d|kr.| d|  |¡t|dƒ¡q.WWd QRXd S)a Means object with defined keys. .. code-block:: python { 'properties': { 'key': {'type': 'number'}, }, } Valid object is containing key called 'key' and value any number. zif {variable}_is_dict:r*z($[^a-zA-Z]|[^a-zA-Z0-9])rWz{}[{}] must be objectzif "{}" in {variable}_keys:z{variable}_keys.remove("{}")z#{variable}__{0} = {variable}["{1}"]z{}__{}z{}.{}T)rfNrzelse: {variable}["{}"] = {})rƒr^Úcreate_variable_keysrZr%rqrprbr rrrr]rergrhr0rt)rJÚkeyZprop_definitionZkey_namerOrOrPrG¼s" z(CodeGeneratorDraft04.generate_propertiesc Csê| ¡| d¡Î| ¡x*|jd ¡D]\}}t |¡|j|<q,W| d¡„x||jd ¡D]j\}}| dt|ƒ¡L| d¡| d¡WdQRX|j |d  |j ¡d   |j |j ¡d d WdQRXqdWWdQRXWdQRXdS) a4 Means object with defined keys as patterns. .. code-block:: python { 'patternProperties': { '^x': {'type': 'number'}, }, } Valid object is containing key starting with a 'x' and value any number. zif {variable}_is_dict:r+z9for {variable}_key, {variable}_val in {variable}.items():z-if REGEX_PATTERNS[{}].search({variable}_key):z%if {variable}_key in {variable}_keys:z&{variable}_keys.remove({variable}_key)Nz{}_valz {}.{{{}_key}}T)rf) rƒr^r„rZr%rqrrrsrtrgrr]rh)rJrrKrOrOrPrHÝs    z0CodeGeneratorDraft04.generate_pattern_propertiesc Csâ| ¡| d¡Æ| ¡|jd}|dks6|ikr:dS|r°t|j di¡ ¡ƒ}| d¡J| d|¡2| d¡| |d  |j ¡d  |j |j ¡¡WdQRXWdQRXn$| d ¡|j d dd WdQRXWdQRXdS)aŸ Means object with keys with values defined by definition. .. code-block:: python { 'properties': { 'key': {'type': 'number'}, } 'additionalProperties': {'type': 'string'}, } Valid object is containing key called 'key' and it's value any number and any other key with any string. zif {variable}_is_dict:r,TNr*z&for {variable}_key in {variable}_keys:zif {variable}_key not in {}:z1{variable}_value = {variable}.get({variable}_key)z{}_valuez {}.{{{}_key}}zif {variable}_keys:z;{name} must not contain "+str({variable}_keys)+" properties)rY) rƒr^r„rZrcrzÚkeysrgrr]rhr_)rJZadd_prop_definitionZproperties_keysrOrOrPrIüs"     ( z3CodeGeneratorDraft04.generate_additional_propertiesc Cs | ¡| d¡îd}xÔ|jd ¡D]Â\}}|gks(|dkrBq(d}| d| |¡¡Œ|dkrt|jd|ddnlt|tƒrÊx`|D]@}| d| |¡¡$|jd | |¡| |¡ddWd QRXq„Wn|j||j |j dd Wd QRXq(W|rü| d ¡Wd QRXd S) aþ Means when object has property, it needs to have also other property. .. code-block:: python { 'dependencies': { 'bar': ['foo'], }, } Valid object is containing only foo, both bar and foo or none of them, but not object with only bar. Since draft 06 definition can be boolean or empty array. True and empty array means nothing, False means that key cannot be there at all. zif {variable}_is_dict:Tr)Fzif "{}" in {variable}:z{} in {name} must not be there)rYzif "{}" not in {variable}:z#{name} missing dependency {} for {}N)rfÚpass) rƒr^rZr%rer_rbrcrgr]rh)rJZis_emptyr…ÚvaluesÚvaluerOrOrPrF s"   .$z*CodeGeneratorDraft04.generate_dependencies)!Ú__name__Ú __module__Ú __qualname__rwr.ÚpropertyrQr2r3r4r5r6r7r8r9r:r;rvr<r=r>r?r@rArBrCrDrErGrHrIrFÚ __classcell__rOrO)rNrPrsB  !    <   !$r) r}rqÚ exceptionsrÚ generatorrrrSrrrorrOrOrOrPÚs