Coverage for /home/tbone/mambaforge/lib/python3.9/site-packages/importnb/decoder.py: 93%

1 import json

2 import linecache

3 import textwrap

4 from functools import partial

5

6

7 def quote(object, *, quotes="'''"):

8 if quotes in object:

9 quotes = '"""'

10 return quotes + object + "\n" + quotes

11

12

13 from ._json_parser import Lark_StandAlone, Transformer

14

15

16 class Transformer(Transformer):

17 def __init__(

18 self,

19 markdown=quote,

20 code=textwrap.dedent,

21 raw=partial(textwrap.indent, prefix="# "),

22 **kwargs,

23 ):

24 super().__init__(**kwargs)

25

26 for key in ("markdown", "code", "raw"):

27 setattr(self, "transform_" + key, locals().get(key))

28

29 def string(self, s):

30 return s[0].line, json.loads(s[0])

31

32 def item(self, s):

33 key = s[0][-1]

34 if key == "cells":

35 return self.render(list(map(dict, s[-1])))

36 elif key in {"source", "text"}:

37 return key, s[-1]

38 elif key == "cell_type":

39 return key, s[-1][-1]

40

41 def array(self, s):

42 if s:

43 return s

44 return []

45

46 def object(self, s):

47 return [x for x in s if x is not None]

48

49 def render_one(self, kind, lines):

50 s = "".join(lines)

51 if not s.endswith(("\n",)):

52 s += "\n"

53 return getattr(self, f"transform_{kind}")(s)

54

55 def render(self, x):

56 body = []

57 for token in x:

58 t = token.get("cell_type")

59 try:

60 s = token["source"]

61 except KeyError:

62 s = token.get("text")

63 if s:

64 if not isinstance(s, list):

65 s = [s]

66 l, lines = s[0][0], [x[1] for x in s]

67 body.extend([""] * (l - len(body)))

68 lines = self.render_one(t, lines)

69 body.extend(lines.splitlines())

70 return "\n".join(body + [""])

71

72

73 class LineCacheNotebookDecoder(Transformer):

74 def __init__(

75 self,

76 markdown=quote,

77 code=textwrap.dedent,

78 raw=partial(textwrap.indent, prefix="# "),

79 **kwargs,

80 ):

81 super().__init__(**kwargs)

82

83 for key in ("markdown", "code", "raw"):

84 setattr(self, "transform_" + key, locals().get(key))

85

86 def source_from_json_grammar(self, object):

87 return Lark_StandAlone(transformer=self).parse(object)

88

89 def decode(self, object, filename):

90 s = self.source_from_json_grammar(object)

91 if s:

92 source = s[0]

93 linecache.updatecache(filename)

94 if filename in linecache.cache:

95 linecache.cache[filename] = (

96 linecache.cache[filename][0],

97 linecache.cache[filename][1],

98 source.splitlines(True),

99 filename,

100 )

101 return source

102 return ""