Guest User

json_generator_vmprof_line

a guest
Jun 27th, 2019
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 185.10 KB | None | 0 0
  1. Total hits: 329 s
  2. File: json_generator.py
  3. Function: <module> at line 11
  4.  
  5. Line #     Hits   % Hits  Line Contents
  6. =======================================
  7.     11                    """
  8.    12
  9.    13                    import json
  10.    14                    import pprint
  11.    15                    fname = "/Users/300041709/code/self/wtfpython/README.md"
  12.    16                    examples = []
  13.    17
  14.    18        6      1.8  import yappi
  15.    19
  16.    20                    #yappi.start()
  17.    21
  18.    22                    # The globals
  19.    23                    current_example = 1
  20.    24                    sequence_num = 1
  21.    25                    current_section_name = ""
  22.    26
  23.    27
  24.    28                    STATEMENT_PREFIXES = ["...", ">>> ", "$ "]
  25.    29
  26.    30                    #@profile
  27.    31                    def generate_code_block(statements, output):
  28.    32                        global sequence_num
  29.    33                        result = {
  30.    34                            "type": "code",
  31.    35                            "sequence_num": sequence_num,
  32.    36                            "statements": statements,
  33.    37                            "output": output
  34.    38                        }
  35.    39                        sequence_num += 1
  36.    40                        return result
  37.    41
  38.    42
  39.    43                    def generate_markdown_block(lines):
  40.    44                        global sequence_num
  41.    45                        result = {
  42.    46                            "type": "markdown",
  43.    47                            "sequence_num": sequence_num,
  44.    48                            "value": lines
  45.    49                        }
  46.    50                        sequence_num += 1
  47.    51                        return result
  48.    52
  49.    53                    def is_interactive_statement(line):
  50.    54                        for prefix in STATEMENT_PREFIXES:
  51.    55                            if line.startswith(prefix):
  52.    56                                return True
  53.    57                        return False
  54.    58
  55.    59                    #@profile
  56.    60                    def parse_example_parts(lines, example_title_line):
  57.    61                        parts = {
  58.    62                            "build_up": [],
  59.    63                            "explanation": []
  60.    64                        }
  61.    65                        content = []
  62.    66                        statements_so_far = []
  63.    67                        output_so_far = []
  64.    68                        next_line = example_title_line
  65.    69                        # store build_up till an H4 (explanation) is encountered
  66.    70                        while not next_line.startswith("#### "):
  67.     71                            # Watching out for the snippets
  68.     72                            if next_line.startswith("```"):
  69.    73                                # It's a snippet, whatever found until now is text
  70.    74                                is_interactive = False
  71.    75                                if content:
  72.    76                                    parts["build_up"].append(generate_markdown_block(content))
  73.    77                                    content = []
  74.    78
  75.    79                                next_line = next(lines)
  76.    80
  77.    81                                while not next_line.startswith("```"):
  78.     82                                    if is_interactive_statement(next_line):
  79.     83                                        is_interactive = True
  80.     84                                        if (output_so_far):
  81.     85                                            parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  82.     86                                            statements_so_far, output_so_far = [], []
  83.     87                                        statements_so_far.append(next_line)
  84.     88                                    else:
  85.     89                                        # can be either output or normal code
  86.     90                                        if is_interactive:
  87.     91                                            output_so_far.append(next_line)
  88.     92                                        else:
  89.     93                                            statements_so_far.append(next_line)
  90.     94                                    next_line = next(lines)
  91.     95
  92.     96                                # Snippet is over
  93.     97                                parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  94.     98                                statements_so_far, output_so_far = [], []
  95.     99                                next_line = next(lines)
  96.    100                            else:
  97.    101                                # It's a text, go on.
  98.    102                                content.append(next_line)
  99.    103                                next_line = next(lines)
  100.    104
  101.    105                        # Explanation encountered, save any content till now (if any)
  102.    106                        if content:
  103.    107                            parts["build_up"].append(generate_markdown_block(content))
  104.    108
  105.    109                        # Reset stuff
  106.    110                        content = []
  107.    111                        statements_so_far, output_so_far = [], []
  108.    112
  109.    113                        # store lines again until --- or another H3 is encountered
  110.    114                        while not (next_line.startswith("---") or
  111.    115                                   next_line.startswith("### ")):
  112.    116                            if next_line.startswith("```"):
  113.   117                                # It's a snippet, whatever found until now is text
  114.   118                                is_interactive = False
  115.   119                                if content:
  116.   120                                    parts["build_up"].append(generate_markdown_block(content))
  117.   121                                    content = []
  118.   122
  119.   123                                next_line = next(lines)
  120.   124
  121.   125                                while not next_line.startswith("```"):
  122.    126                                    if is_interactive_statement(next_line):
  123.    127                                        is_interactive = True
  124.    128                                        if (output_so_far):
  125.    129                                            parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  126.    130                                            statements_so_far, output_so_far = [], []
  127.    131                                        statements_so_far.append(next_line)
  128.    132                                    else:
  129.    133                                        # can be either output or normal code
  130.    134                                        if is_interactive:
  131.    135                                            output_so_far.append(next_line)
  132.    136                                        else:
  133.    137                                            statements_so_far.append(next_line)
  134.    138                                    next_line = next(lines)
  135.    139
  136.    140                                # Snippet is over
  137.    141                                parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  138.    142                                statements_so_far, output_so_far = [], []
  139.    143                                next_line = next(lines)
  140.    144                            else:
  141.    145                                # It's a text, go on.
  142.    146                                content.append(next_line)
  143.    147                                next_line = next(lines)
  144.    148
  145.    149                        # All done
  146.    150                        if content:
  147.    151                            parts["explanation"].append(generate_markdown_block(content))
  148.    152
  149.    153                        return next_line, parts
  150.    154
  151.    155                    def remove_from_beginning(tokens, line):
  152.    156                        for token in tokens:
  153.    157                            if line.startswith(token):
  154.    158                                line = line.replace(token, "")
  155.    159                        return line
  156.    160
  157.    161
  158.    162                    def inspect_and_sanitize_code_lines(lines):
  159.    163                        tokens_to_remove = STATEMENT_PREFIXES
  160.    164                        result = []
  161.    165                        is_print_present = False
  162.    166                        for line in lines:
  163.    167                            line = remove_from_beginning(tokens_to_remove, line)
  164.    168                            if line.startswith("print ") or line.startswith("print("):
  165.    169                                is_print_present = True
  166.    170                            result.append(line)
  167.    171                        return is_print_present, result
  168.    172
  169.    173                    def convert_to_cells(cell_contents):
  170.    174                        cells = []
  171.    175                        for stuff in cell_contents:
  172.    176                            if stuff["type"] == "markdown":
  173.    177                                # todo add metadata later
  174.    178                                cells.append(
  175.    179                                    {
  176.    180                                        "cell_type": "markdown",
  177.    181                                        "metadata": {},
  178.    182                                        "source": stuff["value"]
  179.    183                                    }
  180.    184                                )
  181.    185                            elif stuff["type"] == "code":
  182.    186                                is_print_present, sanitized_code = inspect_and_sanitize_code_lines(stuff["statements"])
  183.    187                                if is_print_present:
  184.    188                                    cells.append(
  185.    189                                        {
  186.    190                                            "cell_type": "code",
  187.    191                                            "metadata": {
  188.    192                                                "collapsed": True
  189.    193                                            },
  190.    194                                            "execution_count": None,
  191.    195                                            "outputs": [{
  192.    196                                                "name": "stdout",
  193.    197                                                "output_type": "stream",
  194.    198                                                "text": stuff["output"]
  195.    199                                            }],
  196.    200                                            "source": sanitized_code
  197.    201                                        }
  198.    202                                    )
  199.    203                                else:
  200.    204                                    cells.append(
  201.    205                                        {
  202.    206                                            "cell_type": "code",
  203.    207                                            "execution_count": None,
  204.    208                                            "metadata": {
  205.    209                                                "collapsed": True
  206.    210                                            },
  207.    211                                            "outputs": [{
  208.    212                                                "data": {
  209.    213                                                    "text/plain": stuff["output"]
  210.    214                                                },
  211.    215                                                "output_type": "execute_result",
  212.    216                                                "metadata": {},
  213.    217                                                "execution_count": None
  214.    218                                            }],
  215.    219                                            "source": sanitized_code
  216.    220                                        }
  217.    221                                    )
  218.    222
  219.    223                        return cells
  220.    224
  221.    225
  222.    226                    def convert_to_notebook(parsed_json):
  223.    227                        result = {
  224.    228                            "cells": [],
  225.    229                            "metadata": {},
  226.    230                            "nbformat": 4,
  227.    231                            "nbformat_minor": 2
  228.    232                        }
  229.    233                        for example in parsed_json:
  230.    234                            parts = example["parts"]
  231.    235                            build_up = parts.get("build_up")
  232.    236                            explanation = parts.get("explanation")
  233.    237                            notebook_path = "test.ipynb"
  234.    238
  235.    239                            if(build_up):
  236.    240                                result["cells"] += convert_to_cells(build_up)
  237.    241
  238.    242                            if(explanation):
  239.    243                                result["cells"] += convert_to_cells(explanation)
  240.    244
  241.    245                        pprint.pprint(result, indent=2)
  242.    246                        with open(notebook_path, "w") as f:
  243.    247                            json.dump(result, f)
  244.    248
  245.    249
  246.    250
  247.    251                    with open(fname, 'r+', encoding="utf-8") as f:
  248.    252        2      0.6      lines = iter(f.readlines())
  249.    253                        line = next(lines)
  250.    254                        result = []
  251.    255                        try:
  252.    256                            while True:
  253.    257                                if line.startswith("## "):
  254.    258                                    # A section is encountered
  255.    259                                    current_section_name = line.replace("## ", "").strip()
  256.    260                                    section_text = []
  257.    261                                    line = next(lines)
  258.    262                                    # Until a new section is encountered
  259.    263                                    while not (line.startswith("## " )):
  260.    264                                        # check if it's a H3
  261.    265                                        if line.startswith("### "):
  262.    266                                            # An example is encountered
  263.    267                                            title = line.replace("### ", "")
  264.    268                                            example_details = {
  265.    269                                                "id": current_example,
  266.    270                                                "title": line.replace("### ", ""),
  267.    271                                                "section": current_section_name
  268.    272                                            }
  269.    273        2      0.6                          line, example_details["parts"] = parse_example_parts(lines, line)
  270.    274                                            result.append(example_details)
  271.    275                                            current_example += 1
  272.    276                                        else:
  273.    277                                            section_text.append(line)
  274.    278                                            line = next(lines)
  275.    279                                else:
  276.    280                                    line = next(lines)
  277.    281
  278.    282                        except StopIteration:
  279.    283      149     45.3          pprint.pprint(result, indent=2)
  280.    284      170     51.7          convert_to_notebook(result)
  281.  
  282. Total hits: 14 s
  283.  
  284. Could not find file <frozen importlib._bootstrap>
  285. Are you sure you are running this program from the same directory
  286. that you ran the profiler from?
  287. Continuing without the function's contents.
  288.  
  289. Line #     Hits   % Hits  Line Contents
  290. =======================================
  291.   978
  292.   979
  293.   980
  294.   981
  295.   982
  296.   983       14    100.0
  297.  
  298. Total hits: 14 s
  299.  
  300. Could not find file <frozen importlib._bootstrap>
  301. Are you sure you are running this program from the same directory
  302. that you ran the profiler from?
  303. Continuing without the function's contents.
  304.  
  305. Line #     Hits   % Hits  Line Contents
  306. =======================================
  307.    948
  308.    949
  309.    950
  310.    951
  311.    952
  312.    953
  313.    954
  314.    955
  315.    956
  316.    957
  317.    958
  318.    959
  319.    960
  320.    961
  321.    962
  322.    963        3     21.4
  323.    964
  324.    965
  325.    966
  326.    967       11     78.6
  327.  
  328. Total hits: 3 s
  329.  
  330. Could not find file <frozen importlib._bootstrap>
  331. Are you sure you are running this program from the same directory
  332. that you ran the profiler from?
  333. Continuing without the function's contents.
  334.  
  335. Line #     Hits   % Hits  Line Contents
  336. =======================================
  337.   882
  338.   883
  339.   884
  340.   885
  341.   886
  342.   887
  343.   888
  344.   889
  345.   890
  346.   891
  347.   892
  348.   893
  349.   894
  350.   895
  351.   896
  352.   897
  353.   898
  354.   899
  355.   900
  356.   901
  357.   902
  358.   903
  359.   904
  360.   905
  361.   906        3    100.0
  362.  
  363. Total hits: 3 s
  364.  
  365. Could not find file <frozen importlib._bootstrap_external>
  366. Are you sure you are running this program from the same directory
  367. that you ran the profiler from?
  368. Continuing without the function's contents.
  369.  
  370. Line #     Hits   % Hits  Line Contents
  371. =======================================
  372.   1272
  373.   1273
  374.   1274
  375.   1275
  376.   1276
  377.   1277
  378.   1278
  379.   1279
  380.   1280        3    100.0
  381.  
  382. Total hits: 3 s
  383.  
  384. Could not find file <frozen importlib._bootstrap_external>
  385. Are you sure you are running this program from the same directory
  386. that you ran the profiler from?
  387. Continuing without the function's contents.
  388.  
  389. Line #     Hits   % Hits  Line Contents
  390. =======================================
  391.  1240
  392.  1241
  393.  1242
  394.  1243
  395.  1244
  396.  1245
  397.  1246
  398.  1247
  399.  1248
  400.  1249        2     66.7
  401.  1250
  402.  1251
  403.  1252        1     33.3
  404.  
  405. Total hits: 2 s
  406.  
  407. Could not find file <frozen importlib._bootstrap_external>
  408. Are you sure you are running this program from the same directory
  409. that you ran the profiler from?
  410. Continuing without the function's contents.
  411.  
  412. Line #     Hits   % Hits  Line Contents
  413. =======================================
  414.   1203
  415.   1204
  416.   1205
  417.   1206
  418.   1207
  419.   1208
  420.   1209
  421.   1210
  422.   1211
  423.   1212
  424.   1213        2    100.0
  425.  
  426. Total hits: 11 s
  427.  
  428. Could not find file <frozen importlib._bootstrap>
  429. Are you sure you are running this program from the same directory
  430. that you ran the profiler from?
  431. Continuing without the function's contents.
  432.  
  433. Line #     Hits   % Hits  Line Contents
  434. =======================================
  435.   663
  436.   664
  437.   665
  438.   666
  439.   667
  440.   668
  441.   669
  442.   670        2     18.2
  443.   671
  444.   672
  445.   673
  446.   674
  447.   675
  448.   676
  449.   677        9     81.8
  450.  
  451. Total hits: 9 s
  452.  
  453. Could not find file <frozen importlib._bootstrap_external>
  454. Are you sure you are running this program from the same directory
  455. that you ran the profiler from?
  456. Continuing without the function's contents.
  457.  
  458. Line #     Hits   % Hits  Line Contents
  459. =======================================
  460.    722
  461.    723
  462.    724        1     11.1
  463.    725
  464.    726
  465.    727
  466.    728        8     88.9
  467.  
  468. Total hits: 10 s
  469.  
  470. Could not find file <frozen importlib._bootstrap>
  471. Are you sure you are running this program from the same directory
  472. that you ran the profiler from?
  473. Continuing without the function's contents.
  474.  
  475. Line #     Hits   % Hits  Line Contents
  476. =======================================
  477.   211
  478.   212
  479.   213
  480.   214
  481.   215
  482.   216
  483.   217
  484.   218
  485.   219       10    100.0
  486.  
  487. Total hits: 5 s
  488. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/site-packages/yappi.py
  489. Function: <module> at line 6
  490.  
  491. Line #     Hits   % Hits  Line Contents
  492. =======================================
  493.     6                    """
  494.     7                    import os
  495.     8                    import sys
  496.     9        1     20.0  import _yappi
  497.    10        4     80.0  import pickle
  498.    11                    import threading
  499.    12                    try:
  500.    13                        from thread import get_ident        # Python 2
  501.    14                    except ImportError:
  502.    15                        from threading import get_ident     # Python 3
  503.    16
  504.    17                    from contextlib import contextmanager
  505.    18
  506.    19                    class YappiError(Exception): pass
  507.    20
  508.    21                    __all__ = ['start', 'stop', 'get_func_stats', 'get_thread_stats', 'clear_stats', 'is_running',
  509.    22                               'get_clock_time', 'get_clock_type', 'set_clock_type', 'get_clock_info', 'get_mem_usage']
  510.    23
  511.    24                    LINESEP = os.linesep
  512.    25                    COLUMN_GAP = 2
  513.    26                    YPICKLE_PROTOCOL = 2
  514.    27
  515.    28                    COLUMNS_FUNCSTATS = ["name", "ncall", "ttot", "tsub", "tavg"]
  516.    29                    COLUMNS_THREADSTATS = ["name", "id", "tid", "ttot", "scnt"]
  517.    30                    SORT_TYPES_FUNCSTATS = {"name":0, "callcount":3, "totaltime":6, "subtime":7, "avgtime":10,
  518.    31                                            "ncall":3, "ttot":6, "tsub":7, "tavg":10}
  519.    32                    SORT_TYPES_CHILDFUNCSTATS = {"name":10, "callcount":1, "totaltime":3, "subtime":4, "avgtime":5,
  520.    33                                            "ncall":1, "ttot":3, "tsub":4, "tavg":5}
  521.    34                    SORT_TYPES_THREADSTATS = {"name":0, "id":1, "tid":2, "totaltime":3, "schedcount":4,
  522.    35                                              "ttot":3, "scnt":4}
  523.    36                    SORT_ORDERS = {"ascending":0, "asc":0, "descending":1, "desc":1}
  524.    37                    DEFAULT_SORT_TYPE = "totaltime"
  525.    38                    DEFAULT_SORT_ORDER = "desc"
  526.    39
  527.    40                    CLOCK_TYPES = {"WALL":0, "CPU":1}
  528.    41
  529.    42                    def _validate_sorttype(sort_type, list):
  530.    43                        sort_type = sort_type.lower()
  531.    44                        if sort_type not in list:
  532.    45                            raise YappiError("Invalid SortType parameter: '%s'" % (sort_type))
  533.    46                        return sort_type
  534.    47
  535.    48                    def _validate_sortorder(sort_order):
  536.    49                        sort_order = sort_order.lower()
  537.    50                        if sort_order not in SORT_ORDERS:
  538.    51                            raise YappiError("Invalid SortOrder parameter: '%s'" % (sort_order))
  539.    52                        return sort_order
  540.    53
  541.    54                    def _validate_columns(name, list):
  542.    55                        name = name.lower()
  543.    56                        if name not in list:
  544.    57                            raise YappiError("Invalid Column name: '%s'" % (name))
  545.    58
  546.    59
  547.    60                    def _ctx_name_callback():
  548.    61                        """
  549.    62                        We don't use threading.current_thread() becuase it will deadlock if
  550.     63                        called when profiling threading._active_limbo_lock.acquire().
  551.     64                        See: #Issue48.
  552.     65                        """
  553.    66                        try:
  554.    67                            current_thread = threading._active[get_ident()]
  555.    68                            return current_thread.__class__.__name__
  556.    69                        except KeyError:
  557.    70                            # Threads may not be registered yet in first few profile callbacks.
  558.    71                            return None
  559.    72
  560.    73                    def _profile_thread_callback(frame, event, arg):
  561.    74                        """
  562.     75                        _profile_thread_callback will only be called once per-thread. _yappi will detect
  563.     76                        the new thread and changes the profilefunc param of the ThreadState
  564.     77                        structure. This is an internal function please don't mess with it.
  565.    78                        """
  566.    79                        _yappi._profile_event(frame, event, arg)
  567.    80
  568.    81                    def _fft(x, COL_SIZE=8):
  569.    82                        """
  570.    83                        function to prettify time columns in stats.
  571.    84                        """
  572.    85                        _rprecision = 6
  573.    86                        while(_rprecision > 0):
  574.    87                            _fmt = "%0." + "%d" % (_rprecision) + "f"
  575.    88                            s = _fmt % (x)
  576.    89                            if len(s) <= COL_SIZE:
  577.    90                                break
  578.    91                            _rprecision -= 1
  579.    92                        return s
  580.    93
  581.    94                    def _func_fullname(builtin, module, lineno, name):
  582.    95                        if builtin:
  583.    96                            return "%s.%s" % (module, name)
  584.    97                        else:
  585.    98                            return "%s:%d %s" % (module, lineno, name)
  586.    99
  587.   100                    """
  588.   101                    Converts our internal yappi's YFuncStats (YSTAT type) to PSTAT. So there are
  589.    102                    some differences between the statistics parameters. The PSTAT format is as following:
  590.    103
  591.    104                    PSTAT expects a dict. entry as following:
  592.    105
  593.    106                    stats[("mod_name", line_no, "func_name")] = \
  594.    107                        ( total_call_count, actual_call_count, total_time, cumulative_time,
  595.    108                        {
  596.    109                            ("mod_name", line_no, "func_name") :
  597.    110                            (total_call_count, --> total count caller called the callee
  598.    111                            actual_call_count, --> total count caller called the callee - (recursive calls)
  599.    112                            total_time,        --> total time caller spent _only_ for this function (not further subcalls)
  600.    113                            cumulative_time)   --> total time caller spent for this function
  601.    114                        } --> callers dict
  602.    115                        )
  603.    116
  604.    117                    Note that in PSTAT the total time spent in the function is called as cumulative_time and
  605.    118                    the time spent _only_ in the function as total_time. From Yappi's perspective, this means:
  606.   119
  607.   120                    total_time (inline time) = tsub
  608.   121                    cumulative_time (total time) = ttot
  609.   122
  610.   123                    Other than that we hold called functions in a profile entry as named 'children'. On the
  611.   124                    other hand, PSTAT expects to have a dict of callers of the function. So we also need to
  612.   125                    convert children to callers dict.
  613.   126                    From Python Docs:
  614.   127                    '''
  615.    128                    With cProfile, each caller is preceded by three numbers:
  616.    129                    the number of times this specific call was made, and the total
  617.    130                    and cumulative times spent in the current function while it was
  618.    131                    invoked by this specific caller.
  619.    132                    '''
  620.   133                    That means we only need to assign ChildFuncStat's ttot/tsub values to the caller
  621.    134                    properly. Docs indicate that when b() is called by a() pstat holds the total time
  622.    135                    of b() when called by a, just like yappi.
  623.    136
  624.    137                    PSTAT only expects to have the above dict to be saved.
  625.    138                    """
  626.   139                    def convert2pstats(stats):
  627.   140                        from collections import defaultdict
  628.   141                        """
  629.    142                        Converts the internal stat type of yappi(which is returned by a call to YFuncStats.get())
  630.    143                        as pstats object.
  631.    144                        """
  632.   145                        if not isinstance(stats, YFuncStats):
  633.   146                            raise YappiError("Source stats must be derived from YFuncStats.")
  634.   147                        import pstats
  635.   148                        class _PStatHolder:
  636.   149                            def __init__(self, d):
  637.   150                                self.stats = d
  638.   151                            def create_stats(self):
  639.   152                                pass
  640.   153                        def pstat_id(fs):
  641.   154                            return (fs.module, fs.lineno, fs.name)
  642.   155
  643.   156                        _pdict = {}
  644.   157
  645.   158                        # convert callees to callers
  646.   159                        _callers = defaultdict(dict)
  647.   160                        for fs in stats:
  648.   161                            for ct in fs.children:
  649.   162                                _callers[ct][pstat_id(fs)] = (ct.ncall, ct.nactualcall, ct.tsub ,ct.ttot)
  650.   163
  651.   164                        # populate the pstat dict.
  652.   165                        for fs in stats:
  653.   166                            _pdict[pstat_id(fs)] = (fs.ncall, fs.nactualcall, fs.tsub, fs.ttot, _callers[fs], )
  654.   167
  655.   168                        return pstats.Stats(_PStatHolder(_pdict))
  656.   169
  657.   170                    def profile(clock_type="cpu", profile_builtins=False, return_callback=None):
  658.   171                        """
  659.    172                        A profile decorator that can be used to profile a single call.
  660.    173
  661.    174                        We need to clear_stats() on entry/exit of the function unfortunately.
  662.    175                        As yappi is a per-interpreter resource, we cannot simply resume profiling
  663.    176                        session upon exit of the function, that is because we _may_ simply change
  664.    177                        start() params which may differ from the paused session that may cause instable
  665.    178                        results. So, if you use a decorator, then global profiling may return bogus
  666.    179                        results or no results at all.
  667.    180                        """
  668.   181                        def _profile_dec(func):
  669.   182                            def wrapper(*args, **kwargs):
  670.   183                                if func._rec_level == 0:
  671.   184                                    clear_stats()
  672.   185                                    set_clock_type(clock_type)
  673.   186                                    start(profile_builtins, profile_threads=False)
  674.   187                                func._rec_level += 1
  675.   188                                try:
  676.   189                                    return func(*args, **kwargs)
  677.   190                                finally:
  678.   191                                    func._rec_level -= 1
  679.   192                                    # only show profile information when recursion level of the
  680.   193                                    # function becomes 0. Otherwise, we are in the middle of a
  681.   194                                    # recursive call tree and not finished yet.
  682.   195                                    if func._rec_level == 0:
  683.   196                                        try:
  684.   197                                            stop()
  685.   198                                            if return_callback is None:
  686.   199                                                sys.stdout.write(LINESEP)
  687.   200                                                sys.stdout.write("Executed in %s %s clock seconds" %
  688.   201                                                    (_fft(get_thread_stats()[0].ttot), clock_type.upper()))
  689.   202                                                sys.stdout.write(LINESEP)
  690.   203                                                get_func_stats().print_all()
  691.   204                                            else:
  692.   205                                                return_callback(func, get_func_stats())
  693.   206                                        finally:
  694.   207                                            clear_stats()
  695.   208                            func._rec_level = 0
  696.   209                            return wrapper
  697.   210                        return _profile_dec
  698.   211
  699.   212                    class StatString(object):
  700.   213                        """
  701.    214                        Class to prettify/trim a profile result column.
  702.    215                        """
  703.   216                        _TRAIL_DOT = ".."
  704.   217                        _LEFT = 1
  705.   218                        _RIGHT = 2
  706.   219
  707.   220                        def __init__(self, s):
  708.   221                            self._s = str(s)
  709.   222
  710.   223                        def _trim(self, length, direction):
  711.   224                            if (len(self._s) > length):
  712.   225                                if direction == self._LEFT:
  713.   226                                    self._s = self._s[-length:]
  714.   227                                    return self._TRAIL_DOT + self._s[len(self._TRAIL_DOT):]
  715.   228                                elif direction == self._RIGHT:
  716.   229                                    self._s = self._s[:length]
  717.   230                                    return self._s[:-len(self._TRAIL_DOT)] + self._TRAIL_DOT
  718.   231                            return self._s + (" " * (length - len(self._s)))
  719.   232
  720.   233                        def ltrim(self, length):
  721.   234                            return self._trim(length, self._LEFT)
  722.   235
  723.   236                        def rtrim(self, length):
  724.   237                            return self._trim(length, self._RIGHT)
  725.   238
  726.   239                    class YStat(dict):
  727.   240                        """
  728.    241                        Class to hold a profile result line in a dict object, which all items can also be accessed as
  729.    242                        instance attributes where their attribute name is the given key. Mimicked NamedTuples.
  730.    243                        """
  731.   244                        _KEYS = {}
  732.   245
  733.   246                        def __init__(self, values):
  734.   247                            super(YStat, self).__init__()
  735.   248
  736.   249                            for key,i in self._KEYS.items():
  737.   250                                setattr(self, key, values[i])
  738.   251
  739.   252                        def __setattr__(self, name, value):
  740.   253                            self[self._KEYS[name]] = value
  741.   254                            super(YStat, self).__setattr__(name, value)
  742.   255
  743.   256                    class YFuncStat(YStat):
  744.   257                        """
  745.    258                        Class holding information for function stats.
  746.    259                        """
  747.   260                        _KEYS = {'name':0, 'module':1, 'lineno':2, 'ncall':3, 'nactualcall':4, 'builtin':5, 'ttot':6, 'tsub':7, 'index':8, 'children':9, 'ctx_id':10, 'tavg':11, 'full_name':12}
  748.   261
  749.   262                        def __eq__(self, other):
  750.   263                            if other is None:
  751.   264                                return False
  752.   265                            return self.full_name == other.full_name
  753.   266
  754.   267                        def __ne__(self, other):
  755.   268                            return not self == other
  756.   269
  757.   270                        def __add__(self, other):
  758.   271
  759.   272                            # do not merge if merging the same instance
  760.   273                            if self is other:
  761.   274                                return self
  762.   275
  763.   276                            self.ncall += other.ncall
  764.   277                            self.nactualcall += other.nactualcall
  765.   278                            self.ttot += other.ttot
  766.   279                            self.tsub += other.tsub
  767.   280                            self.tavg = self.ttot / self.ncall
  768.   281                            for other_child_stat in other.children:
  769.   282                                # all children point to a valid entry, and we shall have merged previous entries by here.
  770.   283                                self.children.append(other_child_stat)
  771.   284                            return self
  772.   285
  773.   286                        def __hash__(self):
  774.   287                            return hash(self.full_name)
  775.   288
  776.   289                        def is_recursive(self):
  777.   290                            # we have a known bug where call_leave not called for some thread functions(run() especially)
  778.   291                            # in that case ncalls will be updated in call_enter, however nactualcall will not. This is for
  779.   292                            # checking that case.
  780.   293                            if self.nactualcall == 0:
  781.   294                                return False
  782.   295                            return self.ncall != self.nactualcall
  783.   296
  784.   297                        def strip_dirs(self):
  785.   298                            self.module = os.path.basename(self.module)
  786.   299                            self.full_name = _func_fullname(self.builtin, self.module, self.lineno,
  787.   300                                self.name)
  788.   301                            return self
  789.   302
  790.   303                        def _print(self, out, columns):
  791.   304                            for x in sorted(columns.keys()):
  792.   305                                title, size = columns[x]
  793.   306                                if title == "name":
  794.   307                                    out.write(StatString(self.full_name).ltrim(size))
  795.   308                                    out.write(" " * COLUMN_GAP)
  796.   309                                elif title == "ncall":
  797.   310                                    if self.is_recursive():
  798.   311                                        out.write(StatString("%d/%d" % (self.ncall,
  799.   312                                                self.nactualcall)).rtrim(size))
  800.   313                                    else:
  801.   314                                        out.write(StatString(self.ncall).rtrim(size))
  802.   315                                    out.write(" " * COLUMN_GAP)
  803.   316                                elif title == "tsub":
  804.   317                                    out.write(StatString(_fft(self.tsub, size)).rtrim(size))
  805.   318                                    out.write(" " * COLUMN_GAP)
  806.   319                                elif title == "ttot":
  807.   320                                    out.write(StatString(_fft(self.ttot, size)).rtrim(size))
  808.   321                                    out.write(" " * COLUMN_GAP)
  809.   322                                elif title == "tavg":
  810.   323                                    out.write(StatString(_fft(self.tavg, size)).rtrim(size))
  811.   324                            out.write(LINESEP)
  812.   325
  813.   326                    class YChildFuncStat(YFuncStat):
  814.   327                        """
  815.    328                        Class holding information for children function stats.
  816.    329                        """
  817.   330                        _KEYS = {'index':0, 'ncall':1, 'nactualcall':2, 'ttot':3, 'tsub':4, 'tavg':5, 'builtin':6, 'full_name':7, 'module':8, 'lineno':9, 'name':10}
  818.   331
  819.   332                        def __add__(self, other):
  820.   333                            if other is None:
  821.   334                                return self
  822.   335                            self.nactualcall += other.nactualcall
  823.   336                            self.ncall += other.ncall
  824.   337                            self.ttot += other.ttot
  825.   338                            self.tsub += other.tsub
  826.   339                            self.tavg = self.ttot / self.ncall
  827.   340                            return self
  828.   341                    class YThreadStat(YStat):
  829.   342                        """
  830.    343                        Class holding information for thread stats.
  831.    344                        """
  832.   345                        _KEYS = {'name':0, 'id':1, 'tid':2, 'ttot':3,'sched_count':4,}
  833.   346
  834.   347                        def __eq__(self, other):
  835.   348                            if other is None:
  836.   349                                return False
  837.   350                            return self.id == other.id
  838.   351
  839.   352                        def __ne__(self, other):
  840.   353                            return not self == other
  841.   354
  842.   355                        def __hash__(self, *args, **kwargs):
  843.   356                            return hash(self.id)
  844.   357
  845.   358                        def _print(self, out, columns):
  846.   359                            for x in sorted(columns.keys()):
  847.   360                                title, size = columns[x]
  848.   361                                if title == "name":
  849.   362                                    out.write(StatString(self.name).ltrim(size))
  850.   363                                    out.write(" " * COLUMN_GAP)
  851.   364                                elif title == "id":
  852.   365                                    out.write(StatString(self.id).rtrim(size))
  853.   366                                    out.write(" " * COLUMN_GAP)
  854.   367                                elif title == "tid":
  855.   368                                    out.write(StatString(self.tid).rtrim(size))
  856.   369                                    out.write(" " * COLUMN_GAP)
  857.   370                                elif title == "ttot":
  858.   371                                    out.write(StatString(_fft(self.ttot, size)).rtrim(size))
  859.   372                                    out.write(" " * COLUMN_GAP)
  860.   373                                elif title == "scnt":
  861.   374                                    out.write(StatString(self.sched_count).rtrim(size))
  862.   375                            out.write(LINESEP)
  863.   376
  864.   377                    class YStats(object):
  865.   378                        """
  866.    379                        Main Stats class where we collect the information from _yappi and apply the user filters.
  867.  
  868. Total hits: 2 s
  869.  
  870. Could not find file <frozen importlib._bootstrap>
  871. Are you sure you are running this program from the same directory
  872. that you ran the profiler from?
  873. Continuing without the function's contents.
  874.  
  875. Line #     Hits   % Hits  Line Contents
  876. =======================================
  877.   576
  878.   577
  879.   578
  880.   579
  881.   580
  882.   581
  883.   582
  884.   583        2    100.0
  885.  
  886. Total hits: 2 s
  887.  
  888. Could not find file <frozen importlib._bootstrap_external>
  889. Are you sure you are running this program from the same directory
  890. that you ran the profiler from?
  891. Continuing without the function's contents.
  892.  
  893. Line #     Hits   % Hits  Line Contents
  894. =======================================
  895.   1040
  896.   1041
  897.   1042
  898.   1043        2    100.0
  899.  
  900. Total hits: 1 s
  901.  
  902. Could not find file <frozen importlib._bootstrap_external>
  903. Are you sure you are running this program from the same directory
  904. that you ran the profiler from?
  905. Continuing without the function's contents.
  906.  
  907. Line #     Hits   % Hits  Line Contents
  908. =======================================
  909.   793
  910.   794
  911.   795
  912.   796
  913.   797
  914.   798
  915.   799
  916.   800
  917.   801
  918.   802
  919.   803
  920.   804
  921.   805
  922.   806
  923.   807
  924.   808
  925.   809
  926.   810
  927.   811
  928.   812
  929.   813
  930.   814
  931.   815
  932.   816
  933.   817
  934.   818        1    100.0
  935.  
  936. Total hits: 1 s
  937.  
  938. Could not find file <frozen importlib._bootstrap_external>
  939. Are you sure you are running this program from the same directory
  940. that you ran the profiler from?
  941. Continuing without the function's contents.
  942.  
  943. Line #     Hits   % Hits  Line Contents
  944. =======================================
  945.    914
  946.    915
  947.    916        1    100.0
  948.  
  949. Total hits: 3 s
  950. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pickle.py
  951. Function: <module> at line 24
  952.  
  953. Line #     Hits   % Hits  Line Contents
  954. =======================================
  955.     24                    """
  956.    25
  957.    26                    from types import FunctionType
  958.    27                    from copyreg import dispatch_table
  959.    28                    from copyreg import _extension_registry, _inverted_registry, _extension_cache
  960.    29                    from itertools import islice
  961.    30                    from functools import partial
  962.    31                    import sys
  963.    32                    from sys import maxsize
  964.    33                    from struct import pack, unpack
  965.    34                    import re
  966.    35                    import io
  967.    36                    import codecs
  968.    37        1     33.3  import _compat_pickle
  969.    38
  970.    39                    __all__ = ["PickleError", "PicklingError", "UnpicklingError", "Pickler",
  971.    40                               "Unpickler", "dump", "dumps", "load", "loads"]
  972.    41
  973.    42                    # Shortcut for use in isinstance testing
  974.    43                    bytes_types = (bytes, bytearray)
  975.    44
  976.    45                    # These are purely informational; no code uses these.
  977.    46                    format_version = "4.0"                  # File format version we write
  978.    47                    compatible_formats = ["1.0",            # Original protocol 0
  979.    48                                          "1.1",            # Protocol 0 with INST added
  980.    49                                          "1.2",            # Original protocol 1
  981.    50                                          "1.3",            # Protocol 1 with BINFLOAT added
  982.    51                                          "2.0",            # Protocol 2
  983.    52                                          "3.0",            # Protocol 3
  984.    53                                          "4.0",            # Protocol 4
  985.    54                                          ]                 # Old format versions we can read
  986.    55
  987.    56                    # This is the highest protocol number we know how to read.
  988.    57                    HIGHEST_PROTOCOL = 4
  989.    58
  990.    59                    # The protocol we write by default.  May be less than HIGHEST_PROTOCOL.
  991.    60                    # We intentionally write a protocol that Python 2.x cannot read;
  992.    61                    # there are too many issues with that.
  993.    62                    DEFAULT_PROTOCOL = 3
  994.    63
  995.    64                    class PickleError(Exception):
  996.    65                        """A common base class for the other pickling exceptions."""
  997.    66                        pass
  998.    67
  999.    68                    class PicklingError(PickleError):
  1000.    69                        """This exception is raised when an unpicklable object is passed to the
  1001.     70                        dump() method.
  1002.     71
  1003.     72                        """
  1004.    73                        pass
  1005.    74
  1006.    75                    class UnpicklingError(PickleError):
  1007.    76                        """This exception is raised when there is a problem unpickling an object,
  1008.     77                        such as a security violation.
  1009.     78
  1010.     79                        Note that other exceptions may also be raised during unpickling, including
  1011.     80                        (but not necessarily limited to) AttributeError, EOFError, ImportError,
  1012.     81                        and IndexError.
  1013.     82
  1014.     83                        """
  1015.    84                        pass
  1016.    85
  1017.    86                    # An instance of _Stop is raised by Unpickler.load_stop() in response to
  1018.    87                    # the STOP opcode, passing the object that is the result of unpickling.
  1019.    88                    class _Stop(Exception):
  1020.    89                        def __init__(self, value):
  1021.    90                            self.value = value
  1022.    91
  1023.    92                    # Jython has PyStringMap; it's a dict subclass with string keys
  1024.    93                    try:
  1025.    94                        from org.python.core import PyStringMap
  1026.    95                    except ImportError:
  1027.    96                        PyStringMap = None
  1028.    97
  1029.    98                    # Pickle opcodes.  See pickletools.py for extensive docs.  The listing
  1030.    99                    # here is in kind-of alphabetical order of 1-character pickle code.
  1031.   100                    # pickletools groups them by purpose.
  1032.   101
  1033.   102                    MARK           = b'('   # push special markobject on stack
  1034.   103                    STOP           = b'.'   # every pickle ends with STOP
  1035.   104                    POP            = b'0'   # discard topmost stack item
  1036.   105                    POP_MARK       = b'1'   # discard stack top through topmost markobject
  1037.   106                    DUP            = b'2'   # duplicate top stack item
  1038.   107                    FLOAT          = b'F'   # push float object; decimal string argument
  1039.   108                    INT            = b'I'   # push integer or bool; decimal string argument
  1040.   109                    BININT         = b'J'   # push four-byte signed int
  1041.   110                    BININT1        = b'K'   # push 1-byte unsigned int
  1042.   111                    LONG           = b'L'   # push long; decimal string argument
  1043.   112                    BININT2        = b'M'   # push 2-byte unsigned int
  1044.   113                    NONE           = b'N'   # push None
  1045.   114                    PERSID         = b'P'   # push persistent object; id is taken from string arg
  1046.   115                    BINPERSID      = b'Q'   #  "       "         "  ;  "  "   "     "  stack
  1047.    116                    REDUCE         = b'R'   # apply callable to argtuple, both on stack
  1048.    117                    STRING         = b'S'   # push string; NL-terminated string argument
  1049.    118                    BINSTRING      = b'T'   # push string; counted binary string argument
  1050.    119                    SHORT_BINSTRING= b'U'   #  "     "   ;    "      "       "      " < 256 bytes
  1051.    120                    UNICODE        = b'V'   # push Unicode string; raw-unicode-escaped'd argument
  1052.    121                    BINUNICODE     = b'X'   #   "     "       "  ; counted UTF-8 string argument
  1053.    122                    APPEND         = b'a'   # append stack top to list below it
  1054.    123                    BUILD          = b'b'   # call __setstate__ or __dict__.update()
  1055.    124                    GLOBAL         = b'c'   # push self.find_class(modname, name); 2 string args
  1056.    125                    DICT           = b'd'   # build a dict from stack items
  1057.    126                    EMPTY_DICT     = b'}'   # push empty dict
  1058.    127                    APPENDS        = b'e'   # extend list on stack by topmost stack slice
  1059.    128                    GET            = b'g'   # push item from memo on stack; index is string arg
  1060.    129                    BINGET         = b'h'   #   "    "    "    "   "   "  ;   "    " 1-byte arg
  1061.    130                    INST           = b'i'   # build & push class instance
  1062.    131                    LONG_BINGET    = b'j'   # push item from memo on stack; index is 4-byte arg
  1063.    132                    LIST           = b'l'   # build list from topmost stack items
  1064.    133                    EMPTY_LIST     = b']'   # push empty list
  1065.    134                    OBJ            = b'o'   # build & push class instance
  1066.    135                    PUT            = b'p'   # store stack top in memo; index is string arg
  1067.    136                    BINPUT         = b'q'   #   "     "    "   "   " ;   "    " 1-byte arg
  1068.    137                    LONG_BINPUT    = b'r'   #   "     "    "   "   " ;   "    " 4-byte arg
  1069.    138                    SETITEM        = b's'   # add key+value pair to dict
  1070.    139                    TUPLE          = b't'   # build tuple from topmost stack items
  1071.    140                    EMPTY_TUPLE    = b')'   # push empty tuple
  1072.    141                    SETITEMS       = b'u'   # modify dict by adding topmost key+value pairs
  1073.    142                    BINFLOAT       = b'G'   # push float; arg is 8-byte float encoding
  1074.    143
  1075.    144                    TRUE           = b'I01\n'  # not an opcode; see INT docs in pickletools.py
  1076.    145                    FALSE          = b'I00\n'  # not an opcode; see INT docs in pickletools.py
  1077.    146
  1078.    147                    # Protocol 2
  1079.    148
  1080.    149                    PROTO          = b'\x80'  # identify pickle protocol
  1081.    150                    NEWOBJ         = b'\x81'  # build object by applying cls.__new__ to argtuple
  1082.    151                    EXT1           = b'\x82'  # push object from extension registry; 1-byte index
  1083.    152                    EXT2           = b'\x83'  # ditto, but 2-byte index
  1084.    153                    EXT4           = b'\x84'  # ditto, but 4-byte index
  1085.    154                    TUPLE1         = b'\x85'  # build 1-tuple from stack top
  1086.    155                    TUPLE2         = b'\x86'  # build 2-tuple from two topmost stack items
  1087.    156                    TUPLE3         = b'\x87'  # build 3-tuple from three topmost stack items
  1088.    157                    NEWTRUE        = b'\x88'  # push True
  1089.    158                    NEWFALSE       = b'\x89'  # push False
  1090.    159                    LONG1          = b'\x8a'  # push long from < 256 bytes
  1091.    160                    LONG4          = b'\x8b'  # push really big long
  1092.    161
  1093.    162                    _tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3]
  1094.    163
  1095.    164                    # Protocol 3 (Python 3.x)
  1096.    165
  1097.    166                    BINBYTES       = b'B'   # push bytes; counted binary string argument
  1098.    167                    SHORT_BINBYTES = b'C'   #  "     "   ;    "      "       "      " < 256 bytes
  1099.    168
  1100.    169                    # Protocol 4
  1101.    170                    SHORT_BINUNICODE = b'\x8c'  # push short string; UTF-8 length < 256 bytes
  1102.    171                    BINUNICODE8      = b'\x8d'  # push very long string
  1103.    172                    BINBYTES8        = b'\x8e'  # push very long bytes string
  1104.    173                    EMPTY_SET        = b'\x8f'  # push empty set on the stack
  1105.    174                    ADDITEMS         = b'\x90'  # modify set by adding topmost stack items
  1106.    175                    FROZENSET        = b'\x91'  # build frozenset from topmost stack items
  1107.    176                    NEWOBJ_EX        = b'\x92'  # like NEWOBJ but work with keyword only arguments
  1108.    177                    STACK_GLOBAL     = b'\x93'  # same as GLOBAL but using names on the stacks
  1109.    178                    MEMOIZE          = b'\x94'  # store top of the stack in memo
  1110.    179                    FRAME            = b'\x95'  # indicate the beginning of a new frame
  1111.    180
  1112.    181                    __all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$", x)])
  1113.    182
  1114.    183
  1115.    184                    class _Framer:
  1116.    185
  1117.    186                        _FRAME_SIZE_MIN = 4
  1118.    187                        _FRAME_SIZE_TARGET = 64 * 1024
  1119.    188
  1120.    189                        def __init__(self, file_write):
  1121.    190                            self.file_write = file_write
  1122.    191                            self.current_frame = None
  1123.    192
  1124.    193                        def start_framing(self):
  1125.    194                            self.current_frame = io.BytesIO()
  1126.    195
  1127.    196                        def end_framing(self):
  1128.    197                            if self.current_frame and self.current_frame.tell() > 0:
  1129.    198                                self.commit_frame(force=True)
  1130.    199                                self.current_frame = None
  1131.    200
  1132.    201                        def commit_frame(self, force=False):
  1133.    202                            if self.current_frame:
  1134.    203                                f = self.current_frame
  1135.    204                                if f.tell() >= self._FRAME_SIZE_TARGET or force:
  1136.    205                                    data = f.getbuffer()
  1137.    206                                    write = self.file_write
  1138.    207                                    if len(data) >= self._FRAME_SIZE_MIN:
  1139.    208                                        # Issue a single call to the write method of the underlying
  1140.    209                                        # file object for the frame opcode with the size of the
  1141.    210                                        # frame. The concatenation is expected to be less expensive
  1142.    211                                        # than issuing an additional call to write.
  1143.    212                                        write(FRAME + pack("<Q", len(data)))
  1144.    213
  1145.    214                                    # Issue a separate call to write to append the frame
  1146.    215                                    # contents without concatenation to the above to avoid a
  1147.    216                                    # memory copy.
  1148.    217                                    write(data)
  1149.    218
  1150.    219                                    # Start the new frame with a new io.BytesIO instance so that
  1151.    220                                    # the file object can have delayed access to the previous frame
  1152.    221                                    # contents via an unreleased memoryview of the previous
  1153.    222                                    # io.BytesIO instance.
  1154.    223                                    self.current_frame = io.BytesIO()
  1155.    224
  1156.    225                        def write(self, data):
  1157.    226                            if self.current_frame:
  1158.    227                                return self.current_frame.write(data)
  1159.    228                            else:
  1160.    229                                return self.file_write(data)
  1161.    230
  1162.    231                        def write_large_bytes(self, header, payload):
  1163.    232                            write = self.file_write
  1164.    233                            if self.current_frame:
  1165.    234                                # Terminate the current frame and flush it to the file.
  1166.    235                                self.commit_frame(force=True)
  1167.    236
  1168.    237                            # Perform direct write of the header and payload of the large binary
  1169.    238                            # object. Be careful not to concatenate the header and the payload
  1170.    239                            # prior to calling 'write' as we do not want to allocate a large
  1171.    240                            # temporary bytes object.
  1172.    241                            # We intentionally do not insert a protocol 4 frame opcode to make
  1173.    242                            # it possible to optimize file.read calls in the loader.
  1174.    243                            write(header)
  1175.    244                            write(payload)
  1176.    245
  1177.    246
  1178.    247                    class _Unframer:
  1179.    248
  1180.    249                        def __init__(self, file_read, file_readline, file_tell=None):
  1181.    250                            self.file_read = file_read
  1182.    251                            self.file_readline = file_readline
  1183.    252                            self.current_frame = None
  1184.    253
  1185.    254                        def read(self, n):
  1186.    255                            if self.current_frame:
  1187.    256                                data = self.current_frame.read(n)
  1188.    257                                if not data and n != 0:
  1189.    258                                    self.current_frame = None
  1190.    259                                    return self.file_read(n)
  1191.    260                                if len(data) < n:
  1192.    261                                    raise UnpicklingError(
  1193.    262                                        "pickle exhausted before end of frame")
  1194.    263                                return data
  1195.    264                            else:
  1196.    265                                return self.file_read(n)
  1197.    266
  1198.    267                        def readline(self):
  1199.    268                            if self.current_frame:
  1200.    269                                data = self.current_frame.readline()
  1201.    270                                if not data:
  1202.    271                                    self.current_frame = None
  1203.    272                                    return self.file_readline()
  1204.    273                                if data[-1] != b'\n'[0]:
  1205.    274                                    raise UnpicklingError(
  1206.    275                                        "pickle exhausted before end of frame")
  1207.    276                                return data
  1208.    277                            else:
  1209.    278                                return self.file_readline()
  1210.    279
  1211.    280                        def load_frame(self, frame_size):
  1212.    281                            if self.current_frame and self.current_frame.read() != b'':
  1213.    282                                raise UnpicklingError(
  1214.    283                                    "beginning of a new frame before end of current frame")
  1215.    284                            self.current_frame = io.BytesIO(self.file_read(frame_size))
  1216.    285
  1217.    286
  1218.    287                    # Tools used for pickling.
  1219.    288
  1220.    289                    def _getattribute(obj, name):
  1221.    290                        for subpath in name.split('.'):
  1222.    291                            if subpath == '<locals>':
  1223.    292                                raise AttributeError("Can't get local attribute {!r} on {!r}"
  1224.    293                                                     .format(name, obj))
  1225.    294                            try:
  1226.    295                                parent = obj
  1227.    296                                obj = getattr(obj, subpath)
  1228.    297                            except AttributeError:
  1229.    298                                raise AttributeError("Can't get attribute {!r} on {!r}"
  1230.    299                                                     .format(name, obj)) from None
  1231.    300                        return obj, parent
  1232.    301
  1233.    302                    def whichmodule(obj, name):
  1234.    303                        """Find the module an object belong to."""
  1235.    304                        module_name = getattr(obj, '__module__', None)
  1236.    305                        if module_name is not None:
  1237.    306                            return module_name
  1238.    307                        # Protect the iteration by using a list copy of sys.modules against dynamic
  1239.    308                        # modules that trigger imports of other modules upon calls to getattr.
  1240.    309                        for module_name, module in list(sys.modules.items()):
  1241.    310                            if module_name == '__main__' or module is None:
  1242.    311                                continue
  1243.    312                            try:
  1244.    313                                if _getattribute(module, name)[0] is obj:
  1245.    314                                    return module_name
  1246.    315                            except AttributeError:
  1247.    316                                pass
  1248.    317                        return '__main__'
  1249.    318
  1250.    319                    def encode_long(x):
  1251.    320                        r"""Encode a long to a two's complement little-endian binary string.
  1252.   321                        Note that 0 is a special case, returning an empty string, to save a
  1253.   322                        byte in the LONG1 pickling context.
  1254.   323
  1255.   324                        >>> encode_long(0)
  1256.   325                        b''
  1257.   326                        >>> encode_long(255)
  1258.   327                        b'\xff\x00'
  1259.   328                        >>> encode_long(32767)
  1260.   329                        b'\xff\x7f'
  1261.   330                        >>> encode_long(-256)
  1262.   331                        b'\x00\xff'
  1263.   332                        >>> encode_long(-32768)
  1264.   333                        b'\x00\x80'
  1265.   334                        >>> encode_long(-128)
  1266.   335                        b'\x80'
  1267.   336                        >>> encode_long(127)
  1268.   337                        b'\x7f'
  1269.   338                        >>>
  1270.   339                        """
  1271.    340                        if x == 0:
  1272.    341                            return b''
  1273.    342                        nbytes = (x.bit_length() >> 3) + 1
  1274.    343                        result = x.to_bytes(nbytes, byteorder='little', signed=True)
  1275.    344                        if x < 0 and nbytes > 1:
  1276.    345                            if result[-1] == 0xff and (result[-2] & 0x80) != 0:
  1277.    346                                result = result[:-1]
  1278.    347                        return result
  1279.    348
  1280.    349                    def decode_long(data):
  1281.    350                        r"""Decode a long from a two's complement little-endian binary string.
  1282.   351
  1283.   352                        >>> decode_long(b'')
  1284.   353                        0
  1285.   354                        >>> decode_long(b"\xff\x00")
  1286.   355                        255
  1287.   356                        >>> decode_long(b"\xff\x7f")
  1288.   357                        32767
  1289.   358                        >>> decode_long(b"\x00\xff")
  1290.   359                        -256
  1291.   360                        >>> decode_long(b"\x00\x80")
  1292.   361                        -32768
  1293.   362                        >>> decode_long(b"\x80")
  1294.   363                        -128
  1295.   364                        >>> decode_long(b"\x7f")
  1296.   365                        127
  1297.   366                        """
  1298.    367                        return int.from_bytes(data, byteorder='little', signed=True)
  1299.    368
  1300.    369
  1301.    370                    # Pickling machinery
  1302.    371
  1303.    372        1     33.3  class _Pickler:
  1304.    373
  1305.    374                        def __init__(self, file, protocol=None, *, fix_imports=True):
  1306.    375                            """This takes a binary file for writing a pickle data stream.
  1307.   376
  1308.   377                            The optional *protocol* argument tells the pickler to use the
  1309.   378                            given protocol; supported protocols are 0, 1, 2, 3 and 4.  The
  1310.   379                            default protocol is 3; a backward-incompatible protocol designed
  1311.   380                            for Python 3.
  1312.   381
  1313.   382                            Specifying a negative protocol version selects the highest
  1314.   383                            protocol version supported.  The higher the protocol used, the
  1315.   384                            more recent the version of Python needed to read the pickle
  1316.   385                            produced.
  1317.   386
  1318.   387                            The *file* argument must have a write() method that accepts a
  1319.   388                            single bytes argument. It can thus be a file object opened for
  1320.   389                            binary writing, an io.BytesIO instance, or any other custom
  1321.   390                            object that meets this interface.
  1322.   391
  1323.   392                            If *fix_imports* is True and *protocol* is less than 3, pickle
  1324.   393                            will try to map the new Python 3 names to the old module names
  1325.   394                            used in Python 2, so that the pickle data stream is readable
  1326.   395                            with Python 2.
  1327.   396                            """
  1328.    397                            if protocol is None:
  1329.    398                                protocol = DEFAULT_PROTOCOL
  1330.    399                            if protocol < 0:
  1331.    400                                protocol = HIGHEST_PROTOCOL
  1332.    401                            elif not 0 <= protocol <= HIGHEST_PROTOCOL:
  1333.    402                                raise ValueError("pickle protocol must be <= %d" % HIGHEST_PROTOCOL)
  1334.    403                            try:
  1335.    404                                self._file_write = file.write
  1336.    405                            except AttributeError:
  1337.    406                                raise TypeError("file must have a 'write' attribute")
  1338.    407                            self.framer = _Framer(self._file_write)
  1339.    408                            self.write = self.framer.write
  1340.    409                            self._write_large_bytes = self.framer.write_large_bytes
  1341.    410                            self.memo = {}
  1342.    411                            self.proto = int(protocol)
  1343.    412                            self.bin = protocol >= 1
  1344.    413                            self.fast = 0
  1345.    414                            self.fix_imports = fix_imports and protocol < 3
  1346.    415
  1347.    416                        def clear_memo(self):
  1348.    417                            """Clears the pickler's "memo".
  1349.   418
  1350.   419                            The memo is the data structure that remembers which objects the
  1351.   420                            pickler has already seen, so that shared or recursive objects
  1352.   421                            are pickled by reference and not by value.  This method is
  1353.   422                            useful when re-using picklers.
  1354.   423                            """
  1355.    424                            self.memo.clear()
  1356.    425
  1357.    426                        def dump(self, obj):
  1358.    427                            """Write a pickled representation of obj to the open file."""
  1359.    428                            # Check whether Pickler was initialized correctly. This is
  1360.    429                            # only needed to mimic the behavior of _pickle.Pickler.dump().
  1361.    430                            if not hasattr(self, "_file_write"):
  1362.    431                                raise PicklingError("Pickler.__init__() was not called by "
  1363.    432                                                    "%s.__init__()" % (self.__class__.__name__,))
  1364.    433                            if self.proto >= 2:
  1365.    434                                self.write(PROTO + pack("<B", self.proto))
  1366.    435                            if self.proto >= 4:
  1367.    436                                self.framer.start_framing()
  1368.    437                            self.save(obj)
  1369.    438                            self.write(STOP)
  1370.    439                            self.framer.end_framing()
  1371.    440
  1372.    441                        def memoize(self, obj):
  1373.    442                            """Store an object in the memo."""
  1374.    443
  1375.    444                            # The Pickler memo is a dictionary mapping object ids to 2-tuples
  1376.    445                            # that contain the Unpickler memo key and the object being memoized.
  1377.    446                            # The memo key is written to the pickle and will become
  1378.    447                            # the key in the Unpickler's memo.  The object is stored in the
  1379.    448                            # Pickler memo so that transient objects are kept alive during
  1380.    449                            # pickling.
  1381.    450
  1382.    451                            # The use of the Unpickler memo length as the memo key is just a
  1383.    452                            # convention.  The only requirement is that the memo values be unique.
  1384.    453                            # But there appears no advantage to any other scheme, and this
  1385.    454                            # scheme allows the Unpickler memo to be implemented as a plain (but
  1386.    455                            # growable) array, indexed by memo key.
  1387.    456                            if self.fast:
  1388.    457                                return
  1389.    458                            assert id(obj) not in self.memo
  1390.    459                            idx = len(self.memo)
  1391.    460                            self.write(self.put(idx))
  1392.    461                            self.memo[id(obj)] = idx, obj
  1393.    462
  1394.    463                        # Return a PUT (BINPUT, LONG_BINPUT) opcode string, with argument i.
  1395.    464                        def put(self, idx):
  1396.    465                            if self.proto >= 4:
  1397.    466                                return MEMOIZE
  1398.    467                            elif self.bin:
  1399.    468                                if idx < 256:
  1400.    469                                    return BINPUT + pack("<B", idx)
  1401.    470                                else:
  1402.    471                                    return LONG_BINPUT + pack("<I", idx)
  1403.    472                            else:
  1404.    473                                return PUT + repr(idx).encode("ascii") + b'\n'
  1405.    474
  1406.    475                        # Return a GET (BINGET, LONG_BINGET) opcode string, with argument i.
  1407.    476                        def get(self, i):
  1408.    477                            if self.bin:
  1409.    478                                if i < 256:
  1410.    479                                    return BINGET + pack("<B", i)
  1411.    480                                else:
  1412.    481                                    return LONG_BINGET + pack("<I", i)
  1413.    482
  1414.    483                            return GET + repr(i).encode("ascii") + b'\n'
  1415.    484
  1416.    485                        def save(self, obj, save_persistent_id=True):
  1417.    486                            self.framer.commit_frame()
  1418.    487
  1419.    488                            # Check for persistent id (defined by a subclass)
  1420.    489                            pid = self.persistent_id(obj)
  1421.    490                            if pid is not None and save_persistent_id:
  1422.    491                                self.save_pers(pid)
  1423.    492                                return
  1424.    493
  1425.    494                            # Check the memo
  1426.    495                            x = self.memo.get(id(obj))
  1427.    496                            if x is not None:
  1428.    497                                self.write(self.get(x[0]))
  1429.    498                                return
  1430.    499
  1431.    500                            # Check the type dispatch table
  1432.    501                            t = type(obj)
  1433.    502                            f = self.dispatch.get(t)
  1434.    503                            if f is not None:
  1435.    504                                f(self, obj) # Call unbound method with explicit self
  1436.    505                                return
  1437.    506
  1438.    507                            # Check private dispatch table if any, or else copyreg.dispatch_table
  1439.    508                            reduce = getattr(self, 'dispatch_table', dispatch_table).get(t)
  1440.    509                            if reduce is not None:
  1441.    510                                rv = reduce(obj)
  1442.    511                            else:
  1443.    512                                # Check for a class with a custom metaclass; treat as regular class
  1444.    513                                try:
  1445.    514                                    issc = issubclass(t, type)
  1446.    515                                except TypeError: # t is not a class (old Boost; see SF #502085)
  1447.    516                                    issc = False
  1448.    517                                if issc:
  1449.    518                                    self.save_global(obj)
  1450.    519                                    return
  1451.    520
  1452.    521                                # Check for a __reduce_ex__ method, fall back to __reduce__
  1453.    522                                reduce = getattr(obj, "__reduce_ex__", None)
  1454.    523                                if reduce is not None:
  1455.    524                                    rv = reduce(self.proto)
  1456.    525                                else:
  1457.    526                                    reduce = getattr(obj, "__reduce__", None)
  1458.    527                                    if reduce is not None:
  1459.    528                                        rv = reduce()
  1460.    529                                    else:
  1461.    530                                        raise PicklingError("Can't pickle %r object: %r" %
  1462.    531                                                            (t.__name__, obj))
  1463.    532
  1464.    533                            # Check for string returned by reduce(), meaning "save as global"
  1465.    534                            if isinstance(rv, str):
  1466.    535                                self.save_global(obj, rv)
  1467.    536                                return
  1468.    537
  1469.    538                            # Assert that reduce() returned a tuple
  1470.    539                            if not isinstance(rv, tuple):
  1471.    540                                raise PicklingError("%s must return string or tuple" % reduce)
  1472.    541
  1473.    542                            # Assert that it returned an appropriately sized tuple
  1474.    543                            l = len(rv)
  1475.    544                            if not (2 <= l <= 5):
  1476.    545                                raise PicklingError("Tuple returned by %s must have "
  1477.    546                                                    "two to five elements" % reduce)
  1478.    547
  1479.    548                            # Save the reduce() output and finally memoize the object
  1480.    549                            self.save_reduce(obj=obj, *rv)
  1481.    550
  1482.    551                        def persistent_id(self, obj):
  1483.    552                            # This exists so a subclass can override it
  1484.    553                            return None
  1485.    554
  1486.    555                        def save_pers(self, pid):
  1487.    556                            # Save a persistent id reference
  1488.    557                            if self.bin:
  1489.    558                                self.save(pid, save_persistent_id=False)
  1490.    559                                self.write(BINPERSID)
  1491.    560                            else:
  1492.    561                                try:
  1493.    562                                    self.write(PERSID + str(pid).encode("ascii") + b'\n')
  1494.    563                                except UnicodeEncodeError:
  1495.    564                                    raise PicklingError(
  1496.    565                                        "persistent IDs in protocol 0 must be ASCII strings")
  1497.    566
  1498.    567                        def save_reduce(self, func, args, state=None, listitems=None,
  1499.    568                                        dictitems=None, obj=None):
  1500.    569                            # This API is called by some subclasses
  1501.    570
  1502.    571                            if not isinstance(args, tuple):
  1503.    572                                raise PicklingError("args from save_reduce() must be a tuple")
  1504.    573                            if not callable(func):
  1505.    574                                raise PicklingError("func from save_reduce() must be callable")
  1506.    575
  1507.    576                            save = self.save
  1508.    577                            write = self.write
  1509.    578
  1510.    579                            func_name = getattr(func, "__name__", "")
  1511.    580                            if self.proto >= 2 and func_name == "__newobj_ex__":
  1512.    581                                cls, args, kwargs = args
  1513.    582                                if not hasattr(cls, "__new__"):
  1514.    583                                    raise PicklingError("args[0] from {} args has no __new__"
  1515.    584                                                        .format(func_name))
  1516.    585                                if obj is not None and cls is not obj.__class__:
  1517.    586                                    raise PicklingError("args[0] from {} args has the wrong class"
  1518.    587                                                        .format(func_name))
  1519.    588                                if self.proto >= 4:
  1520.    589                                    save(cls)
  1521.    590                                    save(args)
  1522.    591                                    save(kwargs)
  1523.    592                                    write(NEWOBJ_EX)
  1524.    593                                else:
  1525.    594                                    func = partial(cls.__new__, cls, *args, **kwargs)
  1526.    595                                    save(func)
  1527.    596                                    save(())
  1528.    597                                    write(REDUCE)
  1529.    598                            elif self.proto >= 2 and func_name == "__newobj__":
  1530.    599                                # A __reduce__ implementation can direct protocol 2 or newer to
  1531.    600                                # use the more efficient NEWOBJ opcode, while still
  1532.    601                                # allowing protocol 0 and 1 to work normally.  For this to
  1533.    602                                # work, the function returned by __reduce__ should be
  1534.    603                                # called __newobj__, and its first argument should be a
  1535.    604                                # class.  The implementation for __newobj__
  1536.    605                                # should be as follows, although pickle has no way to
  1537.    606                                # verify this:
  1538.    607                                #
  1539.    608                                # def __newobj__(cls, *args):
  1540.    609                                #     return cls.__new__(cls, *args)
  1541.    610                                #
  1542.    611                                # Protocols 0 and 1 will pickle a reference to __newobj__,
  1543.    612                                # while protocol 2 (and above) will pickle a reference to
  1544.    613                                # cls, the remaining args tuple, and the NEWOBJ code,
  1545.    614                                # which calls cls.__new__(cls, *args) at unpickling time
  1546.    615                                # (see load_newobj below).  If __reduce__ returns a
  1547.    616                                # three-tuple, the state from the third tuple item will be
  1548.    617                                # pickled regardless of the protocol, calling __setstate__
  1549.    618                                # at unpickling time (see load_build below).
  1550.    619                                #
  1551.    620                                # Note that no standard __newobj__ implementation exists;
  1552.    621                                # you have to provide your own.  This is to enforce
  1553.    622                                # compatibility with Python 2.2 (pickles written using
  1554.    623                                # protocol 0 or 1 in Python 2.3 should be unpicklable by
  1555.    624                                # Python 2.2).
  1556.    625                                cls = args[0]
  1557.    626                                if not hasattr(cls, "__new__"):
  1558.    627                                    raise PicklingError(
  1559.    628                                        "args[0] from __newobj__ args has no __new__")
  1560.    629                                if obj is not None and cls is not obj.__class__:
  1561.    630                                    raise PicklingError(
  1562.    631                                        "args[0] from __newobj__ args has the wrong class")
  1563.    632                                args = args[1:]
  1564.    633                                save(cls)
  1565.    634                                save(args)
  1566.    635                                write(NEWOBJ)
  1567.    636                            else:
  1568.    637                                save(func)
  1569.    638                                save(args)
  1570.    639                                write(REDUCE)
  1571.    640
  1572.    641                            if obj is not None:
  1573.    642                                # If the object is already in the memo, this means it is
  1574.    643                                # recursive. In this case, throw away everything we put on the
  1575.    644                                # stack, and fetch the object back from the memo.
  1576.    645                                if id(obj) in self.memo:
  1577.    646                                    write(POP + self.get(self.memo[id(obj)][0]))
  1578.    647                                else:
  1579.    648                                    self.memoize(obj)
  1580.    649
  1581.    650                            # More new special cases (that work with older protocols as
  1582.    651                            # well): when __reduce__ returns a tuple with 4 or 5 items,
  1583.    652                            # the 4th and 5th item should be iterators that provide list
  1584.    653                            # items and dict items (as (key, value) tuples), or None.
  1585.    654
  1586.    655                            if listitems is not None:
  1587.    656                                self._batch_appends(listitems)
  1588.    657
  1589.    658                            if dictitems is not None:
  1590.    659                                self._batch_setitems(dictitems)
  1591.    660
  1592.    661                            if state is not None:
  1593.    662                                save(state)
  1594.    663                                write(BUILD)
  1595.    664
  1596.    665                        # Methods below this point are dispatched through the dispatch table
  1597.    666
  1598.    667                        dispatch = {}
  1599.    668
  1600.    669                        def save_none(self, obj):
  1601.    670                            self.write(NONE)
  1602.    671                        dispatch[type(None)] = save_none
  1603.    672
  1604.    673                        def save_bool(self, obj):
  1605.    674                            if self.proto >= 2:
  1606.    675                                self.write(NEWTRUE if obj else NEWFALSE)
  1607.    676                            else:
  1608.    677                                self.write(TRUE if obj else FALSE)
  1609.    678                        dispatch[bool] = save_bool
  1610.    679
  1611.    680                        def save_long(self, obj):
  1612.    681                            if self.bin:
  1613.    682                                # If the int is small enough to fit in a signed 4-byte 2's-comp
  1614.    683                                # format, we can store it more efficiently than the general
  1615.    684                                # case.
  1616.    685                                # First one- and two-byte unsigned ints:
  1617.    686                                if obj >= 0:
  1618.    687                                    if obj <= 0xff:
  1619.    688                                        self.write(BININT1 + pack("<B", obj))
  1620.    689                                        return
  1621.    690                                    if obj <= 0xffff:
  1622.    691                                        self.write(BININT2 + pack("<H", obj))
  1623.    692                                        return
  1624.    693                                # Next check for 4-byte signed ints:
  1625.    694                                if -0x80000000 <= obj <= 0x7fffffff:
  1626.    695                                    self.write(BININT + pack("<i", obj))
  1627.    696                                    return
  1628.    697                            if self.proto >= 2:
  1629.    698                                encoded = encode_long(obj)
  1630.    699                                n = len(encoded)
  1631.    700                                if n < 256:
  1632.    701                                    self.write(LONG1 + pack("<B", n) + encoded)
  1633.    702                                else:
  1634.    703                                    self.write(LONG4 + pack("<i", n) + encoded)
  1635.    704                                return
  1636.    705                            if -0x80000000 <= obj <= 0x7fffffff:
  1637.    706                                self.write(INT + repr(obj).encode("ascii") + b'\n')
  1638.    707                            else:
  1639.    708                                self.write(LONG + repr(obj).encode("ascii") + b'L\n')
  1640.    709                        dispatch[int] = save_long
  1641.    710
  1642.    711                        def save_float(self, obj):
  1643.    712                            if self.bin:
  1644.    713                                self.write(BINFLOAT + pack('>d', obj))
  1645.    714                            else:
  1646.    715                                self.write(FLOAT + repr(obj).encode("ascii") + b'\n')
  1647.    716                        dispatch[float] = save_float
  1648.    717
  1649.    718                        def save_bytes(self, obj):
  1650.    719                            if self.proto < 3:
  1651.    720                                if not obj: # bytes object is empty
  1652.    721                                    self.save_reduce(bytes, (), obj=obj)
  1653.    722                                else:
  1654.    723                                    self.save_reduce(codecs.encode,
  1655.    724                                                     (str(obj, 'latin1'), 'latin1'), obj=obj)
  1656.    725                                return
  1657.    726                            n = len(obj)
  1658.    727                            if n <= 0xff:
  1659.    728                                self.write(SHORT_BINBYTES + pack("<B", n) + obj)
  1660.    729                            elif n > 0xffffffff and self.proto >= 4:
  1661.    730                                self._write_large_bytes(BINBYTES8 + pack("<Q", n), obj)
  1662.    731                            elif n >= self.framer._FRAME_SIZE_TARGET:
  1663.    732                                self._write_large_bytes(BINBYTES + pack("<I", n), obj)
  1664.    733                            else:
  1665.    734                                self.write(BINBYTES + pack("<I", n) + obj)
  1666.    735                            self.memoize(obj)
  1667.    736                        dispatch[bytes] = save_bytes
  1668.    737
  1669.    738                        def save_str(self, obj):
  1670.    739                            if self.bin:
  1671.    740                                encoded = obj.encode('utf-8', 'surrogatepass')
  1672.    741                                n = len(encoded)
  1673.    742                                if n <= 0xff and self.proto >= 4:
  1674.    743                                    self.write(SHORT_BINUNICODE + pack("<B", n) + encoded)
  1675.    744                                elif n > 0xffffffff and self.proto >= 4:
  1676.    745                                    self._write_large_bytes(BINUNICODE8 + pack("<Q", n), encoded)
  1677.    746                                elif n >= self.framer._FRAME_SIZE_TARGET:
  1678.    747                                    self._write_large_bytes(BINUNICODE + pack("<I", n), encoded)
  1679.    748                                else:
  1680.    749                                    self.write(BINUNICODE + pack("<I", n) + encoded)
  1681.    750                            else:
  1682.    751                                obj = obj.replace("\\", "\\u005c")
  1683.   752                                obj = obj.replace("\n", "\\u000a")
  1684.   753                                self.write(UNICODE + obj.encode('raw-unicode-escape') +
  1685.   754                                           b'\n')
  1686.   755                            self.memoize(obj)
  1687.   756                        dispatch[str] = save_str
  1688.   757
  1689.   758                        def save_tuple(self, obj):
  1690.   759                            if not obj: # tuple is empty
  1691.   760                                if self.bin:
  1692.   761                                    self.write(EMPTY_TUPLE)
  1693.   762                                else:
  1694.   763                                    self.write(MARK + TUPLE)
  1695.   764                                return
  1696.   765
  1697.   766                            n = len(obj)
  1698.   767                            save = self.save
  1699.   768                            memo = self.memo
  1700.   769                            if n <= 3 and self.proto >= 2:
  1701.   770                                for element in obj:
  1702.   771                                    save(element)
  1703.   772                                # Subtle.  Same as in the big comment below.
  1704.   773                                if id(obj) in memo:
  1705.   774                                    get = self.get(memo[id(obj)][0])
  1706.   775                                    self.write(POP * n + get)
  1707.   776                                else:
  1708.   777                                    self.write(_tuplesize2code[n])
  1709.   778                                    self.memoize(obj)
  1710.   779                                return
  1711.   780
  1712.   781                            # proto 0 or proto 1 and tuple isn't empty, or proto > 1 and tuple
  1713.   782                            # has more than 3 elements.
  1714.   783                            write = self.write
  1715.   784                            write(MARK)
  1716.   785                            for element in obj:
  1717.   786                                save(element)
  1718.   787
  1719.   788                            if id(obj) in memo:
  1720.   789                                # Subtle.  d was not in memo when we entered save_tuple(), so
  1721.   790                                # the process of saving the tuple's elements must have saved
  1722.   791                                # the tuple itself:  the tuple is recursive.  The proper action
  1723.   792                                # now is to throw away everything we put on the stack, and
  1724.   793                                # simply GET the tuple (it's already constructed).  This check
  1725.   794                                # could have been done in the "for element" loop instead, but
  1726.   795                                # recursive tuples are a rare thing.
  1727.   796                                get = self.get(memo[id(obj)][0])
  1728.   797                                if self.bin:
  1729.   798                                    write(POP_MARK + get)
  1730.   799                                else:   # proto 0 -- POP_MARK not available
  1731.   800                                    write(POP * (n+1) + get)
  1732.   801                                return
  1733.   802
  1734.   803                            # No recursion.
  1735.   804                            write(TUPLE)
  1736.   805                            self.memoize(obj)
  1737.   806
  1738.   807                        dispatch[tuple] = save_tuple
  1739.   808
  1740.   809                        def save_list(self, obj):
  1741.   810                            if self.bin:
  1742.   811                                self.write(EMPTY_LIST)
  1743.   812                            else:   # proto 0 -- can't use EMPTY_LIST
  1744.   813                                self.write(MARK + LIST)
  1745.   814
  1746.   815                            self.memoize(obj)
  1747.   816                            self._batch_appends(obj)
  1748.   817
  1749.   818                        dispatch[list] = save_list
  1750.   819
  1751.   820                        _BATCHSIZE = 1000
  1752.   821
  1753.   822                        def _batch_appends(self, items):
  1754.   823                            # Helper to batch up APPENDS sequences
  1755.   824                            save = self.save
  1756.   825                            write = self.write
  1757.   826
  1758.   827                            if not self.bin:
  1759.   828                                for x in items:
  1760.   829                                    save(x)
  1761.   830                                    write(APPEND)
  1762.   831                                return
  1763.   832
  1764.   833                            it = iter(items)
  1765.   834                            while True:
  1766.   835                                tmp = list(islice(it, self._BATCHSIZE))
  1767.   836                                n = len(tmp)
  1768.   837                                if n > 1:
  1769.   838                                    write(MARK)
  1770.   839                                    for x in tmp:
  1771.   840                                        save(x)
  1772.   841                                    write(APPENDS)
  1773.   842                                elif n:
  1774.   843                                    save(tmp[0])
  1775.   844                                    write(APPEND)
  1776.   845                                # else tmp is empty, and we're done
  1777.   846                                if n < self._BATCHSIZE:
  1778.   847                                    return
  1779.   848
  1780.   849                        def save_dict(self, obj):
  1781.   850                            if self.bin:
  1782.   851                                self.write(EMPTY_DICT)
  1783.   852                            else:   # proto 0 -- can't use EMPTY_DICT
  1784.   853                                self.write(MARK + DICT)
  1785.   854
  1786.   855                            self.memoize(obj)
  1787.   856                            self._batch_setitems(obj.items())
  1788.   857
  1789.   858                        dispatch[dict] = save_dict
  1790.   859                        if PyStringMap is not None:
  1791.   860                            dispatch[PyStringMap] = save_dict
  1792.   861
  1793.   862                        def _batch_setitems(self, items):
  1794.   863                            # Helper to batch up SETITEMS sequences; proto >= 1 only
  1795.   864                            save = self.save
  1796.   865                            write = self.write
  1797.   866
  1798.   867                            if not self.bin:
  1799.   868                                for k, v in items:
  1800.   869                                    save(k)
  1801.   870                                    save(v)
  1802.   871                                    write(SETITEM)
  1803.   872                                return
  1804.   873
  1805.   874                            it = iter(items)
  1806.   875                            while True:
  1807.   876                                tmp = list(islice(it, self._BATCHSIZE))
  1808.   877                                n = len(tmp)
  1809.   878                                if n > 1:
  1810.   879                                    write(MARK)
  1811.   880                                    for k, v in tmp:
  1812.   881                                        save(k)
  1813.   882                                        save(v)
  1814.   883                                    write(SETITEMS)
  1815.   884                                elif n:
  1816.   885                                    k, v = tmp[0]
  1817.   886                                    save(k)
  1818.   887                                    save(v)
  1819.   888                                    write(SETITEM)
  1820.   889                                # else tmp is empty, and we're done
  1821.   890                                if n < self._BATCHSIZE:
  1822.   891                                    return
  1823.   892
  1824.   893                        def save_set(self, obj):
  1825.   894                            save = self.save
  1826.   895                            write = self.write
  1827.   896
  1828.   897                            if self.proto < 4:
  1829.   898                                self.save_reduce(set, (list(obj),), obj=obj)
  1830.   899                                return
  1831.   900
  1832.   901                            write(EMPTY_SET)
  1833.   902                            self.memoize(obj)
  1834.   903
  1835.   904                            it = iter(obj)
  1836.   905                            while True:
  1837.   906                                batch = list(islice(it, self._BATCHSIZE))
  1838.   907                                n = len(batch)
  1839.   908                                if n > 0:
  1840.   909                                    write(MARK)
  1841.   910                                    for item in batch:
  1842.   911                                        save(item)
  1843.   912                                    write(ADDITEMS)
  1844.   913                                if n < self._BATCHSIZE:
  1845.   914                                    return
  1846.   915                        dispatch[set] = save_set
  1847.   916
  1848.   917                        def save_frozenset(self, obj):
  1849.   918                            save = self.save
  1850.   919                            write = self.write
  1851.   920
  1852.   921                            if self.proto < 4:
  1853.   922                                self.save_reduce(frozenset, (list(obj),), obj=obj)
  1854.   923                                return
  1855.   924
  1856.   925                            write(MARK)
  1857.   926                            for item in obj:
  1858.   927                                save(item)
  1859.   928
  1860.   929                            if id(obj) in self.memo:
  1861.   930                                # If the object is already in the memo, this means it is
  1862.   931                                # recursive. In this case, throw away everything we put on the
  1863.   932                                # stack, and fetch the object back from the memo.
  1864.   933                                write(POP_MARK + self.get(self.memo[id(obj)][0]))
  1865.   934                                return
  1866.   935
  1867.   936                            write(FROZENSET)
  1868.   937                            self.memoize(obj)
  1869.   938                        dispatch[frozenset] = save_frozenset
  1870.   939
  1871.   940                        def save_global(self, obj, name=None):
  1872.   941                            write = self.write
  1873.   942                            memo = self.memo
  1874.   943
  1875.   944                            if name is None:
  1876.   945                                name = getattr(obj, '__qualname__', None)
  1877.   946                            if name is None:
  1878.   947                                name = obj.__name__
  1879.   948
  1880.   949                            module_name = whichmodule(obj, name)
  1881.   950                            try:
  1882.   951                                __import__(module_name, level=0)
  1883.   952                                module = sys.modules[module_name]
  1884.   953                                obj2, parent = _getattribute(module, name)
  1885.   954                            except (ImportError, KeyError, AttributeError):
  1886.   955                                raise PicklingError(
  1887.   956                                    "Can't pickle %r: it's not found as %s.%s" %
  1888.   957                                    (obj, module_name, name)) from None
  1889.   958                            else:
  1890.   959                                if obj2 is not obj:
  1891.   960                                    raise PicklingError(
  1892.   961                                        "Can't pickle %r: it's not the same object as %s.%s" %
  1893.   962                                        (obj, module_name, name))
  1894.   963
  1895.   964                            if self.proto >= 2:
  1896.   965                                code = _extension_registry.get((module_name, name))
  1897.   966                                if code:
  1898.   967                                    assert code > 0
  1899.   968                                    if code <= 0xff:
  1900.   969                                        write(EXT1 + pack("<B", code))
  1901.   970                                    elif code <= 0xffff:
  1902.   971                                        write(EXT2 + pack("<H", code))
  1903.   972                                    else:
  1904.   973                                        write(EXT4 + pack("<i", code))
  1905.   974                                    return
  1906.   975                            lastname = name.rpartition('.')[2]
  1907.   976                            if parent is module:
  1908.   977                                name = lastname
  1909.   978                            # Non-ASCII identifiers are supported only with protocols >= 3.
  1910.   979                            if self.proto >= 4:
  1911.   980                                self.save(module_name)
  1912.   981                                self.save(name)
  1913.   982                                write(STACK_GLOBAL)
  1914.   983                            elif parent is not module:
  1915.   984                                self.save_reduce(getattr, (parent, lastname))
  1916.   985                            elif self.proto >= 3:
  1917.   986                                write(GLOBAL + bytes(module_name, "utf-8") + b'\n' +
  1918.   987                                      bytes(name, "utf-8") + b'\n')
  1919.   988                            else:
  1920.   989                                if self.fix_imports:
  1921.   990                                    r_name_mapping = _compat_pickle.REVERSE_NAME_MAPPING
  1922.   991                                    r_import_mapping = _compat_pickle.REVERSE_IMPORT_MAPPING
  1923.   992                                    if (module_name, name) in r_name_mapping:
  1924.   993                                        module_name, name = r_name_mapping[(module_name, name)]
  1925.   994                                    elif module_name in r_import_mapping:
  1926.   995                                        module_name = r_import_mapping[module_name]
  1927.   996                                try:
  1928.   997                                    write(GLOBAL + bytes(module_name, "ascii") + b'\n' +
  1929.   998                                          bytes(name, "ascii") + b'\n')
  1930.   999                                except UnicodeEncodeError:
  1931.  1000                                    raise PicklingError(
  1932.  1001                                        "can't pickle global identifier '%s.%s' using "
  1933.  1002                                        "pickle protocol %i" % (module, name, self.proto)) from None
  1934.  1003
  1935.  1004                            self.memoize(obj)
  1936.  1005
  1937.  1006                        def save_type(self, obj):
  1938.  1007                            if obj is type(None):
  1939.  1008                                return self.save_reduce(type, (None,), obj=obj)
  1940.  1009                            elif obj is type(NotImplemented):
  1941.  1010                                return self.save_reduce(type, (NotImplemented,), obj=obj)
  1942.  1011                            elif obj is type(...):
  1943.  1012                                return self.save_reduce(type, (...,), obj=obj)
  1944.  1013                            return self.save_global(obj)
  1945.  1014
  1946.  1015                        dispatch[FunctionType] = save_global
  1947.  1016                        dispatch[type] = save_type
  1948.  1017
  1949.  1018
  1950.  1019                    # Unpickling machinery
  1951.  1020
  1952.  1021                    class _Unpickler:
  1953.  1022
  1954.  1023                        def __init__(self, file, *, fix_imports=True,
  1955.  1024                                     encoding="ASCII", errors="strict"):
  1956.  1025                            """This takes a binary file for reading a pickle data stream.
  1957.  1026
  1958.  1027                            The protocol version of the pickle is detected automatically, so
  1959.  1028                            no proto argument is needed.
  1960.  1029
  1961.  1030                            The argument *file* must have two methods, a read() method that
  1962.  1031                            takes an integer argument, and a readline() method that requires
  1963.  1032                            no arguments.  Both methods should return bytes.  Thus *file*
  1964.  1033                            can be a binary file object opened for reading, an io.BytesIO
  1965.  1034                            object, or any other custom object that meets this interface.
  1966.  1035
  1967.  1036                            The file-like object must have two methods, a read() method
  1968.  1037                            that takes an integer argument, and a readline() method that
  1969.  1038                            requires no arguments.  Both methods should return bytes.
  1970.  1039                            Thus file-like object can be a binary file object opened for
  1971.  1040                            reading, a BytesIO object, or any other custom object that
  1972.  1041                            meets this interface.
  1973.  1042
  1974.  1043                            Optional keyword arguments are *fix_imports*, *encoding* and
  1975.  1044                            *errors*, which are used to control compatibility support for
  1976.  1045                            pickle stream generated by Python 2.  If *fix_imports* is True,
  1977.  1046                            pickle will try to map the old Python 2 names to the new names
  1978.  1047                            used in Python 3.  The *encoding* and *errors* tell pickle how
  1979.  1048                            to decode 8-bit string instances pickled by Python 2; these
  1980.  1049                            default to 'ASCII' and 'strict', respectively. *encoding* can be
  1981.  1050                            'bytes' to read theses 8-bit string instances as bytes objects.
  1982.  1051                            """
  1983.  1052                            self._file_readline = file.readline
  1984.  1053                            self._file_read = file.read
  1985.  1054                            self.memo = {}
  1986.  1055                            self.encoding = encoding
  1987.  1056                            self.errors = errors
  1988.  1057                            self.proto = 0
  1989.  1058                            self.fix_imports = fix_imports
  1990.  1059
  1991.  1060                        def load(self):
  1992.  1061                            """Read a pickled object representation from the open file.
  1993.  1062
  1994.  1063                            Return the reconstituted object hierarchy specified in the file.
  1995.  1064                            """
  1996.  1065                            # Check whether Unpickler was initialized correctly. This is
  1997.  1066                            # only needed to mimic the behavior of _pickle.Unpickler.dump().
  1998.  1067                            if not hasattr(self, "_file_read"):
  1999.  1068                                raise UnpicklingError("Unpickler.__init__() was not called by "
  2000.  1069                                                      "%s.__init__()" % (self.__class__.__name__,))
  2001.  1070                            self._unframer = _Unframer(self._file_read, self._file_readline)
  2002.  1071                            self.read = self._unframer.read
  2003.  1072                            self.readline = self._unframer.readline
  2004.  1073                            self.metastack = []
  2005.  1074                            self.stack = []
  2006.  1075                            self.append = self.stack.append
  2007.  1076                            self.proto = 0
  2008.  1077                            read = self.read
  2009.  1078                            dispatch = self.dispatch
  2010.  1079                            try:
  2011.  1080                                while True:
  2012.  1081                                    key = read(1)
  2013.  1082                                    if not key:
  2014.  1083                                        raise EOFError
  2015.  1084                                    assert isinstance(key, bytes_types)
  2016.  1085                                    dispatch[key[0]](self)
  2017.  1086                            except _Stop as stopinst:
  2018.  1087                                return stopinst.value
  2019.  1088
  2020.  1089                        # Return a list of items pushed in the stack after last MARK instruction.
  2021.  1090                        def pop_mark(self):
  2022.  1091                            items = self.stack
  2023.  1092                            self.stack = self.metastack.pop()
  2024.  1093                            self.append = self.stack.append
  2025.  1094                            return items
  2026.  1095
  2027.  1096                        def persistent_load(self, pid):
  2028.  1097                            raise UnpicklingError("unsupported persistent id encountered")
  2029.  1098
  2030.  1099                        dispatch = {}
  2031.  1100
  2032.  1101                        def load_proto(self):
  2033.  1102                            proto = self.read(1)[0]
  2034.  1103                            if not 0 <= proto <= HIGHEST_PROTOCOL:
  2035.  1104                                raise ValueError("unsupported pickle protocol: %d" % proto)
  2036.  1105                            self.proto = proto
  2037.  1106                        dispatch[PROTO[0]] = load_proto
  2038.  1107
  2039.  1108                        def load_frame(self):
  2040.  1109                            frame_size, = unpack('<Q', self.read(8))
  2041.  1110                            if frame_size > sys.maxsize:
  2042.  1111                                raise ValueError("frame size > sys.maxsize: %d" % frame_size)
  2043.  1112                            self._unframer.load_frame(frame_size)
  2044.  1113                        dispatch[FRAME[0]] = load_frame
  2045.  1114
  2046.  1115                        def load_persid(self):
  2047.  1116                            try:
  2048.  1117                                pid = self.readline()[:-1].decode("ascii")
  2049.  1118                            except UnicodeDecodeError:
  2050.  1119                                raise UnpicklingError(
  2051.  1120                                    "persistent IDs in protocol 0 must be ASCII strings")
  2052.  1121                            self.append(self.persistent_load(pid))
  2053.  1122                        dispatch[PERSID[0]] = load_persid
  2054.  1123
  2055.  1124                        def load_binpersid(self):
  2056.  1125                            pid = self.stack.pop()
  2057.  1126                            self.append(self.persistent_load(pid))
  2058.  1127                        dispatch[BINPERSID[0]] = load_binpersid
  2059.  1128
  2060.  1129                        def load_none(self):
  2061.  1130                            self.append(None)
  2062.  1131                        dispatch[NONE[0]] = load_none
  2063.  1132
  2064.  1133                        def load_false(self):
  2065.  1134                            self.append(False)
  2066.  1135                        dispatch[NEWFALSE[0]] = load_false
  2067.  1136
  2068.  1137                        def load_true(self):
  2069.  1138                            self.append(True)
  2070.  1139                        dispatch[NEWTRUE[0]] = load_true
  2071.  1140
  2072.  1141                        def load_int(self):
  2073.  1142                            data = self.readline()
  2074.  1143                            if data == FALSE[1:]:
  2075.  1144                                val = False
  2076.  1145                            elif data == TRUE[1:]:
  2077.  1146                                val = True
  2078.  1147                            else:
  2079.  1148                                val = int(data, 0)
  2080.  1149                            self.append(val)
  2081.  1150                        dispatch[INT[0]] = load_int
  2082.  1151
  2083.  1152                        def load_binint(self):
  2084.  1153                            self.append(unpack('<i', self.read(4))[0])
  2085.  1154                        dispatch[BININT[0]] = load_binint
  2086.  1155
  2087.  1156                        def load_binint1(self):
  2088.  1157                            self.append(self.read(1)[0])
  2089.  1158                        dispatch[BININT1[0]] = load_binint1
  2090.  1159
  2091.  1160                        def load_binint2(self):
  2092.  1161                            self.append(unpack('<H', self.read(2))[0])
  2093.  1162                        dispatch[BININT2[0]] = load_binint2
  2094.  1163
  2095.  1164                        def load_long(self):
  2096.  1165                            val = self.readline()[:-1]
  2097.  1166                            if val and val[-1] == b'L'[0]:
  2098.  1167                                val = val[:-1]
  2099.  1168                            self.append(int(val, 0))
  2100.  1169                        dispatch[LONG[0]] = load_long
  2101.  1170
  2102.  1171                        def load_long1(self):
  2103.  1172                            n = self.read(1)[0]
  2104.  1173                            data = self.read(n)
  2105.  1174                            self.append(decode_long(data))
  2106.  1175                        dispatch[LONG1[0]] = load_long1
  2107.  1176
  2108.  1177                        def load_long4(self):
  2109.  1178                            n, = unpack('<i', self.read(4))
  2110.  1179                            if n < 0:
  2111.  1180                                # Corrupt or hostile pickle -- we never write one like this
  2112.  1181                                raise UnpicklingError("LONG pickle has negative byte count")
  2113.  1182                            data = self.read(n)
  2114.  1183                            self.append(decode_long(data))
  2115.  1184                        dispatch[LONG4[0]] = load_long4
  2116.  1185
  2117.  1186                        def load_float(self):
  2118.  1187                            self.append(float(self.readline()[:-1]))
  2119.  1188                        dispatch[FLOAT[0]] = load_float
  2120.  1189
  2121.  1190                        def load_binfloat(self):
  2122.  1191                            self.append(unpack('>d', self.read(8))[0])
  2123.  1192                        dispatch[BINFLOAT[0]] = load_binfloat
  2124.  1193
  2125.  1194                        def _decode_string(self, value):
  2126.  1195                            # Used to allow strings from Python 2 to be decoded either as
  2127.  1196                            # bytes or Unicode strings.  This should be used only with the
  2128.  1197                            # STRING, BINSTRING and SHORT_BINSTRING opcodes.
  2129.  1198                            if self.encoding == "bytes":
  2130.  1199                                return value
  2131.  1200                            else:
  2132.  1201                                return value.decode(self.encoding, self.errors)
  2133.  1202
  2134.  1203                        def load_string(self):
  2135.  1204                            data = self.readline()[:-1]
  2136.  1205                            # Strip outermost quotes
  2137.  1206                            if len(data) >= 2 and data[0] == data[-1] and data[0] in b'"\'':
  2138.  1207                                data = data[1:-1]
  2139.  1208                            else:
  2140.  1209                                raise UnpicklingError("the STRING opcode argument must be quoted")
  2141.  1210                            self.append(self._decode_string(codecs.escape_decode(data)[0]))
  2142.  1211                        dispatch[STRING[0]] = load_string
  2143.  1212
  2144.  1213                        def load_binstring(self):
  2145.  1214                            # Deprecated BINSTRING uses signed 32-bit length
  2146.  1215                            len, = unpack('<i', self.read(4))
  2147.  1216                            if len < 0:
  2148.  1217                                raise UnpicklingError("BINSTRING pickle has negative byte count")
  2149.  1218                            data = self.read(len)
  2150.  1219                            self.append(self._decode_string(data))
  2151.  1220                        dispatch[BINSTRING[0]] = load_binstring
  2152.  1221
  2153.  1222                        def load_binbytes(self):
  2154.  1223                            len, = unpack('<I', self.read(4))
  2155.  1224                            if len > maxsize:
  2156.  1225                                raise UnpicklingError("BINBYTES exceeds system's maximum size "
  2157.  1226                                                      "of %d bytes" % maxsize)
  2158.  1227                            self.append(self.read(len))
  2159.  1228                        dispatch[BINBYTES[0]] = load_binbytes
  2160.  1229
  2161.  1230                        def load_unicode(self):
  2162.  1231                            self.append(str(self.readline()[:-1], 'raw-unicode-escape'))
  2163.  1232                        dispatch[UNICODE[0]] = load_unicode
  2164.  1233
  2165.  1234                        def load_binunicode(self):
  2166.  1235                            len, = unpack('<I', self.read(4))
  2167.  1236                            if len > maxsize:
  2168.  1237                                raise UnpicklingError("BINUNICODE exceeds system's maximum size "
  2169.  1238                                                      "of %d bytes" % maxsize)
  2170.  1239                            self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
  2171.  1240                        dispatch[BINUNICODE[0]] = load_binunicode
  2172.  1241
  2173.  1242                        def load_binunicode8(self):
  2174.  1243                            len, = unpack('<Q', self.read(8))
  2175.  1244                            if len > maxsize:
  2176.  1245                                raise UnpicklingError("BINUNICODE8 exceeds system's maximum size "
  2177.  1246                                                      "of %d bytes" % maxsize)
  2178.  1247                            self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
  2179.  1248                        dispatch[BINUNICODE8[0]] = load_binunicode8
  2180.  1249
  2181.  1250                        def load_binbytes8(self):
  2182.  1251                            len, = unpack('<Q', self.read(8))
  2183.  1252                            if len > maxsize:
  2184.  1253                                raise UnpicklingError("BINBYTES8 exceeds system's maximum size "
  2185.  1254                                                      "of %d bytes" % maxsize)
  2186.  1255                            self.append(self.read(len))
  2187.  1256                        dispatch[BINBYTES8[0]] = load_binbytes8
  2188.  1257
  2189.  1258                        def load_short_binstring(self):
  2190.  1259                            len = self.read(1)[0]
  2191.  1260                            data = self.read(len)
  2192.  1261                            self.append(self._decode_string(data))
  2193.  1262                        dispatch[SHORT_BINSTRING[0]] = load_short_binstring
  2194.  1263
  2195.  1264                        def load_short_binbytes(self):
  2196.  1265                            len = self.read(1)[0]
  2197.  1266                            self.append(self.read(len))
  2198.  1267                        dispatch[SHORT_BINBYTES[0]] = load_short_binbytes
  2199.  1268
  2200.  1269                        def load_short_binunicode(self):
  2201.  1270                            len = self.read(1)[0]
  2202.  1271                            self.append(str(self.read(len), 'utf-8', 'surrogatepass'))
  2203.  1272                        dispatch[SHORT_BINUNICODE[0]] = load_short_binunicode
  2204.  1273
  2205.  1274                        def load_tuple(self):
  2206.  1275                            items = self.pop_mark()
  2207.  1276                            self.append(tuple(items))
  2208.  1277                        dispatch[TUPLE[0]] = load_tuple
  2209.  1278
  2210.  1279                        def load_empty_tuple(self):
  2211.  1280                            self.append(())
  2212.  1281                        dispatch[EMPTY_TUPLE[0]] = load_empty_tuple
  2213.  1282
  2214.  1283                        def load_tuple1(self):
  2215.  1284                            self.stack[-1] = (self.stack[-1],)
  2216.  1285                        dispatch[TUPLE1[0]] = load_tuple1
  2217.  1286
  2218.  1287                        def load_tuple2(self):
  2219.  1288                            self.stack[-2:] = [(self.stack[-2], self.stack[-1])]
  2220.  1289                        dispatch[TUPLE2[0]] = load_tuple2
  2221.  1290
  2222.  1291                        def load_tuple3(self):
  2223.  1292                            self.stack[-3:] = [(self.stack[-3], self.stack[-2], self.stack[-1])]
  2224.  1293                        dispatch[TUPLE3[0]] = load_tuple3
  2225.  1294
  2226.  1295                        def load_empty_list(self):
  2227.  1296                            self.append([])
  2228.  1297                        dispatch[EMPTY_LIST[0]] = load_empty_list
  2229.  1298
  2230.  1299                        def load_empty_dictionary(self):
  2231.  1300                            self.append({})
  2232.  1301                        dispatch[EMPTY_DICT[0]] = load_empty_dictionary
  2233.  1302
  2234.  1303                        def load_empty_set(self):
  2235.  1304                            self.append(set())
  2236.  1305                        dispatch[EMPTY_SET[0]] = load_empty_set
  2237.  1306
  2238.  1307                        def load_frozenset(self):
  2239.  1308                            items = self.pop_mark()
  2240.  1309                            self.append(frozenset(items))
  2241.  1310                        dispatch[FROZENSET[0]] = load_frozenset
  2242.  1311
  2243.  1312                        def load_list(self):
  2244.  1313                            items = self.pop_mark()
  2245.  1314                            self.append(items)
  2246.  1315                        dispatch[LIST[0]] = load_list
  2247.  1316
  2248.  1317                        def load_dict(self):
  2249.  1318                            items = self.pop_mark()
  2250.  1319                            d = {items[i]: items[i+1]
  2251.  1320                                 for i in range(0, len(items), 2)}
  2252.  1321                            self.append(d)
  2253.  1322                        dispatch[DICT[0]] = load_dict
  2254.  1323
  2255.  1324                        # INST and OBJ differ only in how they get a class object.  It's not
  2256.  1325                        # only sensible to do the rest in a common routine, the two routines
  2257.  1326                        # previously diverged and grew different bugs.
  2258.  1327                        # klass is the class to instantiate, and k points to the topmost mark
  2259.  1328                        # object, following which are the arguments for klass.__init__.
  2260.  1329                        def _instantiate(self, klass, args):
  2261.  1330                            if (args or not isinstance(klass, type) or
  2262.  1331                                hasattr(klass, "__getinitargs__")):
  2263.  1332                                try:
  2264.  1333                                    value = klass(*args)
  2265.  1334                                except TypeError as err:
  2266.  1335                                    raise TypeError("in constructor for %s: %s" %
  2267.  1336                                                    (klass.__name__, str(err)), sys.exc_info()[2])
  2268.  1337                            else:
  2269.  1338                                value = klass.__new__(klass)
  2270.  1339                            self.append(value)
  2271.  1340
  2272.  1341                        def load_inst(self):
  2273.  1342                            module = self.readline()[:-1].decode("ascii")
  2274.  1343                            name = self.readline()[:-1].decode("ascii")
  2275.  1344                            klass = self.find_class(module, name)
  2276.  1345                            self._instantiate(klass, self.pop_mark())
  2277.  1346                        dispatch[INST[0]] = load_inst
  2278.  1347
  2279.  1348                        def load_obj(self):
  2280.  1349                            # Stack is ... markobject classobject arg1 arg2 ...
  2281.  1350                            args = self.pop_mark()
  2282.  1351                            cls = args.pop(0)
  2283.  1352                            self._instantiate(cls, args)
  2284.  1353                        dispatch[OBJ[0]] = load_obj
  2285.  1354
  2286.  1355                        def load_newobj(self):
  2287.  1356                            args = self.stack.pop()
  2288.  1357                            cls = self.stack.pop()
  2289.  1358                            obj = cls.__new__(cls, *args)
  2290.  1359                            self.append(obj)
  2291.  1360                        dispatch[NEWOBJ[0]] = load_newobj
  2292.  1361
  2293.  1362                        def load_newobj_ex(self):
  2294.  1363                            kwargs = self.stack.pop()
  2295.  1364                            args = self.stack.pop()
  2296.  1365                            cls = self.stack.pop()
  2297.  1366                            obj = cls.__new__(cls, *args, **kwargs)
  2298.  1367                            self.append(obj)
  2299.  1368                        dispatch[NEWOBJ_EX[0]] = load_newobj_ex
  2300.  1369
  2301.  1370                        def load_global(self):
  2302.  1371                            module = self.readline()[:-1].decode("utf-8")
  2303.  1372                            name = self.readline()[:-1].decode("utf-8")
  2304.  1373                            klass = self.find_class(module, name)
  2305.  1374                            self.append(klass)
  2306.  1375                        dispatch[GLOBAL[0]] = load_global
  2307.  1376
  2308.  1377                        def load_stack_global(self):
  2309.  1378                            name = self.stack.pop()
  2310.  1379                            module = self.stack.pop()
  2311.  1380                            if type(name) is not str or type(module) is not str:
  2312.  1381                                raise UnpicklingError("STACK_GLOBAL requires str")
  2313.  1382                            self.append(self.find_class(module, name))
  2314.  1383                        dispatch[STACK_GLOBAL[0]] = load_stack_global
  2315.  1384
  2316.  1385                        def load_ext1(self):
  2317.  1386                            code = self.read(1)[0]
  2318.  1387                            self.get_extension(code)
  2319.  1388                        dispatch[EXT1[0]] = load_ext1
  2320.  1389
  2321.  1390                        def load_ext2(self):
  2322.  1391                            code, = unpack('<H', self.read(2))
  2323.  1392                            self.get_extension(code)
  2324.  1393                        dispatch[EXT2[0]] = load_ext2
  2325.  1394
  2326.  1395                        def load_ext4(self):
  2327.  1396                            code, = unpack('<i', self.read(4))
  2328.  1397                            self.get_extension(code)
  2329.  1398                        dispatch[EXT4[0]] = load_ext4
  2330.  1399
  2331.  1400                        def get_extension(self, code):
  2332.  1401                            nil = []
  2333.  1402                            obj = _extension_cache.get(code, nil)
  2334.  1403                            if obj is not nil:
  2335.  1404                                self.append(obj)
  2336.  1405                                return
  2337.  1406                            key = _inverted_registry.get(code)
  2338.  1407                            if not key:
  2339.  1408                                if code <= 0: # note that 0 is forbidden
  2340.  1409                                    # Corrupt or hostile pickle.
  2341.  1410                                    raise UnpicklingError("EXT specifies code <= 0")
  2342.  1411                                raise ValueError("unregistered extension code %d" % code)
  2343.  1412                            obj = self.find_class(*key)
  2344.  1413                            _extension_cache[code] = obj
  2345.  1414                            self.append(obj)
  2346.  1415
  2347.  1416                        def find_class(self, module, name):
  2348.  1417                            # Subclasses may override this.
  2349.  1418                            if self.proto < 3 and self.fix_imports:
  2350.  1419                                if (module, name) in _compat_pickle.NAME_MAPPING:
  2351.  1420                                    module, name = _compat_pickle.NAME_MAPPING[(module, name)]
  2352.  1421                                elif module in _compat_pickle.IMPORT_MAPPING:
  2353.  1422                                    module = _compat_pickle.IMPORT_MAPPING[module]
  2354.  1423                            __import__(module, level=0)
  2355.  1424                            if self.proto >= 4:
  2356.  1425                                return _getattribute(sys.modules[module], name)[0]
  2357.  1426                            else:
  2358.  1427                                return getattr(sys.modules[module], name)
  2359.  1428
  2360.  1429                        def load_reduce(self):
  2361.  1430                            stack = self.stack
  2362.  1431                            args = stack.pop()
  2363.  1432                            func = stack[-1]
  2364.  1433                            stack[-1] = func(*args)
  2365.  1434                        dispatch[REDUCE[0]] = load_reduce
  2366.  1435
  2367.  1436                        def load_pop(self):
  2368.  1437                            if self.stack:
  2369.  1438                                del self.stack[-1]
  2370.  1439                            else:
  2371.  1440                                self.pop_mark()
  2372.  1441                        dispatch[POP[0]] = load_pop
  2373.  1442
  2374.  1443                        def load_pop_mark(self):
  2375.  1444                            self.pop_mark()
  2376.  1445                        dispatch[POP_MARK[0]] = load_pop_mark
  2377.  1446
  2378.  1447                        def load_dup(self):
  2379.  1448                            self.append(self.stack[-1])
  2380.  1449                        dispatch[DUP[0]] = load_dup
  2381.  1450
  2382.  1451                        def load_get(self):
  2383.  1452                            i = int(self.readline()[:-1])
  2384.  1453                            self.append(self.memo[i])
  2385.  1454                        dispatch[GET[0]] = load_get
  2386.  1455
  2387.  1456                        def load_binget(self):
  2388.  1457                            i = self.read(1)[0]
  2389.  1458                            self.append(self.memo[i])
  2390.  1459                        dispatch[BINGET[0]] = load_binget
  2391.  1460
  2392.  1461                        def load_long_binget(self):
  2393.  1462                            i, = unpack('<I', self.read(4))
  2394.  1463                            self.append(self.memo[i])
  2395.  1464                        dispatch[LONG_BINGET[0]] = load_long_binget
  2396.  1465
  2397.  1466                        def load_put(self):
  2398.  1467                            i = int(self.readline()[:-1])
  2399.  1468                            if i < 0:
  2400.  1469                                raise ValueError("negative PUT argument")
  2401.  1470                            self.memo[i] = self.stack[-1]
  2402.  1471                        dispatch[PUT[0]] = load_put
  2403.  1472
  2404.  1473                        def load_binput(self):
  2405.  1474                            i = self.read(1)[0]
  2406.  1475                            if i < 0:
  2407.  1476                                raise ValueError("negative BINPUT argument")
  2408.  1477                            self.memo[i] = self.stack[-1]
  2409.  1478                        dispatch[BINPUT[0]] = load_binput
  2410.  1479
  2411.  1480                        def load_long_binput(self):
  2412.  1481                            i, = unpack('<I', self.read(4))
  2413.  1482                            if i > maxsize:
  2414.  1483                                raise ValueError("negative LONG_BINPUT argument")
  2415.  1484                            self.memo[i] = self.stack[-1]
  2416.  1485                        dispatch[LONG_BINPUT[0]] = load_long_binput
  2417.  1486
  2418.  1487                        def load_memoize(self):
  2419.  1488                            memo = self.memo
  2420.  1489                            memo[len(memo)] = self.stack[-1]
  2421.  1490                        dispatch[MEMOIZE[0]] = load_memoize
  2422.  1491
  2423.  1492                        def load_append(self):
  2424.  1493                            stack = self.stack
  2425.  1494                            value = stack.pop()
  2426.  1495                            list = stack[-1]
  2427.  1496                            list.append(value)
  2428.  1497                        dispatch[APPEND[0]] = load_append
  2429.  1498
  2430.  1499                        def load_appends(self):
  2431.  1500                            items = self.pop_mark()
  2432.  1501                            list_obj = self.stack[-1]
  2433.  1502                            try:
  2434.  1503                                extend = list_obj.extend
  2435.  1504                            except AttributeError:
  2436.  1505                                pass
  2437.  1506                            else:
  2438.  1507                                extend(items)
  2439.  1508                                return
  2440.  1509                            # Even if the PEP 307 requires extend() and append() methods,
  2441.  1510                            # fall back on append() if the object has no extend() method
  2442.  1511                            # for backward compatibility.
  2443.  1512                            append = list_obj.append
  2444.  1513                            for item in items:
  2445.  1514                                append(item)
  2446.  1515                        dispatch[APPENDS[0]] = load_appends
  2447.  1516
  2448.  1517                        def load_setitem(self):
  2449.  1518                            stack = self.stack
  2450.  1519                            value = stack.pop()
  2451.  1520                            key = stack.pop()
  2452.  1521                            dict = stack[-1]
  2453.  1522                            dict[key] = value
  2454.  1523                        dispatch[SETITEM[0]] = load_setitem
  2455.  1524
  2456.  1525                        def load_setitems(self):
  2457.  1526                            items = self.pop_mark()
  2458.  1527                            dict = self.stack[-1]
  2459.  1528                            for i in range(0, len(items), 2):
  2460.  1529                                dict[items[i]] = items[i + 1]
  2461.  1530                        dispatch[SETITEMS[0]] = load_setitems
  2462.  1531
  2463.  1532                        def load_additems(self):
  2464.  1533                            items = self.pop_mark()
  2465.  1534                            set_obj = self.stack[-1]
  2466.  1535                            if isinstance(set_obj, set):
  2467.  1536                                set_obj.update(items)
  2468.  1537                            else:
  2469.  1538                                add = set_obj.add
  2470.  1539                                for item in items:
  2471.  1540                                    add(item)
  2472.  1541                        dispatch[ADDITEMS[0]] = load_additems
  2473.  1542
  2474.  1543                        def load_build(self):
  2475.  1544                            stack = self.stack
  2476.  1545                            state = stack.pop()
  2477.  1546                            inst = stack[-1]
  2478.  1547                            setstate = getattr(inst, "__setstate__", None)
  2479.  1548                            if setstate is not None:
  2480.  1549                                setstate(state)
  2481.  1550                                return
  2482.  1551                            slotstate = None
  2483.  1552                            if isinstance(state, tuple) and len(state) == 2:
  2484.  1553                                state, slotstate = state
  2485.  1554                            if state:
  2486.  1555                                inst_dict = inst.__dict__
  2487.  1556                                intern = sys.intern
  2488.  1557                                for k, v in state.items():
  2489.  1558                                    if type(k) is str:
  2490.  1559                                        inst_dict[intern(k)] = v
  2491.  1560                                    else:
  2492.  1561                                        inst_dict[k] = v
  2493.  1562                            if slotstate:
  2494.  1563                                for k, v in slotstate.items():
  2495.  1564                                    setattr(inst, k, v)
  2496.  1565                        dispatch[BUILD[0]] = load_build
  2497.  1566
  2498.  1567                        def load_mark(self):
  2499.  1568                            self.metastack.append(self.stack)
  2500.  1569                            self.stack = []
  2501.  1570                            self.append = self.stack.append
  2502.  1571                        dispatch[MARK[0]] = load_mark
  2503.  1572
  2504.  1573                        def load_stop(self):
  2505.  1574                            value = self.stack.pop()
  2506.  1575                            raise _Stop(value)
  2507.  1576                        dispatch[STOP[0]] = load_stop
  2508.  1577
  2509.  1578
  2510.  1579                    # Shorthands
  2511.  1580
  2512.  1581                    def _dump(obj, file, protocol=None, *, fix_imports=True):
  2513.  1582                        _Pickler(file, protocol, fix_imports=fix_imports).dump(obj)
  2514.  1583
  2515.  1584                    def _dumps(obj, protocol=None, *, fix_imports=True):
  2516.  1585                        f = io.BytesIO()
  2517.  1586                        _Pickler(f, protocol, fix_imports=fix_imports).dump(obj)
  2518.  1587                        res = f.getvalue()
  2519.  1588                        assert isinstance(res, bytes_types)
  2520.  1589                        return res
  2521.  1590
  2522.  1591                    def _load(file, *, fix_imports=True, encoding="ASCII", errors="strict"):
  2523.  1592                        return _Unpickler(file, fix_imports=fix_imports,
  2524.  1593                                         encoding=encoding, errors=errors).load()
  2525.  1594
  2526.  1595                    def _loads(s, *, fix_imports=True, encoding="ASCII", errors="strict"):
  2527.  1596                        if isinstance(s, str):
  2528.  1597                            raise TypeError("Can't load pickle from unicode string")
  2529.  1598                        file = io.BytesIO(s)
  2530.  1599                        return _Unpickler(file, fix_imports=fix_imports,
  2531.  1600                                          encoding=encoding, errors=errors).load()
  2532.  1601
  2533.  1602                    # Use the faster _pickle if possible
  2534.  1603                    try:
  2535.  1604        1     33.3      from _pickle import (
  2536.  
  2537. Total hits: 1 s
  2538.  
  2539. Could not find file <frozen importlib._bootstrap_external>
  2540. Are you sure you are running this program from the same directory
  2541. that you ran the profiler from?
  2542. Continuing without the function's contents.
  2543.  
  2544. Line #     Hits   % Hits  Line Contents
  2545. =======================================
  2546.   1356
  2547.   1357
  2548.   1358
  2549.   1359
  2550.   1360
  2551.   1361
  2552.   1362
  2553.   1363
  2554.   1364
  2555.   1365
  2556.   1366
  2557.   1367
  2558.   1368
  2559.   1369
  2560.   1370
  2561.   1371
  2562.   1372
  2563.   1373
  2564.   1374
  2565.   1375
  2566.   1376
  2567.   1377
  2568.   1378
  2569.   1379
  2570.   1380
  2571.   1381
  2572.   1382
  2573.   1383
  2574.   1384
  2575.   1385
  2576.   1386
  2577.   1387
  2578.   1388
  2579.   1389
  2580.   1390
  2581.   1391
  2582.   1392
  2583.   1393
  2584.   1394        1    100.0
  2585.  
  2586. Total hits: 1 s
  2587.  
  2588. Could not find file <frozen importlib._bootstrap_external>
  2589. Are you sure you are running this program from the same directory
  2590. that you ran the profiler from?
  2591. Continuing without the function's contents.
  2592.  
  2593. Line #     Hits   % Hits  Line Contents
  2594. =======================================
  2595.    93
  2596.    94
  2597.    95        1    100.0
  2598.  
  2599. Total hits: 1 s
  2600.  
  2601. Could not find file <frozen importlib._bootstrap_external>
  2602. Are you sure you are running this program from the same directory
  2603. that you ran the profiler from?
  2604. Continuing without the function's contents.
  2605.  
  2606. Line #     Hits   % Hits  Line Contents
  2607. =======================================
  2608.     84
  2609.     85
  2610.     86
  2611.     87        1    100.0
  2612.  
  2613. Total hits: 1 s
  2614.  
  2615. Could not find file <frozen importlib._bootstrap_external>
  2616. Are you sure you are running this program from the same directory
  2617. that you ran the profiler from?
  2618. Continuing without the function's contents.
  2619.  
  2620. Line #     Hits   % Hits  Line Contents
  2621. =======================================
  2622.    74
  2623.    75
  2624.    76
  2625.    77
  2626.    78
  2627.    79
  2628.    80
  2629.    81        1    100.0
  2630.  
  2631. Total hits: 2 s
  2632. File: json_generator.py
  2633. Function: parse_example_parts at line 60
  2634.  
  2635. Line #     Hits   % Hits  Line Contents
  2636. =======================================
  2637.    60                    def parse_example_parts(lines, example_title_line):
  2638.    61                        parts = {
  2639.    62                            "build_up": [],
  2640.    63                            "explanation": []
  2641.    64                        }
  2642.    65                        content = []
  2643.    66                        statements_so_far = []
  2644.    67                        output_so_far = []
  2645.    68                        next_line = example_title_line
  2646.    69                        # store build_up till an H4 (explanation) is encountered
  2647.    70                        while not next_line.startswith("#### "):
  2648.    71                            # Watching out for the snippets
  2649.    72                            if next_line.startswith("```"):
  2650.    73                                # It's a snippet, whatever found until now is text
  2651.     74                                is_interactive = False
  2652.     75                                if content:
  2653.     76        1     50.0                  parts["build_up"].append(generate_markdown_block(content))
  2654.     77                                    content = []
  2655.     78
  2656.     79                                next_line = next(lines)
  2657.     80
  2658.     81                                while not next_line.startswith("```"):
  2659.    82                                    if is_interactive_statement(next_line):
  2660.    83                                        is_interactive = True
  2661.    84                                        if (output_so_far):
  2662.    85        1     50.0                          parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  2663.    86                                            statements_so_far, output_so_far = [], []
  2664.    87                                        statements_so_far.append(next_line)
  2665.    88                                    else:
  2666.    89                                        # can be either output or normal code
  2667.    90                                        if is_interactive:
  2668.    91                                            output_so_far.append(next_line)
  2669.    92                                        else:
  2670.    93                                            statements_so_far.append(next_line)
  2671.    94                                    next_line = next(lines)
  2672.    95
  2673.    96                                # Snippet is over
  2674.    97                                parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  2675.    98                                statements_so_far, output_so_far = [], []
  2676.    99                                next_line = next(lines)
  2677.   100                            else:
  2678.   101                                # It's a text, go on.
  2679.   102                                content.append(next_line)
  2680.   103                                next_line = next(lines)
  2681.   104
  2682.   105                        # Explanation encountered, save any content till now (if any)
  2683.   106                        if content:
  2684.   107                            parts["build_up"].append(generate_markdown_block(content))
  2685.   108
  2686.   109                        # Reset stuff
  2687.   110                        content = []
  2688.   111                        statements_so_far, output_so_far = [], []
  2689.   112
  2690.   113                        # store lines again until --- or another H3 is encountered
  2691.   114                        while not (next_line.startswith("---") or
  2692.   115                                   next_line.startswith("### ")):
  2693.   116                            if next_line.startswith("```"):
  2694.    117                                # It's a snippet, whatever found until now is text
  2695.    118                                is_interactive = False
  2696.    119                                if content:
  2697.    120                                    parts["build_up"].append(generate_markdown_block(content))
  2698.    121                                    content = []
  2699.    122
  2700.    123                                next_line = next(lines)
  2701.    124
  2702.    125                                while not next_line.startswith("```"):
  2703.   126                                    if is_interactive_statement(next_line):
  2704.   127                                        is_interactive = True
  2705.   128                                        if (output_so_far):
  2706.   129                                            parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  2707.   130                                            statements_so_far, output_so_far = [], []
  2708.   131                                        statements_so_far.append(next_line)
  2709.   132                                    else:
  2710.   133                                        # can be either output or normal code
  2711.   134                                        if is_interactive:
  2712.   135                                            output_so_far.append(next_line)
  2713.   136                                        else:
  2714.   137                                            statements_so_far.append(next_line)
  2715.   138                                    next_line = next(lines)
  2716.   139
  2717.   140                                # Snippet is over
  2718.   141                                parts["build_up"].append(generate_code_block(statements_so_far, output_so_far))
  2719.   142                                statements_so_far, output_so_far = [], []
  2720.   143                                next_line = next(lines)
  2721.   144                            else:
  2722.   145                                # It's a text, go on.
  2723.   146                                content.append(next_line)
  2724.   147                                next_line = next(lines)
  2725.   148
  2726.   149                        # All done
  2727.   150                        if content:
  2728.   151                            parts["explanation"].append(generate_markdown_block(content))
  2729.   152
  2730.   153                        return next_line, parts
  2731.  
  2732. Total hits: 1 s
  2733. File: json_generator.py
  2734. Function: generate_markdown_block at line 43
  2735.  
  2736. Line #     Hits   % Hits  Line Contents
  2737. =======================================
  2738.    43                    def generate_markdown_block(lines):
  2739.    44                        global sequence_num
  2740.    45                        result = {
  2741.    46                            "type": "markdown",
  2742.    47                            "sequence_num": sequence_num,
  2743.    48        1    100.0          "value": lines
  2744.    49                        }
  2745.    50                        sequence_num += 1
  2746.    51                        return result
  2747.  
  2748. Total hits: 1 s
  2749. File: json_generator.py
  2750. Function: generate_code_block at line 31
  2751.  
  2752. Line #     Hits   % Hits  Line Contents
  2753. =======================================
  2754.    31                    def generate_code_block(statements, output):
  2755.    32                        global sequence_num
  2756.    33                        result = {
  2757.    34                            "type": "code",
  2758.    35                            "sequence_num": sequence_num,
  2759.    36                            "statements": statements,
  2760.    37        1    100.0          "output": output
  2761.    38                        }
  2762.    39                        sequence_num += 1
  2763.    40                        return result
  2764.  
  2765. Total hits: 302 s
  2766. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2767. Function: pprint at line 47
  2768.  
  2769. Line #     Hits   % Hits  Line Contents
  2770. =======================================
  2771.    47                    def pprint(object, stream=None, indent=1, width=80, depth=None, *,
  2772.    48                               compact=False):
  2773.    49                        """Pretty-print a Python object to a stream [default is sys.stdout]."""
  2774.    50                        printer = PrettyPrinter(
  2775.    51                            stream=stream, indent=indent, width=width, depth=depth,
  2776.    52                            compact=compact)
  2777.    53      302    100.0      printer.pprint(object)
  2778.  
  2779. Total hits: 302 s
  2780. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2781. Function: pprint at line 138
  2782.  
  2783. Line #     Hits   % Hits  Line Contents
  2784. =======================================
  2785.   138                        def pprint(self, object):
  2786.   139      302    100.0          self._format(object, self._stream, 0, 0, {}, 0)
  2787.   140                            self._stream.write("\n")
  2788.  
  2789. Total hits: 1286 s
  2790. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2791. Function: _format at line 154
  2792.  
  2793. Line #     Hits   % Hits  Line Contents
  2794. =======================================
  2795.   154                        def _format(self, object, stream, indent, allowance, context, level):
  2796.   155                            objid = id(object)
  2797.   156                            if objid in context:
  2798.   157                                stream.write(_recursion(object))
  2799.   158                                self._recursive = True
  2800.   159                                self._readable = False
  2801.   160                                return
  2802.   161       62      4.8          rep = self._repr(object, context, level)
  2803.   162        1      0.1          max_width = self._width - indent - allowance
  2804.   163                            if len(rep) > max_width:
  2805.   164                                p = self._dispatch.get(type(object).__repr__, None)
  2806.   165                                if p is not None:
  2807.   166                                    context[objid] = 1
  2808.   167     1223     95.1                  p(self, object, stream, indent, allowance, context, level + 1)
  2809.   168                                    del context[objid]
  2810.   169                                    return
  2811.   170                                elif isinstance(object, dict):
  2812.   171                                    context[objid] = 1
  2813.   172                                    self._pprint_dict(object, stream, indent, allowance,
  2814.   173                                                      context, level + 1)
  2815.   174                                    del context[objid]
  2816.   175                                    return
  2817.   176                            stream.write(rep)
  2818.  
  2819. Total hits: 63 s
  2820. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2821. Function: _repr at line 391
  2822.  
  2823. Line #     Hits   % Hits  Line Contents
  2824. =======================================
  2825.   391                        def _repr(self, object, context, level):
  2826.   392        4      6.3          repr, readable, recursive = self.format(object, context.copy(),
  2827.   393       59     93.7                                                  self._depth, level)
  2828.   394                            if not readable:
  2829.   395                                self._readable = False
  2830.   396                            if recursive:
  2831.   397                                self._recursive = True
  2832.   398                            return repr
  2833.  
  2834. Total hits: 59 s
  2835. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2836. Function: format at line 400
  2837.  
  2838. Line #     Hits   % Hits  Line Contents
  2839. =======================================
  2840.   400                        def format(self, object, context, maxlevels, level):
  2841.   401                            """Format object for a specific context, returning a string
  2842.   402                            and flags indicating whether the representation is 'readable'
  2843.   403                            and whether the object represents a recursive construct.
  2844.   404                            """
  2845.   405       59    100.0          return _safe_repr(object, context, maxlevels, level)
  2846.  
  2847. Total hits: 174 s
  2848. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2849. Function: _safe_repr at line 490
  2850.  
  2851. Line #     Hits   % Hits  Line Contents
  2852. =======================================
  2853.   490        1      0.6  def _safe_repr(object, context, maxlevels, level):
  2854.   491        1      0.6      typ = type(object)
  2855.   492                        if typ in _builtin_scalars:
  2856.   493        4      2.3          return repr(object), True, False
  2857.   494
  2858.   495                        r = getattr(typ, "__repr__", None)
  2859.   496                        if issubclass(typ, dict) and r is dict.__repr__:
  2860.   497                            if not object:
  2861.   498                                return "{}", True, False
  2862.   499                            objid = id(object)
  2863.   500                            if maxlevels and level >= maxlevels:
  2864.   501                                return "{...}", False, objid in context
  2865.   502                            if objid in context:
  2866.   503                                return _recursion(object), False, True
  2867.   504        1      0.6          context[objid] = 1
  2868.   505                            readable = True
  2869.   506                            recursive = False
  2870.   507                            components = []
  2871.   508                            append = components.append
  2872.   509        1      0.6          level += 1
  2873.   510                            saferepr = _safe_repr
  2874.   511        9      5.2          items = sorted(object.items(), key=_safe_tuple)
  2875.   512                            for k, v in items:
  2876.   513        2      1.1              krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
  2877.   514       60     34.5              vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
  2878.   515        4      2.3              append("%s: %s" % (krepr, vrepr))
  2879.   516                                readable = readable and kreadable and vreadable
  2880.   517        1      0.6              if krecur or vrecur:
  2881.   518                                    recursive = True
  2882.   519                            del context[objid]
  2883.   520       22     12.6          return "{%s}" % ", ".join(components), readable, recursive
  2884.   521
  2885.   522                        if (issubclass(typ, list) and r is list.__repr__) or \
  2886.   523                           (issubclass(typ, tuple) and r is tuple.__repr__):
  2887.   524                            if issubclass(typ, list):
  2888.   525        1      0.6              if not object:
  2889.   526                                    return "[]", True, False
  2890.   527                                format = "[%s]"
  2891.   528                            elif len(object) == 1:
  2892.   529                                format = "(%s,)"
  2893.   530                            else:
  2894.   531                                if not object:
  2895.   532                                    return "()", True, False
  2896.   533                                format = "(%s)"
  2897.   534                            objid = id(object)
  2898.   535                            if maxlevels and level >= maxlevels:
  2899.   536                                return format % "...", False, objid in context
  2900.   537        1      0.6          if objid in context:
  2901.   538                                return _recursion(object), False, True
  2902.   539                            context[objid] = 1
  2903.   540                            readable = True
  2904.   541                            recursive = False
  2905.   542                            components = []
  2906.   543                            append = components.append
  2907.   544                            level += 1
  2908.   545        1      0.6          for o in object:
  2909.   546       54     31.0              orepr, oreadable, orecur = _safe_repr(o, context, maxlevels, level)
  2910.   547                                append(orepr)
  2911.   548                                if not oreadable:
  2912.   549                                    readable = False
  2913.   550                                if orecur:
  2914.   551                                    recursive = True
  2915.   552                            del context[objid]
  2916.   553       11      6.3          return format % ", ".join(components), readable, recursive
  2917.   554
  2918.   555                        rep = repr(object)
  2919.   556                        return rep, (rep and not rep.startswith('<')), False
  2920.  
  2921. Total hits: 513 s
  2922. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2923. Function: _pprint_list at line 207
  2924.  
  2925. Line #     Hits   % Hits  Line Contents
  2926. =======================================
  2927.   207                        def _pprint_list(self, object, stream, indent, allowance, context, level):
  2928.   208                            stream.write('[')
  2929.   209                            self._format_items(object, stream, indent, allowance + 1,
  2930.   210      513    100.0                             context, level)
  2931.   211                            stream.write(']')
  2932.  
  2933. Total hits: 513 s
  2934. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2935. Function: _format_items at line 350
  2936.  
  2937. Line #     Hits   % Hits  Line Contents
  2938. =======================================
  2939.   350                        def _format_items(self, items, stream, indent, allowance, context, level):
  2940.   351                            write = stream.write
  2941.   352                            indent += self._indent_per_level
  2942.   353                            if self._indent_per_level > 1:
  2943.   354                                write((self._indent_per_level - 1) * ' ')
  2944.   355                            delimnl = ',\n' + ' ' * indent
  2945.   356                            delim = ''
  2946.   357                            width = max_width = self._width - indent + 1
  2947.   358                            it = iter(items)
  2948.   359                            try:
  2949.   360                                next_ent = next(it)
  2950.   361                            except StopIteration:
  2951.   362                                return
  2952.   363                            last = False
  2953.   364                            while not last:
  2954.   365                                ent = next_ent
  2955.   366                                try:
  2956.   367        2      0.4                  next_ent = next(it)
  2957.   368                                except StopIteration:
  2958.   369                                    last = True
  2959.   370                                    max_width -= allowance
  2960.   371                                    width -= allowance
  2961.   372                                if self._compact:
  2962.   373                                    rep = self._repr(ent, context, level)
  2963.   374                                    w = len(rep) + 2
  2964.   375                                    if width < w:
  2965.   376                                        width = max_width
  2966.   377                                        if delim:
  2967.   378                                            delim = delimnl
  2968.   379                                    if width >= w:
  2969.   380                                        width -= w
  2970.   381                                        write(delim)
  2971.   382                                        delim = ', '
  2972.   383                                        write(rep)
  2973.   384                                        continue
  2974.   385       50      9.7              write(delim)
  2975.   386                                delim = delimnl
  2976.   387                                self._format(ent, stream, indent,
  2977.   388                                             allowance if last else 1,
  2978.   389      461     89.9                           context, level)
  2979.  
  2980. Total hits: 649 s
  2981. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  2982. Function: _pprint_dict at line 180
  2983.  
  2984. Line #     Hits   % Hits  Line Contents
  2985. =======================================
  2986.   180                        def _pprint_dict(self, object, stream, indent, allowance, context, level):
  2987.   181                            write = stream.write
  2988.   182                            write('{')
  2989.   183                            if self._indent_per_level > 1:
  2990.   184                                write((self._indent_per_level - 1) * ' ')
  2991.   185                            length = len(object)
  2992.   186                            if length:
  2993.   187        1      0.2              items = sorted(object.items(), key=_safe_tuple)
  2994.   188        1      0.2              self._format_dict_items(items, stream, indent, allowance + 1,
  2995.   189      647     99.7                                      context, level)
  2996.   190                            write('}')
  2997.  
  2998. Total hits: 647 s
  2999. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  3000. Function: _format_dict_items at line 333
  3001.  
  3002. Line #     Hits   % Hits  Line Contents
  3003. =======================================
  3004.   333                        def _format_dict_items(self, items, stream, indent, allowance, context,
  3005.   334                                               level):
  3006.   335                            write = stream.write
  3007.   336                            indent += self._indent_per_level
  3008.   337                            delimnl = ',\n' + ' ' * indent
  3009.   338                            last_index = len(items) - 1
  3010.   339                            for i, (key, ent) in enumerate(items):
  3011.   340                                last = i == last_index
  3012.   341        1      0.2              rep = self._repr(key, context, level)
  3013.   342                                write(rep)
  3014.   343                                write(': ')
  3015.   344                                self._format(ent, stream, indent + len(rep) + 2,
  3016.   345                                             allowance if last else 1,
  3017.   346      524     81.0                           context, level)
  3018.   347                                if not last:
  3019.   348      122     18.9                  write(delimnl)
  3020.  
  3021. Total hits: 61 s
  3022. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  3023. Function: _pprint_str at line 244
  3024.  
  3025. Line #     Hits   % Hits  Line Contents
  3026. =======================================
  3027.   244                        def _pprint_str(self, object, stream, indent, allowance, context, level):
  3028.   245                            write = stream.write
  3029.   246                            if not len(object):
  3030.   247                                write(repr(object))
  3031.   248                                return
  3032.   249                            chunks = []
  3033.   250                            lines = object.splitlines(True)
  3034.   251                            if level == 1:
  3035.   252                                indent += 1
  3036.   253                                allowance += 1
  3037.   254                            max_width1 = max_width = self._width - indent
  3038.   255                            for i, line in enumerate(lines):
  3039.   256                                rep = repr(line)
  3040.   257                                if i == len(lines) - 1:
  3041.   258                                    max_width1 -= allowance
  3042.   259                                if len(rep) <= max_width1:
  3043.   260                                    chunks.append(rep)
  3044.   261                                else:
  3045.   262                                    # A list of alternating (non-space, space) strings
  3046.   263        2      3.3                  parts = re.findall(r'\S*\s*', line)
  3047.   264                                    assert parts
  3048.   265                                    assert not parts[-1]
  3049.   266        1      1.6                  parts.pop()  # drop empty last part
  3050.   267                                    max_width2 = max_width
  3051.   268                                    current = ''
  3052.   269        1      1.6                  for j, part in enumerate(parts):
  3053.   270                                        candidate = current + part
  3054.   271                                        if j == len(parts) - 1 and i == len(lines) - 1:
  3055.   272                                            max_width2 -= allowance
  3056.   273                                        if len(repr(candidate)) > max_width2:
  3057.   274                                            if current:
  3058.   275                                                chunks.append(repr(current))
  3059.   276                                            current = part
  3060.   277                                        else:
  3061.   278                                            current = candidate
  3062.   279                                    if current:
  3063.   280                                        chunks.append(repr(current))
  3064.   281                            if len(chunks) == 1:
  3065.   282                                write(rep)
  3066.   283                                return
  3067.   284                            if level == 1:
  3068.   285                                write('(')
  3069.   286                            for i, rep in enumerate(chunks):
  3070.   287        1      1.6              if i > 0:
  3071.   288       55     90.2                  write('\n' + ' '*indent)
  3072.   289        1      1.6              write(rep)
  3073.   290                            if level == 1:
  3074.   291                                write(')')
  3075.  
  3076. Total hits: 2 s
  3077. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/re.py
  3078. Function: findall at line 215
  3079.  
  3080. Line #     Hits   % Hits  Line Contents
  3081. =======================================
  3082.   215                    def findall(pattern, string, flags=0):
  3083.   216                        """Return a list of all non-overlapping matches in the string.
  3084.   217
  3085.   218                        If one or more capturing groups are present in the pattern, return
  3086.   219                        a list of groups; this will be a list of tuples if the pattern
  3087.   220                        has more than one group.
  3088.   221
  3089.   222                        Empty matches are included in the result."""
  3090.   223        2    100.0      return _compile(pattern, flags).findall(string)
  3091.  
  3092. Total hits: 1 s
  3093. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/re.py
  3094. Function: _compile at line 271
  3095.  
  3096. Line #     Hits   % Hits  Line Contents
  3097. =======================================
  3098.   271                    def _compile(pattern, flags):
  3099.   272                        # internal: compile pattern
  3100.   273                        if isinstance(flags, RegexFlag):
  3101.   274                            flags = flags.value
  3102.   275                        try:
  3103.   276        1    100.0          return _cache[type(pattern), pattern, flags]
  3104.   277                        except KeyError:
  3105.   278                            pass
  3106.   279                        if isinstance(pattern, Pattern):
  3107.   280                            if flags:
  3108.   281                                raise ValueError(
  3109.   282                                    "cannot process flags argument with a compiled pattern")
  3110.   283                            return pattern
  3111.   284                        if not sre_compile.isstring(pattern):
  3112.   285                            raise TypeError("first argument must be string or compiled pattern")
  3113.   286                        p = sre_compile.compile(pattern, flags)
  3114.   287                        if not (flags & DEBUG):
  3115.   288                            if len(_cache) >= _MAXCACHE:
  3116.   289                                # Drop the oldest item
  3117.   290                                try:
  3118.   291                                    del _cache[next(iter(_cache))]
  3119.   292                                except (StopIteration, RuntimeError, KeyError):
  3120.   293                                    pass
  3121.   294                            _cache[type(pattern), pattern, flags] = p
  3122.   295                        return p
  3123.  
  3124. Total hits: 3 s
  3125. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  3126. Function: __lt__ at line 87
  3127.  
  3128. Line #     Hits   % Hits  Line Contents
  3129. =======================================
  3130.    87                        def __lt__(self, other):
  3131.    88                            try:
  3132.    89        3    100.0              return self.obj < other.obj
  3133.    90                            except TypeError:
  3134.    91                                return ((str(type(self.obj)), id(self.obj)) < \
  3135.    92                                        (str(type(other.obj)), id(other.obj)))
  3136.  
  3137. Total hits: 5 s
  3138. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/pprint.py
  3139. Function: _safe_tuple at line 94
  3140.  
  3141. Line #     Hits   % Hits  Line Contents
  3142. =======================================
  3143.    94                    def _safe_tuple(t):
  3144.    95                        "Helper function for comparing 2-tuples"
  3145.    96        5    100.0      return _safe_key(t[0]), _safe_key(t[1])
  3146.  
  3147. Total hits: 170 s
  3148. File: json_generator.py
  3149. Function: convert_to_notebook at line 226
  3150.  
  3151. Line #     Hits   % Hits  Line Contents
  3152. =======================================
  3153.   226                    def convert_to_notebook(parsed_json):
  3154.   227                        result = {
  3155.   228                            "cells": [],
  3156.   229                            "metadata": {},
  3157.   230                            "nbformat": 4,
  3158.   231                            "nbformat_minor": 2
  3159.   232                        }
  3160.   233                        for example in parsed_json:
  3161.   234                            parts = example["parts"]
  3162.   235                            build_up = parts.get("build_up")
  3163.   236                            explanation = parts.get("explanation")
  3164.   237                            notebook_path = "test.ipynb"
  3165.   238
  3166.   239                            if(build_up):
  3167.   240        4      2.4              result["cells"] += convert_to_cells(build_up)
  3168.   241
  3169.   242                            if(explanation):
  3170.   243                                result["cells"] += convert_to_cells(explanation)
  3171.   244
  3172.   245      153     90.0      pprint.pprint(result, indent=2)
  3173.   246        1      0.6      with open(notebook_path, "w") as f:
  3174.   247       12      7.1          json.dump(result, f)
  3175.  
  3176. Total hits: 4 s
  3177. File: json_generator.py
  3178. Function: convert_to_cells at line 173
  3179.  
  3180. Line #     Hits   % Hits  Line Contents
  3181. =======================================
  3182.   173                    def convert_to_cells(cell_contents):
  3183.   174                        cells = []
  3184.   175                        for stuff in cell_contents:
  3185.   176                            if stuff["type"] == "markdown":
  3186.   177                                # todo add metadata later
  3187.   178                                cells.append(
  3188.   179                                    {
  3189.   180                                        "cell_type": "markdown",
  3190.   181        1     25.0                      "metadata": {},
  3191.   182        1     25.0                      "source": stuff["value"]
  3192.   183                                    }
  3193.   184                                )
  3194.   185                            elif stuff["type"] == "code":
  3195.   186                                is_print_present, sanitized_code = inspect_and_sanitize_code_lines(stuff["statements"])
  3196.   187                                if is_print_present:
  3197.   188                                    cells.append(
  3198.   189                                        {
  3199.   190                                            "cell_type": "code",
  3200.   191                                            "metadata": {
  3201.   192                                                "collapsed": True
  3202.   193                                            },
  3203.   194                                            "execution_count": None,
  3204.   195                                            "outputs": [{
  3205.   196                                                "name": "stdout",
  3206.   197                                                "output_type": "stream",
  3207.   198                                                "text": stuff["output"]
  3208.   199                                            }],
  3209.   200                                            "source": sanitized_code
  3210.   201                                        }
  3211.   202                                    )
  3212.   203                                else:
  3213.   204                                    cells.append(
  3214.   205                                        {
  3215.   206                                            "cell_type": "code",
  3216.   207                                            "execution_count": None,
  3217.   208                                            "metadata": {
  3218.   209                                                "collapsed": True
  3219.   210                                            },
  3220.   211                                            "outputs": [{
  3221.   212                                                "data": {
  3222.   213        2     50.0                                  "text/plain": stuff["output"]
  3223.   214                                                },
  3224.   215                                                "output_type": "execute_result",
  3225.   216                                                "metadata": {},
  3226.   217                                                "execution_count": None
  3227.   218                                            }],
  3228.   219                                            "source": sanitized_code
  3229.   220                                        }
  3230.   221                                    )
  3231.   222
  3232.   223                        return cells
  3233.  
  3234. Total hits: 12 s
  3235. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/json/__init__.py
  3236. Function: dump at line 120
  3237.  
  3238. Line #     Hits   % Hits  Line Contents
  3239. =======================================
  3240.   120                    def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
  3241.   121                            allow_nan=True, cls=None, indent=None, separators=None,
  3242.   122                            default=None, sort_keys=False, **kw):
  3243.   123                        """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
  3244.   124                        ``.write()``-supporting file-like object).
  3245.   125
  3246.   126                        If ``skipkeys`` is true then ``dict`` keys that are not basic types
  3247.   127                        (``str``, ``int``, ``float``, ``bool``, ``None``) will be skipped
  3248.   128                        instead of raising a ``TypeError``.
  3249.   129
  3250.   130                        If ``ensure_ascii`` is false, then the strings written to ``fp`` can
  3251.   131                        contain non-ASCII characters if they appear in strings contained in
  3252.   132                        ``obj``. Otherwise, all such characters are escaped in JSON strings.
  3253.   133
  3254.   134                        If ``check_circular`` is false, then the circular reference check
  3255.   135                        for container types will be skipped and a circular reference will
  3256.   136                        result in an ``OverflowError`` (or worse).
  3257.   137
  3258.   138                        If ``allow_nan`` is false, then it will be a ``ValueError`` to
  3259.   139                        serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
  3260.   140                        in strict compliance of the JSON specification, instead of using the
  3261.   141                        JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).
  3262.   142
  3263.   143                        If ``indent`` is a non-negative integer, then JSON array elements and
  3264.   144                        object members will be pretty-printed with that indent level. An indent
  3265.   145                        level of 0 will only insert newlines. ``None`` is the most compact
  3266.   146                        representation.
  3267.   147
  3268.   148                        If specified, ``separators`` should be an ``(item_separator, key_separator)``
  3269.   149                        tuple.  The default is ``(', ', ': ')`` if *indent* is ``None`` and
  3270.   150                        ``(',', ': ')`` otherwise.  To get the most compact JSON representation,
  3271.   151                        you should specify ``(',', ':')`` to eliminate whitespace.
  3272.   152
  3273.   153                        ``default(obj)`` is a function that should return a serializable version
  3274.   154                        of obj or raise TypeError. The default simply raises TypeError.
  3275.   155
  3276.   156                        If *sort_keys* is true (default: ``False``), then the output of
  3277.   157                        dictionaries will be sorted by key.
  3278.   158
  3279.   159                        To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
  3280.   160                        ``.default()`` method to serialize additional types), specify it with
  3281.   161                        the ``cls`` kwarg; otherwise ``JSONEncoder`` is used.
  3282.   162
  3283.   163                        """
  3284.    164                        # cached encoder
  3285.    165                        if (not skipkeys and ensure_ascii and
  3286.    166                            check_circular and allow_nan and
  3287.    167                            cls is None and indent is None and separators is None and
  3288.    168                            default is None and not sort_keys and not kw):
  3289.    169                            iterable = _default_encoder.iterencode(obj)
  3290.    170                        else:
  3291.    171                            if cls is None:
  3292.    172                                cls = JSONEncoder
  3293.    173                            iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
  3294.    174                                check_circular=check_circular, allow_nan=allow_nan, indent=indent,
  3295.    175                                separators=separators,
  3296.    176                                default=default, sort_keys=sort_keys, **kw).iterencode(obj)
  3297.    177                        # could accelerate with writelines in some versions of Python, at
  3298.    178                        # a debuggability cost
  3299.    179        4     33.3      for chunk in iterable:
  3300.    180        8     66.7          fp.write(chunk)
  3301.  
  3302. Total hits: 3 s
  3303. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/json/encoder.py
  3304. Function: _iterencode at line 413
  3305.  
  3306. Line #     Hits   % Hits  Line Contents
  3307. =======================================
  3308.    413                        def _iterencode(o, _current_indent_level):
  3309.    414                            if isinstance(o, str):
  3310.    415                                yield _encoder(o)
  3311.    416                            elif o is None:
  3312.    417                                yield 'null'
  3313.    418                            elif o is True:
  3314.    419                                yield 'true'
  3315.    420                            elif o is False:
  3316.    421                                yield 'false'
  3317.    422                            elif isinstance(o, int):
  3318.    423                                # see comment for int/float in _make_iterencode
  3319.    424                                yield _intstr(o)
  3320.    425                            elif isinstance(o, float):
  3321.    426                                # see comment for int/float in _make_iterencode
  3322.    427                                yield _floatstr(o)
  3323.    428                            elif isinstance(o, (list, tuple)):
  3324.    429                                yield from _iterencode_list(o, _current_indent_level)
  3325.    430                            elif isinstance(o, dict):
  3326.    431        3    100.0              yield from _iterencode_dict(o, _current_indent_level)
  3327.    432                            else:
  3328.    433                                if markers is not None:
  3329.    434                                    markerid = id(o)
  3330.    435                                    if markerid in markers:
  3331.    436                                        raise ValueError("Circular reference detected")
  3332.    437                                    markers[markerid] = o
  3333.    438                                o = _default(o)
  3334.    439                                yield from _iterencode(o, _current_indent_level)
  3335.    440                                if markers is not None:
  3336.    441                                    del markers[markerid]
  3337.  
  3338. Total hits: 3 s
  3339. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/json/encoder.py
  3340. Function: _iterencode_dict at line 333
  3341.  
  3342. Line #     Hits   % Hits  Line Contents
  3343. =======================================
  3344.    333                        def _iterencode_dict(dct, _current_indent_level):
  3345.    334                            if not dct:
  3346.    335                                yield '{}'
  3347.    336                                return
  3348.    337                            if markers is not None:
  3349.    338                                markerid = id(dct)
  3350.    339                                if markerid in markers:
  3351.    340                                    raise ValueError("Circular reference detected")
  3352.    341                                markers[markerid] = dct
  3353.    342                            yield '{'
  3354.    343                            if _indent is not None:
  3355.    344                                _current_indent_level += 1
  3356.    345                                newline_indent = '\n' + _indent * _current_indent_level
  3357.    346                                item_separator = _item_separator + newline_indent
  3358.    347                                yield newline_indent
  3359.    348                            else:
  3360.    349                                newline_indent = None
  3361.    350                                item_separator = _item_separator
  3362.    351                            first = True
  3363.    352                            if _sort_keys:
  3364.    353                                items = sorted(dct.items(), key=lambda kv: kv[0])
  3365.    354                            else:
  3366.    355                                items = dct.items()
  3367.    356                            for key, value in items:
  3368.    357                                if isinstance(key, str):
  3369.    358                                    pass
  3370.    359                                # JavaScript is weakly typed for these, so it makes sense to
  3371.    360                                # also allow them.  Many encoders seem to do something like this.
  3372.    361                                elif isinstance(key, float):
  3373.    362                                    # see comment for int/float in _make_iterencode
  3374.    363                                    key = _floatstr(key)
  3375.    364                                elif key is True:
  3376.    365                                    key = 'true'
  3377.    366                                elif key is False:
  3378.    367                                    key = 'false'
  3379.    368                                elif key is None:
  3380.    369                                    key = 'null'
  3381.    370                                elif isinstance(key, int):
  3382.    371                                    # see comment for int/float in _make_iterencode
  3383.    372                                    key = _intstr(key)
  3384.    373                                elif _skipkeys:
  3385.    374                                    continue
  3386.    375                                else:
  3387.    376                                    raise TypeError(f'keys must be str, int, float, bool or None, '
  3388.    377                                                    f'not {key.__class__.__name__}')
  3389.    378                                if first:
  3390.    379                                    first = False
  3391.    380                                else:
  3392.    381                                    yield item_separator
  3393.    382                                yield _encoder(key)
  3394.    383                                yield _key_separator
  3395.    384                                if isinstance(value, str):
  3396.    385                                    yield _encoder(value)
  3397.    386                                elif value is None:
  3398.    387                                    yield 'null'
  3399.    388                                elif value is True:
  3400.    389                                    yield 'true'
  3401.    390                                elif value is False:
  3402.    391                                    yield 'false'
  3403.    392                                elif isinstance(value, int):
  3404.    393                                    # see comment for int/float in _make_iterencode
  3405.    394                                    yield _intstr(value)
  3406.    395                                elif isinstance(value, float):
  3407.    396                                    # see comment for int/float in _make_iterencode
  3408.    397                                    yield _floatstr(value)
  3409.    398                                else:
  3410.    399                                    if isinstance(value, (list, tuple)):
  3411.    400                                        chunks = _iterencode_list(value, _current_indent_level)
  3412.    401                                    elif isinstance(value, dict):
  3413.    402                                        chunks = _iterencode_dict(value, _current_indent_level)
  3414.    403                                    else:
  3415.    404                                        chunks = _iterencode(value, _current_indent_level)
  3416.    405        3    100.0                  yield from chunks
  3417.    406                            if newline_indent is not None:
  3418.    407                                _current_indent_level -= 1
  3419.    408                                yield '\n' + _indent * _current_indent_level
  3420.    409                            yield '}'
  3421.    410                            if markers is not None:
  3422.    411                                del markers[markerid]
  3423.  
  3424. Total hits: 3 s
  3425. File: /Users/300041709/.pyenv/versions/3.7.2/lib/python3.7/json/encoder.py
  3426. Function: _iterencode_list at line 277
  3427.  
  3428. Line #     Hits   % Hits  Line Contents
  3429. =======================================
  3430.    277                        def _iterencode_list(lst, _current_indent_level):
  3431.    278                            if not lst:
  3432.    279                                yield '[]'
  3433.    280                                return
  3434.    281                            if markers is not None:
  3435.    282                                markerid = id(lst)
  3436.    283                                if markerid in markers:
  3437.    284                                    raise ValueError("Circular reference detected")
  3438.    285                                markers[markerid] = lst
  3439.    286        1     33.3          buf = '['
  3440.    287                            if _indent is not None:
  3441.    288                                _current_indent_level += 1
  3442.    289                                newline_indent = '\n' + _indent * _current_indent_level
  3443.    290                                separator = _item_separator + newline_indent
  3444.    291                                buf += newline_indent
  3445.    292                            else:
  3446.    293                                newline_indent = None
  3447.    294                                separator = _item_separator
  3448.    295                            first = True
  3449.    296                            for value in lst:
  3450.    297                                if first:
  3451.    298                                    first = False
  3452.    299                                else:
  3453.    300                                    buf = separator
  3454.    301                                if isinstance(value, str):
  3455.    302                                    yield buf + _encoder(value)
  3456.    303                                elif value is None:
  3457.    304                                    yield buf + 'null'
  3458.    305                                elif value is True:
  3459.    306                                    yield buf + 'true'
  3460.    307                                elif value is False:
  3461.    308                                    yield buf + 'false'
  3462.    309                                elif isinstance(value, int):
  3463.    310                                    # Subclasses of int/float may override __str__, but we still
  3464.    311                                    # want to encode them as integers/floats in JSON. One example
  3465.    312                                    # within the standard library is IntEnum.
  3466.    313                                    yield buf + _intstr(value)
  3467.    314                                elif isinstance(value, float):
  3468.    315                                    # see comment above for int
  3469.    316                                    yield buf + _floatstr(value)
  3470.    317                                else:
  3471.    318                                    yield buf
  3472.    319                                    if isinstance(value, (list, tuple)):
  3473.    320                                        chunks = _iterencode_list(value, _current_indent_level)
  3474.    321                                    elif isinstance(value, dict):
  3475.    322                                        chunks = _iterencode_dict(value, _current_indent_level)
  3476.    323                                    else:
  3477.    324                                        chunks = _iterencode(value, _current_indent_level)
  3478.    325        2     66.7                  yield from chunks
  3479.    326                            if newline_indent is not None:
  3480.    327                                _current_indent_level -= 1
  3481.    328                                yield '\n' + _indent * _current_indent_level
  3482.    329                            yield ']'
  3483.    330                            if markers is not None:
  3484.    331                                del markers[markerid]
Add Comment
Please, Sign In to add comment