1010
1111Notably, does not read setup.py or attempt to emulate anything that can't be read staticly.
1212"""
13-
13+ import re
1414from pathlib import Path
1515
1616try :
2424
2525from .types import BasicMetadata
2626
27+ OPERATOR_RE = re .compile (r"([<>=~]+)(\d.*)" )
28+
29+
30+ def combine_markers (* markers : str ) -> str :
31+ filtered_markers = [m for m in markers if m and m .strip ()]
32+ if len (filtered_markers ) == 0 :
33+ return ""
34+ elif len (filtered_markers ) == 1 :
35+ return filtered_markers [0 ]
36+ else :
37+ return " and " .join (f"({ m } )" for m in filtered_markers )
38+
2739
28- def merge_markers (extra_name : str , value : str ) -> str :
40+ def merge_extra_marker (extra_name : str , value : str ) -> str :
2941 """Simulates what a dist-info requirement string would look like if also restricted to an extra."""
3042 if ";" not in value :
3143 return f'{ value } ; extra == "{ extra_name } "'
3244 else :
3345 a , _ , b = value .partition (";" )
3446 a = a .strip ()
3547 b = b .strip ()
36- return f'{ a } ; ({ b } ) and extra == "{ extra_name } "'
48+ c = f'extra == "{ extra_name } "'
49+ return f"{ a } ; { combine_markers (b , c )} "
3750
3851
3952def from_source_checkout (path : Path ) -> bytes :
@@ -61,7 +74,7 @@ def from_pep621_checkout(path: Path) -> bytes:
6174 extra_name = canonicalize_name (k )
6275 buf .append (f"Provides-Extra: { extra_name } \n " )
6376 for i in v :
64- buf .append ("Requires-Dist: " + merge_markers (extra_name , i ) + "\n " )
77+ buf .append ("Requires-Dist: " + merge_extra_marker (extra_name , i ) + "\n " )
6578
6679 return "" .join (buf ).encode ("utf-8" )
6780
@@ -127,10 +140,21 @@ def from_poetry_checkout(path: Path) -> bytes:
127140 extras = "[%s]" % ("," .join (v ["extras" ]))
128141 else :
129142 extras = ""
143+ markers = v .get ("markers" , "" )
144+ python = v .get ("python" , "" )
145+ if python :
146+ m = OPERATOR_RE .fullmatch (python )
147+ assert m is not None
148+ # TODO do ^/~ work on python version?
149+ python = f"python_version { m .group (1 )} '{ m .group (2 )} '"
150+ markers = combine_markers (markers , python )
151+ if markers :
152+ markers = " ; " + markers
130153 optional = v .get ("optional" , False )
131154 else :
132155 version = v
133156 extras = ""
157+ markers = ""
134158 optional = False
135159
136160 if not version :
@@ -150,17 +174,18 @@ def from_poetry_checkout(path: Path) -> bytes:
150174 version = "==" + version
151175
152176 if optional :
153- saved_extra_constraints [k ] = f"{ extras } { version } "
177+ saved_extra_constraints [k ] = ( f"{ extras } { version } " , markers )
154178 else :
155- buf .append (f"Requires-Dist: { k } { extras } { version } \n " )
179+ buf .append (f"Requires-Dist: { k } { extras } { version } { markers } \n " )
156180
157181 for k , v in doc .get ("tool" , {}).get ("poetry" , {}).get ("extras" , {}).items ():
158182 k = canonicalize_name (k )
159183 buf .append (f"Provides-Extra: { k } \n " )
160184 for vi in v :
161185 vi = canonicalize_name (vi )
186+ constraints , markers = saved_extra_constraints [vi ]
162187 buf .append (
163- f"Requires-Dist: { vi } { merge_markers (k , saved_extra_constraints [ vi ] )} "
188+ f"Requires-Dist: { vi } { constraints } { merge_extra_marker (k , markers )} "
164189 )
165190
166191 return "" .join (buf ).encode ("utf-8" )
@@ -195,7 +220,9 @@ def from_setup_cfg_checkout(path: Path) -> bytes:
195220 for i in v .splitlines ():
196221 i = i .strip ()
197222 if i :
198- buf .append ("Requires-Dist: " + merge_markers (extra_name , i ) + "\n " )
223+ buf .append (
224+ "Requires-Dist: " + merge_extra_marker (extra_name , i ) + "\n "
225+ )
199226
200227 return "" .join (buf ).encode ("utf-8" )
201228
0 commit comments