|
20 | 20 | import os
|
21 | 21 | import os.path
|
22 | 22 | import shutil
|
23 |
| -import tempfile |
24 | 23 | import subprocess
|
25 |
| -from collections import defaultdict |
| 24 | +import tempfile |
26 | 25 | from textwrap import dedent
|
27 |
| -from typing import List, Dict, Set, Optional |
| 26 | +from typing import Dict, List, Optional |
28 | 27 |
|
29 |
| -from stub_uploader import get_version |
30 | 28 | from stub_uploader.const import *
|
31 | 29 | from stub_uploader.metadata import Metadata, read_metadata
|
32 | 30 |
|
@@ -101,13 +99,6 @@ def __init__(self, typeshed_dir: str, distribution: str) -> None:
|
101 | 99 | self.stub_dir = os.path.join(typeshed_dir, THIRD_PARTY_NAMESPACE, distribution)
|
102 | 100 |
|
103 | 101 |
|
104 |
| -def strip_types_prefix(dependency: str) -> str: |
105 |
| - assert dependency.startswith( |
106 |
| - TYPES_PREFIX |
107 |
| - ), "Currently only dependencies on stub packages are supported" |
108 |
| - return dependency[len(TYPES_PREFIX) :] |
109 |
| - |
110 |
| - |
111 | 102 | def find_stub_files(top: str) -> List[str]:
|
112 | 103 | """Find all stub files for a given package, relative to package root.
|
113 | 104 |
|
@@ -214,106 +205,21 @@ def collect_setup_entries(base_dir: str) -> Dict[str, List[str]]:
|
214 | 205 | return package_data
|
215 | 206 |
|
216 | 207 |
|
217 |
| -def verify_dependency(typeshed_dir: str, dependency: str, uploaded: str) -> None: |
218 |
| - """Verify this is a valid dependency, i.e. a stub package uploaded by us.""" |
219 |
| - known_distributions = set( |
220 |
| - os.listdir(os.path.join(typeshed_dir, THIRD_PARTY_NAMESPACE)) |
221 |
| - ) |
222 |
| - assert ";" not in dependency, "Semicolons in dependencies are not supported" |
223 |
| - dependency = get_version.strip_dep_version(dependency) |
224 |
| - assert ( |
225 |
| - strip_types_prefix(dependency) in known_distributions |
226 |
| - ), "Only dependencies on typeshed stubs are allowed" |
227 |
| - with open(uploaded) as f: |
228 |
| - uploaded_distributions = set(f.read().splitlines()) |
229 |
| - |
230 |
| - msg = f"{dependency} looks like a foreign distribution." |
231 |
| - uploaded_distributions_lower = [d.lower() for d in uploaded_distributions] |
232 |
| - if ( |
233 |
| - dependency not in uploaded_distributions |
234 |
| - and dependency.lower() in uploaded_distributions_lower |
235 |
| - ): |
236 |
| - msg += " Note: list is case sensitive" |
237 |
| - assert dependency in uploaded_distributions, msg |
238 |
| - |
239 |
| - |
240 |
| -def update_uploaded(uploaded: str, distribution: str) -> None: |
241 |
| - with open(uploaded) as f: |
242 |
| - current = set(f.read().splitlines()) |
243 |
| - if f"types-{distribution}" not in current: |
244 |
| - with open(uploaded, "w") as f: |
245 |
| - f.write("\n".join(sorted(current | {f"types-{distribution}"}))) |
246 |
| - |
247 |
| - |
248 |
| -def make_dependency_map( |
249 |
| - typeshed_dir: str, distributions: List[str] |
250 |
| -) -> Dict[str, Set[str]]: |
251 |
| - """Return relative dependency map among distributions. |
252 |
| -
|
253 |
| - Important: this only includes dependencies *within* the given |
254 |
| - list of distributions. |
255 |
| - """ |
256 |
| - result: Dict[str, Set[str]] = {d: set() for d in distributions} |
257 |
| - for distribution in distributions: |
258 |
| - data = read_metadata(typeshed_dir, distribution) |
259 |
| - for dependency in data.requires: |
260 |
| - dependency = strip_types_prefix(get_version.strip_dep_version(dependency)) |
261 |
| - if dependency in distributions: |
262 |
| - result[distribution].add(dependency) |
263 |
| - return result |
264 |
| - |
265 |
| - |
266 |
| -def transitive_deps(dep_map: Dict[str, Set[str]]) -> Dict[str, Set[str]]: |
267 |
| - """Propagate dependencies to compute a transitive dependency map. |
268 |
| -
|
269 |
| - Note: this algorithm is O(N**2) in general case, but we don't worry, |
270 |
| - because N is small (less than 1000). So it will take few seconds at worst, |
271 |
| - while building/uploading 1000 packages will take minutes. |
272 |
| - """ |
273 |
| - transitive: Dict[str, Set[str]] = defaultdict(set) |
274 |
| - for distribution in dep_map: |
275 |
| - to_add = {distribution} |
276 |
| - while to_add: |
277 |
| - new = to_add.pop() |
278 |
| - extra = dep_map[new] |
279 |
| - transitive[distribution] |= extra |
280 |
| - assert ( |
281 |
| - distribution not in transitive[distribution] |
282 |
| - ), f"Cyclic dependency {distribution} -> {distribution}" |
283 |
| - to_add |= extra |
284 |
| - return transitive |
285 |
| - |
286 |
| - |
287 |
| -def sort_by_dependency(dep_map: Dict[str, Set[str]]) -> List[str]: |
288 |
| - """Sort distributions by dependency order (those depending on nothing appear first).""" |
289 |
| - trans_map = transitive_deps(dep_map) |
290 |
| - |
291 |
| - # We can't use builtin sort w.r.t. trans_map because it makes various assumptions |
292 |
| - # about properties of equality and order (like their mutual transitivity). |
293 |
| - def sort(ds: List[str]) -> List[str]: |
294 |
| - if not ds: |
295 |
| - return [] |
296 |
| - pivot = ds.pop() |
297 |
| - not_dependent = [d for d in ds if pivot not in trans_map[d]] |
298 |
| - dependent = [d for d in ds if pivot in trans_map[d]] |
299 |
| - return sort(not_dependent) + [pivot] + sort(dependent) |
300 |
| - |
301 |
| - # Return independent packages sorted by name for stability. |
302 |
| - return sort(sorted(dep_map)) |
303 |
| - |
304 |
| - |
305 | 208 | def generate_setup_file(
|
306 | 209 | build_data: BuildData, metadata: Metadata, version: str, commit: str
|
307 | 210 | ) -> str:
|
308 | 211 | """Auto-generate a setup.py file for given distribution using a template."""
|
| 212 | + all_requirements = [ |
| 213 | + str(req) for req in metadata.requires_typeshed + metadata.requires_external |
| 214 | + ] |
309 | 215 | package_data = collect_setup_entries(build_data.stub_dir)
|
310 | 216 | return SETUP_TEMPLATE.format(
|
311 | 217 | distribution=build_data.distribution,
|
312 | 218 | long_description=generate_long_description(
|
313 | 219 | build_data.distribution, commit, metadata
|
314 | 220 | ),
|
315 | 221 | version=version,
|
316 |
| - requires=metadata.requires, |
| 222 | + requires=all_requirements, |
317 | 223 | packages=list(package_data.keys()),
|
318 | 224 | package_data=package_data,
|
319 | 225 | )
|
|
0 commit comments