1
- import ast
2
1
import collections
3
- import fnmatch
4
- import imp
5
2
import logging
6
3
import optparse
7
4
import os
8
- import re
9
5
import sys
10
6
11
7
from pip .commands .show import search_packages_info
12
8
from pip .download import PipSession
13
9
from pip .req import parse_requirements
14
10
from pip .utils import get_installed_distributions , normalize_name
15
11
16
- log = logging .getLogger (__name__ )
17
-
12
+ from pip_check_reqs import common
18
13
19
- class FoundModule :
20
- def __init__ (self , modname , filename , locations = None ):
21
- self .modname = modname
22
- self .filename = os .path .realpath (filename )
23
- self .locations = locations or [] # filename, lineno
24
-
25
- def __repr__ (self ):
26
- return 'FoundModule("%s")' % self .modname
27
-
28
-
29
- class ImportVisitor (ast .NodeVisitor ):
30
- def __init__ (self , options ):
31
- super (ImportVisitor , self ).__init__ ()
32
- self .__options = options
33
- self .__modules = {}
34
- self .__location = None
35
-
36
- def set_location (self , location ):
37
- self .__location = location
38
-
39
- def visit_Import (self , node ):
40
- for alias in node .names :
41
- self .__addModule (alias .name , node .lineno )
42
-
43
- def visit_ImportFrom (self , node ):
44
- if node .module == '__future__' :
45
- # not an actual module
46
- return
47
- for alias in node .names :
48
- if node .module is None :
49
- # relative import
50
- continue
51
- self .__addModule (node .module + '.' + alias .name , node .lineno )
52
-
53
- def __addModule (self , modname , lineno ):
54
- if self .__options .ignore_mods (modname ):
55
- return
56
- path = None
57
- progress = []
58
- modpath = last_modpath = None
59
- for p in modname .split ('.' ):
60
- try :
61
- file , modpath , description = imp .find_module (p , path )
62
- except ImportError :
63
- # the component specified at this point is not importable
64
- # (is just an attr of the module)
65
- # *or* it's not actually installed, so we don't care either
66
- break
67
-
68
- # success! we found *something*
69
- progress .append (p )
70
-
71
- # we might have previously seen a useful path though...
72
- if modpath is None : # pragma: no cover
73
- # the sys module will hit this code path on py3k - possibly
74
- # others will, but I've not discovered them
75
- modpath = last_modpath
76
- break
77
-
78
- # ... though it might not be a file, so not interesting to us
79
- if not os .path .isdir (modpath ):
80
- break
81
-
82
- path = [modpath ]
83
- last_modpath = modpath
84
-
85
- if modpath is None :
86
- # the module doesn't actually appear to exist on disk
87
- return
88
-
89
- modname = '.' .join (progress )
90
- if modname not in self .__modules :
91
- self .__modules [modname ] = FoundModule (modname , modpath )
92
- self .__modules [modname ].locations .append ((self .__location , lineno ))
93
-
94
- def finalise (self ):
95
- return self .__modules
96
-
97
-
98
- def pyfiles (root ):
99
- d = os .path .abspath (root )
100
- if not os .path .isdir (d ):
101
- n , ext = os .path .splitext (d )
102
- if ext == '.py' :
103
- yield d
104
- else :
105
- raise ValueError ('%s is not a python file or directory' % root )
106
- for root , dirs , files in os .walk (d ):
107
- for f in files :
108
- n , ext = os .path .splitext (f )
109
- if ext == '.py' :
110
- yield os .path .join (root , f )
111
-
112
-
113
- def find_imported_modules (options ):
114
- vis = ImportVisitor (options )
115
- for path in options .paths :
116
- for filename in pyfiles (path ):
117
- if options .ignore_files (filename ):
118
- log .info ('ignoring: %s' , os .path .relpath (filename ))
119
- continue
120
- log .debug ('scanning: %s' , os .path .relpath (filename ))
121
- with open (filename ) as f :
122
- content = f .read ()
123
- vis .set_location (filename )
124
- vis .visit (ast .parse (content ))
125
- return vis .finalise ()
126
-
127
-
128
- def is_package_file (path ):
129
- '''Determines whether the path points to a Python package sentinel
130
- file - the __init__.py or its compiled variants.
131
- '''
132
- m = re .search ('(.+)/__init__\.py[co]?$' , path )
133
- if m is not None :
134
- return m .group (1 )
135
- return ''
14
+ log = logging .getLogger (__name__ )
136
15
137
16
138
17
def find_missing_reqs (options ):
139
18
# 1. find files used by imports in the code (as best we can without
140
19
# executing)
141
- used_modules = find_imported_modules (options )
20
+ used_modules = common . find_imported_modules (options )
142
21
143
22
# 2. find which packages provide which files
144
23
installed_files = {}
@@ -149,7 +28,7 @@ def find_missing_reqs(options):
149
28
for file in package ['files' ] or []:
150
29
path = os .path .realpath (os .path .join (package ['location' ], file ))
151
30
installed_files [path ] = package ['name' ]
152
- package_path = is_package_file (path )
31
+ package_path = common . is_package_file (path )
153
32
if package_path :
154
33
# we've seen a package file so add the bare package directory
155
34
# to the installed list as well as we might want to look up
@@ -181,20 +60,6 @@ def find_missing_reqs(options):
181
60
if name not in explicit ]
182
61
183
62
184
- def ignorer (ignore_cfg ):
185
- if not ignore_cfg :
186
- return lambda candidate : False
187
-
188
- def f (candidate , ignore_cfg = ignore_cfg ):
189
- for ignore in ignore_cfg :
190
- if fnmatch .fnmatch (candidate , ignore ):
191
- return True
192
- elif fnmatch .fnmatch (os .path .relpath (candidate ), ignore ):
193
- return True
194
- return False
195
- return f
196
-
197
-
198
63
def main ():
199
64
from pip_check_reqs import __version__
200
65
@@ -222,8 +87,8 @@ def main():
222
87
parser .error ("no source files or directories specified" )
223
88
sys .exit (2 )
224
89
225
- options .ignore_files = ignorer (options .ignore_files )
226
- options .ignore_mods = ignorer (options .ignore_mods )
90
+ options .ignore_files = common . ignorer (options .ignore_files )
91
+ options .ignore_mods = common . ignorer (options .ignore_mods )
227
92
228
93
options .paths = args
229
94
0 commit comments