1
+ #!/usr/bin/env python
2
+ # encoding: utf-8
3
+ #
4
+ # Copyright © 2022, SAS Institute Inc., Cary, NC, USA. All Rights Reserved.
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ import logging
7
+ import sys
8
+
9
+ def findPackageBytecodes (inst ):
10
+ from types import CodeType , FunctionType , ModuleType
11
+ from importlib import import_module
12
+ from functools import reduce
13
+
14
+ if inst .opname == "IMPORT_NAME" :
15
+ path = inst .argval .split ("." )
16
+ path [0 ] = [import_module (path [0 ])]
17
+ result = reduce (lambda x , a : x + [getattr (x [- 1 ], a )], path )
18
+ return ("modules" , result )
19
+ if inst .opname == "LOAD_GLOBAL" :
20
+ if inst .argval in globals () and type (globals ()[inst .argval ]) in [CodeType , FunctionType ]:
21
+ return ("code" , globals ()[inst .argval ])
22
+ if inst .argval in globals () and type (globals ()[inst .argval ]) == ModuleType :
23
+ return ("modules" , [globals ()[inst .argval ]])
24
+ else :
25
+ return None
26
+ if "LOAD_" in inst .opname and type (inst .argval ) in [CodeType , FunctionType ]:
27
+ return ("code" , inst .argval )
28
+ return None
29
+
30
+ def getFunctionPackages (func ):
31
+ import inspect
32
+ from dis import Bytecode
33
+ workList = [func ]
34
+ seen = set ()
35
+ mods = set ()
36
+ logging .debug ("workList type = %s, len = %d" % (type (workList ), len (workList )))
37
+ logging .debug (workList )
38
+ for fn in workList :
39
+ if (hasattr (fn ,"__name__" )):
40
+ if fn .__name__ == "getFunctionPackages" :
41
+ logging .debug ("Preemptively skip %s " % fn .__name__ )
42
+ workList .remove (fn )
43
+ elif fn .__name__ == "findPackageBytecodes" :
44
+ logging .debug ("Preemptively skip %s " % fn .__name__ )
45
+ workList .remove (fn )
46
+ else :
47
+ logging .debug ("Letting through name %s" % fn .__name__ )
48
+ else :
49
+ print ("Letting through %s" % fn )
50
+ for fn in workList :
51
+ codeworkList = [fn ]
52
+ logging .debug ("In workList :" , end = '' )
53
+ logging .debug (fn )
54
+ try :
55
+ closureVars = inspect .getclosurevars (fn ).globals
56
+ for var , ref in closureVars .items ():
57
+ if (var != 'getFunctionPackages' ):
58
+ if inspect .ismodule (ref ):
59
+ mods .add (ref .__name__ )
60
+ elif inspect .isfunction (ref ) and id (ref ) not in seen :
61
+ seen .add (id (ref ))
62
+ mods .add (ref .__module__ )
63
+ if (hasattr (ref , '__name__' )):
64
+ if fn .__name__ == "getFunctionPackages" :
65
+ logging .debug ("A- Not adding to workList %s " % fn .__name__ )
66
+ elif fn .__name__ == "findPackageBytecodes" :
67
+ logging .debug ("A- Not adding to workList %s " % fn .__name__ )
68
+ else :
69
+ logging .debug ("A- Adding to workList: %s" % ref )
70
+ workList .append (ref )
71
+ else :
72
+ logging .debug ("A- Adding to workList: %s" % ref )
73
+ workList .append (ref )
74
+ elif hasattr (ref , "__module__" ):
75
+ logging .debug ("1 fn=%s, k=%s, v=%s" % (fn , var , ref .__module__ ))
76
+ mods .add (ref .__module__ )
77
+ for block in codeworkList :
78
+ for (bType , bRef ) in [findPackageBytecodes (inst ) for inst in Bytecode (block ) if findPackageBytecodes (inst )]:
79
+ if bType == "modules" :
80
+ newmods = [mod .__name__ for mod in bRef if hasattr (mod , "__name__" )]
81
+ for mo in newmods :
82
+ if mo == "getFunctionPackages" :
83
+ logging .debug ("Also skip %s " % mo )
84
+ newmods .remove (mo )
85
+ elif mo == "findPackageBytecodes" :
86
+ logging .debug ("Also skip %s " % mo )
87
+ newmods .remove (mo )
88
+ else :
89
+ logging .debug ("2 fn=%s, k=%s, bRef=%s" % (fn , bType , mo ))
90
+ mods .update (set (newmods ))
91
+ elif bType == "code" and id (bRef ) not in seen :
92
+ seen .add (id (bRef ))
93
+ if hasattr (bRef , "__module__" ):
94
+ if bRef .__name__ != "getFunctionPackages" or bRef .__name__ != "findPackageBytecodes" :
95
+ logging .debug ("3 fn=%s, bType=%s, bRef=%s" % (fn , bType , bRef ))
96
+ mods .add (bRef .__module__ )
97
+ if (inspect .isfunction (bRef )):
98
+ if (hasattr (bRef , '__name__' )):
99
+ if bRef .__name__ .find ("getFunctionPackages" ) != - 1 :
100
+ logging .debug ("B- Not adding to workList %s " % bRef .__name__ )
101
+ elif bRef .__name__ .find ("findPackageBytecodes" ) != - 1 :
102
+ logging .debug ("B- Not adding to workList %s " % bRef .__name__ )
103
+ else :
104
+ logging .debug ("B- Adding to workList 1: %s" % bRef .__name__ )
105
+ workList .append (bRef )
106
+ else :
107
+ logging .debug ("B- Adding to workList 2: %s" % bRef )
108
+ logging .debug (dir (bRef ))
109
+ workList .append (bRef )
110
+ elif (inspect .iscode (bRef )):
111
+ codeworkList .append (bRef )
112
+ except TypeError :
113
+ continue
114
+ result = list (mods )
115
+ result .sort ()
116
+ return result
117
+
118
+ def findDependencies ():
119
+ dependencies = ""
120
+ mySymbols = []
121
+ logging .debug (globals ().keys ())
122
+ try :
123
+ mySymbols = list (globals ().keys ())
124
+ mySymbols .remove ("getFunctionPackages" )
125
+ mySymbols .remove ("findPackageBytecodes" )
126
+ for symbol in mySymbols :
127
+ if symbol .startswith ("__" ):
128
+ logging .debug ("removing %s" % symbol )
129
+ mySymbols .remove (symbol )
130
+ if symbol .startswith ("'" ):
131
+ logging .debug ("removing %s" % symbol )
132
+ mySymbols .remove (symbol )
133
+ allList = []
134
+ for symbol in mySymbols :
135
+ logging .debu ("Symbol=%s" % symbol )
136
+ subList = getFunctionPackages (globals ()[symbol ])
137
+ allList = allList + subList
138
+ logging .debug ('%s : %s' % (symbol , allList ))
139
+ uniqueList = set (allList )
140
+ dependencies = "," .join (uniqueList )
141
+ except :
142
+ logging .debug (sys .exc_info ()[0 ] + " occurred." )
143
+ dependencies = "," .join (sys .exc_info ())
144
+ symbols = "," .join (mySymbols )
145
+ return symbols , dependencies
0 commit comments