@@ -27,6 +27,11 @@ class Factory(object):
2727 Factory class to create various elements needed by Poetry.
2828 """
2929
30+ DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP = {
31+ "allows_prereleases" : "allow_prereleases" ,
32+ "develop" : "editable" ,
33+ }
34+
3035 def create_poetry (
3136 self , cwd = None , with_dev = True
3237 ): # type: (Optional[Path]. bool) -> Poetry
@@ -182,49 +187,40 @@ def create_dependency(
182187 constraint = "*"
183188
184189 if isinstance (constraint , dict ):
185- optional = constraint .get ("optional" , False )
186- python_versions = constraint .get ("python" )
187- platform = constraint .get ("platform" )
188- markers = constraint .get ("markers" )
189- if "allows-prereleases" in constraint :
190- message = (
191- 'The "{}" dependency specifies '
192- 'the "allows-prereleases" property, which is deprecated. '
193- 'Use "allow-prereleases" instead.' .format (name )
194- )
195- warn (message , DeprecationWarning )
196- logger .warning (message )
197-
198- allows_prereleases = constraint .get (
199- "allow-prereleases" , constraint .get ("allows-prereleases" , False )
190+ constraint_without_deprecated_keys = cls .as_constraint_with_deprecated_keys_renamed_to_current_keys (
191+ dependency_name = name , constraint = constraint ,
200192 )
193+ optional = constraint_without_deprecated_keys .get ("optional" , False )
194+ python_versions = constraint_without_deprecated_keys .get ("python" )
195+ platform = constraint_without_deprecated_keys .get ("platform" )
196+ markers = constraint_without_deprecated_keys .get ("markers" )
201197
202- if "git" in constraint :
198+ if "git" in constraint_without_deprecated_keys :
203199 # VCS dependency
204200 dependency = VCSDependency (
205201 name ,
206202 "git" ,
207- constraint ["git" ],
208- branch = constraint .get ("branch" , None ),
209- tag = constraint .get ("tag" , None ),
210- rev = constraint .get ("rev" , None ),
203+ constraint_without_deprecated_keys ["git" ],
204+ branch = constraint_without_deprecated_keys .get ("branch" , None ),
205+ tag = constraint_without_deprecated_keys .get ("tag" , None ),
206+ rev = constraint_without_deprecated_keys .get ("rev" , None ),
211207 category = category ,
212208 optional = optional ,
213- develop = constraint .get ("develop " , False ),
214- extras = constraint .get ("extras" , []),
209+ editable = constraint_without_deprecated_keys .get ("editable " , False ),
210+ extras = constraint_without_deprecated_keys .get ("extras" , []),
215211 )
216- elif "file" in constraint :
217- file_path = Path (constraint ["file" ])
212+ elif "file" in constraint_without_deprecated_keys :
213+ file_path = Path (constraint_without_deprecated_keys ["file" ])
218214
219215 dependency = FileDependency (
220216 name ,
221217 file_path ,
222218 category = category ,
223219 base = root_dir ,
224- extras = constraint .get ("extras" , []),
220+ extras = constraint_without_deprecated_keys .get ("extras" , []),
225221 )
226- elif "path" in constraint :
227- path = Path (constraint ["path" ])
222+ elif "path" in constraint_without_deprecated_keys :
223+ path = Path (constraint_without_deprecated_keys ["path" ])
228224
229225 if root_dir :
230226 is_file = root_dir .joinpath (path ).is_file ()
@@ -238,7 +234,7 @@ def create_dependency(
238234 category = category ,
239235 optional = optional ,
240236 base = root_dir ,
241- extras = constraint .get ("extras" , []),
237+ extras = constraint_without_deprecated_keys .get ("extras" , []),
242238 )
243239 else :
244240 dependency = DirectoryDependency (
@@ -247,27 +243,31 @@ def create_dependency(
247243 category = category ,
248244 optional = optional ,
249245 base = root_dir ,
250- develop = constraint .get ("develop" , False ),
251- extras = constraint .get ("extras" , []),
246+ editable = constraint_without_deprecated_keys .get (
247+ "editable" , False
248+ ),
249+ extras = constraint_without_deprecated_keys .get ("extras" , []),
252250 )
253- elif "url" in constraint :
251+ elif "url" in constraint_without_deprecated_keys :
254252 dependency = URLDependency (
255253 name ,
256- constraint ["url" ],
254+ constraint_without_deprecated_keys ["url" ],
257255 category = category ,
258256 optional = optional ,
259- extras = constraint .get ("extras" , []),
257+ extras = constraint_without_deprecated_keys .get ("extras" , []),
260258 )
261259 else :
262- version = constraint ["version" ]
260+ version = constraint_without_deprecated_keys ["version" ]
263261
264262 dependency = Dependency (
265263 name ,
266264 version ,
267265 optional = optional ,
268266 category = category ,
269- allows_prereleases = allows_prereleases ,
270- extras = constraint .get ("extras" , []),
267+ allows_prereleases = constraint_without_deprecated_keys .get (
268+ "allow_prereleases" , False
269+ ),
270+ extras = constraint_without_deprecated_keys .get ("extras" , []),
271271 )
272272
273273 if not markers :
@@ -296,7 +296,7 @@ def create_dependency(
296296 if not marker .is_any ():
297297 dependency .marker = marker
298298
299- dependency .source_name = constraint .get ("source" )
299+ dependency .source_name = constraint_without_deprecated_keys .get ("source" )
300300 else :
301301 dependency = Dependency (name , constraint , category = category )
302302
@@ -329,12 +329,23 @@ def validate(
329329 if not isinstance (constraint , dict ):
330330 continue
331331
332- if "allows-prereleases" in constraint :
333- result ["warnings" ].append (
334- 'The "{}" dependency specifies '
335- 'the "allows-prereleases" property, which is deprecated. '
336- 'Use "allow-prereleases" instead.' .format (name )
337- )
332+ for deprecated_key in cls .deprecated_keys ():
333+ if deprecated_key in constraint :
334+ if cls .constraint_has_deprecated_key_current_key_conflict (
335+ constraint , deprecated_key
336+ ):
337+ result ["errors" ].append (
338+ cls .deprecated_constraint_key_current_key_conflict_error_message (
339+ dependency_name = name ,
340+ deprecated_key = deprecated_key ,
341+ )
342+ )
343+ else :
344+ result ["warnings" ].append (
345+ cls .constraint_key_deprecation_message (
346+ dependency_name = name , key = deprecated_key
347+ )
348+ )
338349
339350 # Checking for scripts with extras
340351 if "scripts" in config :
@@ -371,3 +382,84 @@ def locate(cls, cwd): # type: (Path) -> Path
371382 cwd
372383 )
373384 )
385+
386+ @classmethod
387+ def deprecated_keys (cls ):
388+ for key in cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP :
389+ yield key
390+
391+ @classmethod
392+ def as_constraint_with_deprecated_keys_renamed_to_current_keys (
393+ cls , dependency_name , constraint
394+ ):
395+ constraint_with_renamed_keys = {}
396+ for key , value in constraint .items ():
397+ if cls .is_deprecated_constraint_key (key ):
398+ cls .raise_on_deprecated_constraint_key_current_key_conflict (
399+ dependency_name , constraint , key
400+ )
401+ cls .warn_constraint_key_is_deprecated (dependency_name , key )
402+ current_key = cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP [key ]
403+ constraint_with_renamed_keys [current_key ] = value
404+ else :
405+ constraint_with_renamed_keys [key ] = value
406+ return constraint_with_renamed_keys
407+
408+ @classmethod
409+ def raise_on_deprecated_constraint_key_current_key_conflict (
410+ cls , dependency_name , constraint , deprecated_key
411+ ):
412+ """Raise `RuntimeError` when both a deprecated key and it's current, updated counterpart (key) are contained in constraint."""
413+ if cls .constraint_has_deprecated_key_current_key_conflict (
414+ constraint , deprecated_key
415+ ):
416+ raise RuntimeError (
417+ cls .deprecated_constraint_key_current_key_conflict_error_message (
418+ dependency_name , deprecated_key ,
419+ )
420+ )
421+
422+ @classmethod
423+ def constraint_has_deprecated_key_current_key_conflict (
424+ cls , constraint , deprecated_key
425+ ):
426+ current_key = cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP [deprecated_key ]
427+ return current_key in constraint
428+
429+ @classmethod
430+ def deprecated_constraint_key_current_key_conflict_error_message (
431+ cls , dependency_name , deprecated_key
432+ ):
433+ current_key = cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP [deprecated_key ]
434+ return (
435+ 'The "{dependency_name}" dependency specifies '
436+ 'both the "{current_key}" property and the deprecated "{deprecated_key}" property. '
437+ 'Please remove "{deprecated_key}" and resolve value conflicts!' .format (
438+ dependency_name = dependency_name ,
439+ current_key = current_key ,
440+ deprecated_key = deprecated_key ,
441+ )
442+ )
443+
444+ @classmethod
445+ def is_deprecated_constraint_key (cls , key ):
446+ return key in cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP
447+
448+ @classmethod
449+ def warn_constraint_key_is_deprecated (cls , dependency_name , key ):
450+ message = cls .constraint_key_deprecation_message (dependency_name , key )
451+ warn (message , DeprecationWarning )
452+ logging .warning (message )
453+
454+ @classmethod
455+ def constraint_key_deprecation_message (cls , dependency_name , key ):
456+ current_key = cls .DEPRECATED_CONSTRAINT_KEY_CURRENT_KEY_MAP [key ]
457+ return (
458+ 'The "{dependency_name}" dependency specifies '
459+ 'the "{deprecated_key}" property, which is deprecated. '
460+ 'Use "{current_key}" instead.' .format (
461+ dependency_name = dependency_name ,
462+ deprecated_key = key ,
463+ current_key = current_key ,
464+ )
465+ )
0 commit comments