1
1
import itertools
2
+ import json
2
3
3
4
from pathlib import Path
5
+ from typing import TYPE_CHECKING
4
6
from typing import Set
7
+ from typing import Tuple
5
8
from typing import Union
6
9
7
10
from poetry .core .packages .package import Package
11
+ from poetry .core .packages .utils .utils import url_to_path
12
+ from poetry .core .utils .helpers import canonicalize_name
8
13
from poetry .core .utils .helpers import module_name
9
14
from poetry .utils ._compat import metadata
10
15
from poetry .utils .env import Env
14
19
15
20
_VENDORS = Path (__file__ ).parent .parent .joinpath ("_vendor" )
16
21
22
+ if TYPE_CHECKING :
23
+ from importlib .metadata import Distribution
24
+
17
25
18
26
try :
19
27
FileNotFoundError
@@ -68,21 +76,14 @@ def get_package_paths(cls, env: Env, name: str) -> Set[Path]:
68
76
return paths
69
77
70
78
@classmethod
71
- def set_package_vcs_properties_from_path (cls , src : Path , package : Package ) -> None :
79
+ def get_package_vcs_properties_from_path (cls , src : Path ) -> Tuple [ str , str , str ] :
72
80
from poetry .core .vcs .git import Git
73
81
74
82
git = Git ()
75
83
revision = git .rev_parse ("HEAD" , src ).strip ()
76
84
url = git .remote_url (src )
77
85
78
- package ._source_type = "git"
79
- package ._source_url = url
80
- package ._source_reference = revision
81
-
82
- @classmethod
83
- def set_package_vcs_properties (cls , package : Package , env : Env ) -> None :
84
- src = env .path / "src" / package .name
85
- cls .set_package_vcs_properties_from_path (src , package )
86
+ return "git" , url , revision
86
87
87
88
@classmethod
88
89
def is_vcs_package (cls , package : Union [Path , Package ], env : Env ) -> bool :
@@ -99,6 +100,125 @@ def is_vcs_package(cls, package: Union[Path, Package], env: Env) -> bool:
99
100
else :
100
101
return True
101
102
103
+ @classmethod
104
+ def create_package_from_distribution (
105
+ cls , distribution : "Distribution" , env : "Env"
106
+ ) -> Package :
107
+ # We first check for a direct_url.json file to determine
108
+ # the type of package.
109
+ path = Path (str (distribution ._path ))
110
+
111
+ if (
112
+ path .name .endswith (".dist-info" )
113
+ and path .joinpath ("direct_url.json" ).exists ()
114
+ ):
115
+ return cls .create_package_from_pep610 (distribution )
116
+
117
+ is_standard_package = env .is_path_relative_to_lib (path )
118
+
119
+ source_type = None
120
+ source_url = None
121
+ source_reference = None
122
+ source_resolved_reference = None
123
+ if is_standard_package :
124
+ if path .name .endswith (".dist-info" ):
125
+ paths = cls .get_package_paths (
126
+ env = env , name = distribution .metadata ["name" ]
127
+ )
128
+ if paths :
129
+ is_editable_package = False
130
+ for src in paths :
131
+ if cls .is_vcs_package (src , env ):
132
+ (
133
+ source_type ,
134
+ source_url ,
135
+ source_reference ,
136
+ ) = cls .get_package_vcs_properties_from_path (src )
137
+ break
138
+
139
+ if not (
140
+ is_editable_package or env .is_path_relative_to_lib (src )
141
+ ):
142
+ is_editable_package = True
143
+ else :
144
+ # TODO: handle multiple source directories?
145
+ if is_editable_package :
146
+ source_type = "directory"
147
+ source_url = paths .pop ().as_posix ()
148
+ else :
149
+ if cls .is_vcs_package (path , env ):
150
+ (
151
+ source_type ,
152
+ source_url ,
153
+ source_reference ,
154
+ ) = cls .get_package_vcs_properties_from_path (
155
+ env .path / "src" / canonicalize_name (distribution .metadata ["name" ])
156
+ )
157
+ else :
158
+ # If not, it's a path dependency
159
+ source_type = "directory"
160
+ source_url = str (path .parent )
161
+
162
+ package = Package (
163
+ distribution .metadata ["name" ],
164
+ distribution .metadata ["version" ],
165
+ source_type = source_type ,
166
+ source_url = source_url ,
167
+ source_reference = source_reference ,
168
+ source_resolved_reference = source_resolved_reference ,
169
+ )
170
+ package .description = distribution .metadata .get ("summary" , "" )
171
+
172
+ return package
173
+
174
+ @classmethod
175
+ def create_package_from_pep610 (cls , distribution : "Distribution" ) -> Package :
176
+ path = Path (str (distribution ._path ))
177
+ source_type = None
178
+ source_url = None
179
+ source_reference = None
180
+ source_resolved_reference = None
181
+ develop = False
182
+
183
+ url_reference = json .loads (
184
+ path .joinpath ("direct_url.json" ).read_text (encoding = "utf-8" )
185
+ )
186
+ if "archive_info" in url_reference :
187
+ # File or URL distribution
188
+ if url_reference ["url" ].startswith ("file:" ):
189
+ # File distribution
190
+ source_type = "file"
191
+ source_url = url_to_path (url_reference ["url" ]).as_posix ()
192
+ else :
193
+ # URL distribution
194
+ source_type = "url"
195
+ source_url = url_reference ["url" ]
196
+ elif "dir_info" in url_reference :
197
+ # Directory distribution
198
+ source_type = "directory"
199
+ source_url = url_to_path (url_reference ["url" ]).as_posix ()
200
+ develop = url_reference ["dir_info" ].get ("editable" , False )
201
+ elif "vcs_info" in url_reference :
202
+ # VCS distribution
203
+ source_type = url_reference ["vcs_info" ]["vcs" ]
204
+ source_url = url_reference ["url" ]
205
+ source_reference = url_reference ["vcs_info" ]["requested_revision" ]
206
+ source_resolved_reference = url_reference ["vcs_info" ]["commit_id" ]
207
+
208
+ package = Package (
209
+ distribution .metadata ["name" ],
210
+ distribution .metadata ["version" ],
211
+ source_type = source_type ,
212
+ source_url = source_url ,
213
+ source_reference = source_reference ,
214
+ source_resolved_reference = source_resolved_reference ,
215
+ develop = develop ,
216
+ )
217
+
218
+ package .description = distribution .metadata .get ("summary" , "" )
219
+
220
+ return package
221
+
102
222
@classmethod
103
223
def load (cls , env : Env , with_dependencies : bool = False ) -> "InstalledRepository" :
104
224
"""
@@ -114,60 +234,28 @@ def load(cls, env: Env, with_dependencies: bool = False) -> "InstalledRepository
114
234
metadata .distributions (path = [entry ]),
115
235
key = lambda d : str (d ._path ),
116
236
):
117
- name = distribution .metadata ["name" ]
118
- path = Path (str (distribution ._path ))
119
- version = distribution .metadata ["version" ]
120
- package = Package (name , version , version )
121
- package .description = distribution .metadata .get ("summary" , "" )
237
+ name = canonicalize_name (distribution .metadata ["name" ])
122
238
123
- if with_dependencies :
124
- for require in distribution .metadata .get_all ("requires-dist" , []):
125
- dep = Dependency .create_from_pep_508 (require )
126
- package .add_dependency (dep )
127
-
128
- if package .name in seen :
239
+ if name in seen :
129
240
continue
130
241
242
+ path = Path (str (distribution ._path ))
243
+
131
244
try :
132
245
path .relative_to (_VENDORS )
133
246
except ValueError :
134
247
pass
135
248
else :
136
249
continue
137
250
138
- seen .add (package .name )
139
-
140
- repo .add_package (package )
251
+ package = cls .create_package_from_distribution (distribution , env )
141
252
142
- is_standard_package = env .is_path_relative_to_lib (path )
143
-
144
- if is_standard_package :
145
- if path .name .endswith (".dist-info" ):
146
- paths = cls .get_package_paths (env = env , name = package .pretty_name )
147
- if paths :
148
- is_editable_package = False
149
- for src in paths :
150
- if cls .is_vcs_package (src , env ):
151
- cls .set_package_vcs_properties (package , env )
152
- break
153
-
154
- if not (
155
- is_editable_package
156
- or env .is_path_relative_to_lib (src )
157
- ):
158
- is_editable_package = True
159
- else :
160
- # TODO: handle multiple source directories?
161
- if is_editable_package :
162
- package ._source_type = "directory"
163
- package ._source_url = paths .pop ().as_posix ()
164
- continue
253
+ if with_dependencies :
254
+ for require in distribution .metadata .get_all ("requires-dist" , []):
255
+ dep = Dependency .create_from_pep_508 (require )
256
+ package .add_dependency (dep )
165
257
166
- if cls .is_vcs_package (path , env ):
167
- cls .set_package_vcs_properties (package , env )
168
- else :
169
- # If not, it's a path dependency
170
- package ._source_type = "directory"
171
- package ._source_url = str (path .parent )
258
+ seen .add (package .name )
259
+ repo .add_package (package )
172
260
173
261
return repo
0 commit comments