B t1`g@sddlmZmZmZddlZddlZddlZddlZddlm Z m Z ddl m Z ddl m Z ddl mZddl mZdd lmZdd l mZmZmZmZdd dZGdddeZddZddZddZdS))absolute_importdivisionunicode_literalsN)chainislice)compat)util)tags)handlers)json) numeric_types string_typesPY3PY2TFc CsD|pt}|p(t||||||| | | | | d }|j|j||d||dS)aReturn a JSON formatted representation of value, a Python object. :param unpicklable: If set to False then the output will not contain the information necessary to turn the JSON data back into Python objects, but a simpler JSON stream is produced. :param max_depth: If set to a non-negative integer then jsonpickle will not recurse deeper than 'max_depth' steps into the object. Anything deeper than 'max_depth' is represented using a Python repr() of the object. :param make_refs: If set to False jsonpickle's referencing support is disabled. Objects that are id()-identical won't be preserved across encode()/decode(), but the resulting JSON stream will be conceptually simpler. jsonpickle detects cyclical objects and will break the cycle by calling repr() instead of recursing when make_refs is set False. :param keys: If set to True then jsonpickle will encode non-string dictionary keys instead of coercing them into strings via `repr()`. This is typically what you want if you need to support Integer or objects as dictionary keys. :param numeric_keys: Only use this option if the backend supports integer dict keys natively. This flag tells jsonpickle to leave numeric keys as-is rather than conforming them to json-friendly strings. Using ``keys=True`` is the typical solution for integer keys, so only use this if you have a specific use case where you want to allow the backend to handle serialization of numeric dict keys. :param warn: If set to True then jsonpickle will warn when it returns None for an object which it cannot pickle (e.g. file descriptors). :param max_iter: If set to a non-negative integer then jsonpickle will consume at most `max_iter` items when pickling iterators. :param use_decimal: If set to True jsonpickle will allow Decimal instances to pass-through, with the assumption that the simplejson backend will be used in `use_decimal` mode. In order to use this mode you will need to configure simplejson:: jsonpickle.set_encoder_options('simplejson', use_decimal=True, sort_keys=True) jsonpickle.set_decoder_options('simplejson', use_decimal=True) jsonpickle.set_preferred_backend('simplejson') NOTE: A side-effect of the above settings is that float values will be converted to Decimal when converting to json. :param use_base85: If possible, use base85 to encode binary data. Base85 bloats binary data by 1/4 as opposed to base64, which expands it by 1/3. This argument is ignored on Python 2 because it doesn't support it. :param fail_safe: If set to a function exceptions are ignored when pickling and if a exception happens the function is called and the return value is used as the value for the object that caused the error :param indent: When `indent` is a non-negative integer, then JSON array elements and object members will be pretty-printed with that indent level. An indent level of 0 will only insert newlines. ``None`` is the most compact representation. Since the default item separator is ``(', ', ': ')``, the output might include trailing whitespace when ``indent`` is specified. You can use ``separators=(',', ': ')`` to avoid this. This value is passed directly to the active JSON backend library and not used by jsonpickle directly. :param separators: If ``separators`` is an ``(item_separator, dict_separator)`` tuple then it will be used instead of the default ``(', ', ': ')`` separators. ``(',', ':')`` is the most compact JSON representation. This value is passed directly to the active JSON backend library and not used by jsonpickle directly. >>> encode('my string') == '"my string"' True >>> encode(36) == '36' True >>> encode({'foo': True}) == '{"foo": true}' True >>> encode({'foo': [1, 2, [3, 4]]}, max_depth=1) '{"foo": "[1, 2, [3, 4]]"}' ) unpicklable make_refskeysbackend max_depthwarnmax_iter numeric_keys use_decimal use_base85 fail_safe)reset)indent separators)r Picklerencodeflatten)valuerrrrrrrcontextrrrrrrrr$6/tmp/pip-unpacked-wheel-wy5q9vwy/jsonpickle/pickler.pyr s\r c @seZdZd>ddZddZdd Zd d Zd d ZddZddZ d?ddZ ddZ ddZ ddZ ddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd@d*d+Zd,d-Zd.d/Zd0d1Zd2d3Zd4d5Zd6d7Zd8d9Zd:d;Zd>> p = Pickler() >>> p.flatten('hello world') == 'hello world' True >>> p.flatten(49) 49 >>> p.flatten(350.0) 350.0 >>> p.flatten(True) True >>> p.flatten(False) False >>> r = p.flatten(None) >>> r is None True >>> p.flatten(False) False >>> p.flatten([1, 2, 3, 4]) [1, 2, 3, 4] >>> p.flatten((1,2,))[tags.TUPLE] [1, 2] >>> p.flatten({'key': 'value'}) == {'key': 'value'} True )r_flatten)r2r8rr$r$r%r!szPickler.flattencCs\|jr|jr||}n@y|jt|}Wn,tk rV||}|jt|<YnX|S)N)rr _flatten_implr-r6KeyError)r2r8resultr$r$r%r?s  zPickler._flattencCsltrt|tjr||St|tkr0||St|tj ksP|j rTt|t j rT|S| |||S)N)r isinstancetypesFileType _flatten_filetypebytes_flatten_bytestringr Z PRIMITIVESr,decimalDecimalr4r5 _flatten_obj)r2r8r$r$r%r@ s   zPickler._flatten_implcCs |j|jkS)N)r'r()r2r$r$r% _max_reachedszPickler._max_reachedc Cs|j||}yDt||j||j}|r2t}n ||}|dkrR||dS||St t fk r}z|Wdd}~XYn<t k r}z|j dkr|n | |SWdd}~XYnXdS)N) r*appendrM _in_cycler)rrepr_get_flattener_pickle_warningKeyboardInterrupt SystemExit Exceptionr)r2r8 max_reachedin_cycleZ flatten_funcer$r$r%rL"s"    zPickler._flatten_objcsfdd|DS)Ncsg|]}|qSr$)r?).0v)r2r$r% ?sz)Pickler._list_recurse..r$)r2r8r$)r2r% _list_recurse>szPickler._list_recursecst|ttfkrB|r2t|tkr,jSjSjSnVt|tt fkrjj s^jSfddSt |rzj St |rtSt |rjS|dS)Ncs*t|tkrtjntjfdd|DiS)Ncsg|]}|qSr$)r?)rYrZ)r2r$r%r[Rsz...)rGtupler TUPLEZSET)r8)r2r$r%Osz(Pickler._get_flattener..)rGlistdictr<r\_flatten_dict_objr4r>r]setrr Z is_object_ref_obj_instanceis_type _mktyperefZis_module_function_flatten_functionrR)r2r8r$)r2r%rQAs"      zPickler._get_flattenercCs\|jr$||r||S||S|}t||j|d}|rDdS||||SdS)z.Reference an existing object or flatten if newFN)rr<_flatten_obj_instancer>rMrOr))r2r8rVrWr$r$r%rdbs    zPickler._ref_obj_instancecCstst|tjstdS)z+ Special case file objects N)rrCrDrEAssertionError)r2r8r$r$r%rFwszPickler._flatten_filecCs4tr$y |dStk r"YnX|j||iS)Nzutf-8)rdecodeUnicodeDecodeErrorr.r0)r2r8r$r$r%rI~s  zPickler._flatten_bytestringcCs`i}t|d}t|d}| o&t|d}t|d}t|d}t|d}t|\} } t|d} |rp|j} nt|} t| } t| t| }|dk r|j r| |t j <|| ||Sd}|j r| r| sy | }Wntk rYnXn,| r y|d }Wntk rYnX|rt|try@t|d }tjt|}x|D]}t||}||SWWntk rYnXn|rt|}d t|}|r|dg|7}t|d d ddkrt j|d <|\}}}}}|rt|drt|dst|tr|dr.t|d|d<|drHt|d|d<tt|j|}t|d}x&|d kr||dkr|d8}qfW|d|d|t j <|S|r$t!|s$|j r| |t j <|rtt|j|"|t j#<|r |s ||$|t j%<|r$||&|t j'<| rdy |(}Wn tk rV|)|dSX|*||St!|r|j rdj+|j,d|t j-<n t./|}|St0|r|1|||St2|r|3||St4|rtt|jt5||j6|t j7<|S|r6t2|r|3||St|dd|1|j8|S|rH|9||S|rR|S|)|dS)z?Recursively flatten an instance and return a json-friendly dict __class____dict__ __slots____getnewargs____getnewargs_ex____getinitargs__ __getstate__N.r__name__ __newobj__ __setstate__rz {name}/{name})name_):hasattrr Z has_method has_reducerlrGimportable_namer r=rr ZOBJECTr! __reduce__ TypeError __reduce_ex__rCritersplitsysmodulesnextgetattrr?rAr`r7NEWOBJrar]mapREDUCEZ is_modulerpZ NEWARGSEXroZNEWARGSrqZINITARGSrrrR _getstateformatrvZREPRrustrZis_dictionary_subclassrbZis_sequence_subclass_flatten_sequence_objZ is_iteratorrr+ZITERATORrm_flatten_newstyle_with_slots)r2r8dataZ has_classZhas_dictZ has_slotsZhas_getnewargsZhas_getnewargs_exZhas_getinitargsrZ has_reduce_exZ has_getstatecls class_namehandlerZ reduce_valZvarpathZcurmodmodnameZ rv_as_listZ insufficiencyfargsstate listitems dictitemsZ reduce_args last_indexr$r$r%rhs                                     zPickler._flatten_obj_instancecCs |jrtjt|i}nd}|S)N)rr ZFUNCTIONr r)r2r8rr$r$r%rg+szPickler._flatten_functionc Cs&|dkr|}|jrl|j}x"t|D]\}}||||q(W|j}xNt|D]\}}||||qRWn*|j}x"t|D]\}}||||q~Wt|drt|j r|j }t |rt |}n(| |r| t|}n ||}||d<t|dr"|jr"i}||j|||d<|S)z8Recursively call flatten() and return json-friendly dictNdefault_factoryrm)rlr_flatten_string_key_value_pairr items"_flatten_non_string_key_value_pair_flatten_key_value_pairr~callablerrerfr<rhr Z CloneFactoryr>rrbrm) r2r8rr!krZfactoryr"Z dict_datar$r$r%rb3s2    zPickler._flatten_dict_objc CsR|j}d}xB|D]:}yt||}||||Wntk rDwYnXd}qW|S)NFT)rrAttributeError)r2r8attrsrr!okrr"r$r$r%_flatten_obj_attrsfs  zPickler._flatten_obj_attrscCsJdd|jD}||t||sFddt|D}|||||S)zAReturn a json-friendly dict for new-style objects with __slots__.cSsg|]}tt|dtqS)rn)_wrap_string_slotrr])rYrr$r$r%r[vsz8Pickler._flatten_newstyle_with_slots..cSs$g|]}|ds|ds|qS)__) startswithendswith)rYxr$r$r%r[|s)rlmrorrdir)r2r8rZallslotsrr$r$r%rss z$Pickler._flatten_newstyle_with_slotscCsvt||s|S|dkrd}|jr.t|tr.n6t|tsdy t|}Wntk rbt |}YnX| |||<|S)z7Flatten a key/value pair into the passed-in dictionary.Nnull) r is_picklablerrCr rrPrUrrr?)r2rrZrr$r$r%rs   zPickler._flatten_key_value_paircCs<t||s|S|jr8t|ts8||}||||<|S)z'Flatten only non-string key/value pairs)r rrrCr _escape_keyr?)r2rrZrr$r$r%rs   z*Pickler._flatten_non_string_key_value_paircCst||s|S|jr.)r~rbrmrr ZSEQ)r2r8rr"r$)r2r%rs  zPickler._flatten_sequence_objc Cstjt|dd||j|jdS)NFT)rrr#rr)r rr rr)r2rr$r$r%rszPickler._escape_keycCs$||}|jr||tj<n|}|S)N)r?rr ZSTATE)r2r8rrr$r$r%rs   zPickler._getstatecCs|jrd|}t|dS)Nz/jsonpickle cannot pickle %r: replaced with None)rwarnings)r2r8msgr$r$r%rRszPickler._pickle_warning) TTNNFFNFFFN)T)N) rv __module__ __qualname__r3rr4r5r;r<r>r!r?r@rMrLr\rQrdrFrIrhrgrbrrrrrrrrrRr$r$r$r%rsP "     !& 3    rcCs.|s| o,t||ko,t| o,t| S)z>Detect cyclic structures that would lead to infinite recursion)r6r Z is_primitiveZis_enum)r8objsrVrr$r$r%rOs rOcCstjt|iS)zxReturn a typeref dictionary >>> _mktyperef(AssertionError) == {'py/type': 'builtins.AssertionError'} True )r ZTYPEr r)r8r$r$r%rfsrfcCst|tr|fS|S)z0Converts __slots__ = 'a' into __slots__ = ('a',))rCr)stringr$r$r%rs r)TTFNTNFNNFFFNNN) __future__rrrrJrrrD itertoolsrrrwrr r r rr r rrrr objectrrOrfrr$r$r$r%sD      _X