99#
1010"""Generate requirements from `setup.py` and `requirements-devel.txt`."""
1111
12- from __future__ import absolute_import , print_function
12+ from __future__ import absolute_import
13+ from __future__ import print_function
1314
1415import os
1516import re
@@ -37,18 +38,16 @@ def parse_set(string):
3738def minver_error (pkg_name ):
3839 """Report error about missing minimum version constraint and exit."""
3940 print (
40- 'ERROR: specify minimal version of "{0}" using '
41- '">=" or "=="' .format (pkg_name ),
42- file = sys .stderr
41+ 'ERROR: specify minimal version of "{0}" using ' '">=" or "=="' .format (pkg_name ),
42+ file = sys .stderr ,
4343 )
4444 sys .exit (1 )
4545
4646
4747def build_pkg_name (pkg ):
4848 """Build package name, including extras if present."""
4949 if pkg .extras :
50- return '{0}[{1}]' .format (
51- pkg .project_name , ',' .join (sorted (pkg .extras )))
50+ return "{0}[{1}]" .format (pkg .project_name , "," .join (sorted (pkg .extras )))
5251 return pkg .project_name
5352
5453
@@ -66,96 +65,77 @@ def parse_pip_file(path):
6665 line = line .strip ()
6766
6867 # see https://pip.readthedocs.io/en/1.1/requirements.html
69- if line .startswith ('-e' ):
68+ if line .startswith ("-e" ):
7069 # devel requirement
71- splitted = line .split (' #egg=' )
70+ splitted = line .split (" #egg=" )
7271 rdev [splitted [1 ].lower ()] = line
7372
74- elif line .startswith ('-r' ):
73+ elif line .startswith ("-r" ):
7574 # recursive file command
76- splitted = re .split (' -r\\ s+' , line )
75+ splitted = re .split (" -r\\ s+" , line )
7776 subrdev , subrnormal , substuff = parse_pip_file (
7877 os .path .join (os .path .dirname (path ), splitted [1 ])
7978 )
8079 for k , v in subrdev .items ():
8180 if k not in rdev :
8281 rdev [k ] = v
8382 rnormal .extend (subrnormal )
84- elif line .startswith ('-' ):
83+ elif line .startswith ("-" ):
8584 # another special command we don't recognize
8685 stuff .append (line )
8786 else :
8887 # ordinary requirement, similarly to them used in setup.py
8988 rnormal .append (line )
9089 except IOError :
91- print (
92- 'Warning: could not parse requirements file "{0}"!' .format (path ),
93- file = sys .stderr
94- )
90+ print ('Warning: could not parse requirements file "{0}"!' .format (path ), file = sys .stderr )
9591
9692 return rdev , rnormal , stuff
9793
9894
99- def iter_requirements (level , extras , pip_file , setup_fp , setup_cfg_fp = None ):
95+ def iter_requirements (level , extras , setup_file ):
10096 """Iterate over requirements."""
97+ from pathlib import Path
98+
99+ setup_file = str (Path (setup_file ).absolute ())
101100 result = dict ()
102101 requires = []
103102 stuff = []
104- if level == 'dev' or setup_fp is None :
105- result , requires , stuff = parse_pip_file (pip_file )
106-
103+ cd = os .getcwd ()
104+ os .chdir (os .path .dirname (setup_file ))
107105 install_requires = []
108106 requires_extras = {}
109- if setup_fp is not None :
110- with mock .patch .object (setuptools , 'setup' ) as mock_setup :
111- sys .path .append (os .path .dirname (setup_fp .name ))
112- g = {'__file__' : setup_fp .name , '__name__' : '__main__' }
113- exec (setup_fp .read (), g )
114- sys .path .pop ()
115- assert g ['setup' ] # silence warning about unused imports
116-
117- # called arguments are in `mock_setup.call_args`
118- mock_args , mock_kwargs = mock_setup .call_args
119- install_requires = mock_kwargs .get (
120- 'install_requires' , install_requires
121- )
122- requires_extras = mock_kwargs .get ('extras_require' , requires_extras )
123-
124- if setup_cfg_fp is not None :
125- parser = configparser .ConfigParser ()
126- parser .read_file (setup_cfg_fp )
127-
128- if parser .has_section ("options" ):
129- value = parser .get ("options" , "install_requires" ,
130- fallback = "" ).strip ()
131-
132- if value :
133- install_requires = [s .strip () for s in value .splitlines ()]
134-
135- if parser .has_section ("options.extras_require" ):
136- for name , value in parser .items ("options.extras_require" ):
137- requires_extras [name ] = [s .strip ()
138- for s in value .strip ().splitlines ()]
139-
140- install_requires .extend (requires )
107+ # change directory to setup.py path
108+ with mock .patch .object (setuptools , "setup" ) as mock_setup :
109+ sys .path .append (os .path .dirname (setup_file ))
110+ g = {"__file__" : setup_file , "__name__" : "__main__" }
111+ with open (setup_file ) as sf :
112+ exec (sf .read (), g )
113+ sys .path .pop ()
114+ assert g ["setup" ] # silence warning about unused imports
115+ # called arguments are in `mock_setup.call_args`
116+ os .chdir (cd )
117+ mock_args , mock_kwargs = mock_setup .call_args
118+ install_requires = mock_kwargs .get ("install_requires" , install_requires )
119+
120+ requires_extras = mock_kwargs .get ("extras_require" , requires_extras )
141121
142122 for e , reqs in requires_extras .items ():
143123 # Handle conditions on extras. See pkginfo_to_metadata function
144124 # in Wheel for details.
145- condition = ''
146- if ':' in e :
147- e , condition = e .split (':' , 1 )
125+ condition = ""
126+ if ":" in e :
127+ e , condition = e .split (":" , 1 )
148128 if not e or e in extras :
149129 if condition :
150- reqs = [' {0}; {1}' .format (r , condition ) for r in reqs ]
130+ reqs = [" {0}; {1}" .format (r , condition ) for r in reqs ]
151131 install_requires .extend (reqs )
152132
153133 for pkg in pkg_resources .parse_requirements (install_requires ):
154134 # skip things we already know
155135 # FIXME be smarter about merging things
156136
157137 # Evaluate environment markers skip if not applicable
158- if hasattr (pkg , ' marker' ) and pkg .marker is not None :
138+ if hasattr (pkg , " marker" ) and pkg .marker is not None :
159139 if not pkg .marker .evaluate ():
160140 continue
161141 else :
@@ -166,44 +146,37 @@ def iter_requirements(level, extras, pip_file, setup_fp, setup_cfg_fp=None):
166146 continue
167147
168148 specs = dict (pkg .specs )
169- if (('>=' in specs ) and ('>' in specs )) \
170- or (('<=' in specs ) and ('<' in specs )):
149+ if ((">=" in specs ) and (">" in specs )) or (("<=" in specs ) and ("<" in specs )):
171150 print (
172- 'ERROR: Do not specify such weird constraints! '
173- '("{0}")' .format (pkg ),
174- file = sys .stderr
151+ "ERROR: Do not specify such weird constraints! " '("{0}")' .format (pkg ),
152+ file = sys .stderr ,
175153 )
176154 sys .exit (1 )
177155
178- if '==' in specs :
179- result [pkg .key ] = '{0}=={1}' .format (
180- build_pkg_name (pkg ), specs ['==' ])
156+ if "==" in specs :
157+ result [pkg .key ] = "{0}=={1}" .format (build_pkg_name (pkg ), specs ["==" ])
181158
182- elif '>=' in specs :
183- if level == 'min' :
184- result [pkg .key ] = '{0}=={1}' .format (
185- build_pkg_name (pkg ), specs ['>=' ]
186- )
159+ elif ">=" in specs :
160+ if level == "min" :
161+ result [pkg .key ] = "{0}=={1}" .format (build_pkg_name (pkg ), specs [">=" ])
187162 else :
188163 result [pkg .key ] = pkg
189164
190- elif '>' in specs :
191- if level == ' min' :
165+ elif ">" in specs :
166+ if level == " min" :
192167 minver_error (build_pkg_name (pkg ))
193168 else :
194169 result [pkg .key ] = pkg
195170
196- elif '~=' in specs :
197- if level == 'min' :
198- result [pkg .key ] = '{0}=={1}' .format (
199- build_pkg_name (pkg ), specs ['~=' ])
171+ elif "~=" in specs :
172+ if level == "min" :
173+ result [pkg .key ] = "{0}=={1}" .format (build_pkg_name (pkg ), specs ["~=" ])
200174 else :
201- ver , _ = os .path .splitext (specs ['~=' ])
202- result [pkg .key ] = '{0}>={1},=={2}.*' .format (
203- build_pkg_name (pkg ), specs ['~=' ], ver )
175+ ver , _ = os .path .splitext (specs ["~=" ])
176+ result [pkg .key ] = "{0}>={1},=={2}.*" .format (build_pkg_name (pkg ), specs ["~=" ], ver )
204177
205178 else :
206- if level == ' min' :
179+ if level == " min" :
207180 minver_error (build_pkg_name (pkg ))
208181 else :
209182 result [pkg .key ] = build_pkg_name (pkg )
0 commit comments