Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/autograph/pyct/loader.py: 32%

37 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================== 

15"""Converting AST to code and Python entities. 

16 

17Adapted from Tangent. 

18""" 

19 

20import atexit 

21import errno 

22import importlib 

23import os 

24import sys 

25import tempfile 

26 

27from tensorflow.python.autograph.pyct import origin_info 

28from tensorflow.python.autograph.pyct import parser 

29 

30 

31def _remove_file(file_name): 

32 """Remove a file, if it exists.""" 

33 try: 

34 os.remove(file_name) 

35 except OSError as e: 

36 if e.errno == errno.ENOENT: 

37 # The file disappeared. Ignore this. Temporary files might get 

38 # cleaned up, especially if they reside in /tmp. 

39 pass 

40 else: 

41 raise 

42 

43 

44def load_source(source, delete_on_exit): 

45 """Loads the given source code as a Python module.""" 

46 with tempfile.NamedTemporaryFile( 

47 mode='w', 

48 suffix='.py', 

49 prefix='__autograph_generated_file', 

50 delete=False, 

51 encoding='utf-8') as f: 

52 module_name = os.path.basename(f.name[:-3]) 

53 file_name = f.name 

54 f.write(source) 

55 

56 if delete_on_exit: 

57 atexit.register(lambda: _remove_file(file_name)) 

58 

59 spec = importlib.util.spec_from_file_location(module_name, file_name) 

60 module = importlib.util.module_from_spec(spec) 

61 spec.loader.exec_module(module) 

62 # TODO(mdan): Use our own garbage-collected cache instead of sys.modules. 

63 sys.modules[module_name] = module 

64 return module, file_name 

65 

66 

67def load_ast(nodes, 

68 indentation=' ', 

69 include_source_map=False, 

70 delete_on_exit=True): 

71 """Loads the given AST as a Python module. 

72 

73 Compiling the AST code this way ensures that the source code is readable by 

74 e.g. `pdb` or `inspect`. 

75 

76 Args: 

77 nodes: Union[ast.AST, Iterable[ast.AST]], the code to compile, as an AST 

78 object. 

79 indentation: Text, the string to use for indentation. 

80 include_source_map: bool, whether return a source map. 

81 delete_on_exit: bool, whether to delete the temporary file used for 

82 compilation on exit. 

83 

84 Returns: 

85 Tuple[module, Text, Dict[LineLocation, OriginInfo]], containing: 

86 the module containing the unparsed nodes, the source code corresponding to 

87 nodes, and the source map. Is include_source_map is False, the source map 

88 will be None. 

89 """ 

90 if not isinstance(nodes, (list, tuple)): 

91 nodes = (nodes,) 

92 

93 source = parser.unparse(nodes, indentation=indentation) 

94 module, _ = load_source(source, delete_on_exit) 

95 

96 if include_source_map: 

97 source_map = origin_info.create_source_map(nodes, source, module.__file__) 

98 else: 

99 source_map = None 

100 

101 # TODO(mdan): Return a structured object. 

102 return module, source, source_map