omdev 0.0.0.dev147__py3-none-any.whl → 0.0.0.dev148__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- omdev/.manifests.json +12 -0
- omdev/interp/cli.py +11 -6
- omdev/interp/inspect.py +5 -6
- omdev/interp/providers.py +6 -6
- omdev/interp/pyenv.py +77 -78
- omdev/interp/resolvers.py +11 -10
- omdev/interp/system.py +8 -8
- omdev/interp/types.py +2 -0
- omdev/manifests/__init__.py +0 -1
- omdev/manifests/__main__.py +11 -0
- omdev/manifests/build.py +2 -76
- omdev/manifests/main.py +84 -0
- omdev/pyproject/cli.py +21 -15
- omdev/scripts/interp.py +558 -133
- omdev/scripts/pyproject.py +1399 -975
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/METADATA +2 -2
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/RECORD +21 -19
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/LICENSE +0 -0
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/WHEEL +0 -0
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/entry_points.txt +0 -0
- {omdev-0.0.0.dev147.dist-info → omdev-0.0.0.dev148.dist-info}/top_level.txt +0 -0
omdev/scripts/interp.py
CHANGED
|
@@ -12,6 +12,9 @@ TODO:
|
|
|
12
12
|
"""
|
|
13
13
|
import abc
|
|
14
14
|
import argparse
|
|
15
|
+
import asyncio
|
|
16
|
+
import asyncio.base_subprocess
|
|
17
|
+
import asyncio.subprocess
|
|
15
18
|
import collections
|
|
16
19
|
import contextlib
|
|
17
20
|
import dataclasses as dc
|
|
@@ -29,6 +32,7 @@ import shutil
|
|
|
29
32
|
import subprocess
|
|
30
33
|
import sys
|
|
31
34
|
import threading
|
|
35
|
+
import time
|
|
32
36
|
import types
|
|
33
37
|
import typing as ta
|
|
34
38
|
|
|
@@ -51,6 +55,9 @@ VersionCmpLocalType = ta.Union['NegativeInfinityVersionType', _VersionCmpLocalTy
|
|
|
51
55
|
VersionCmpKey = ta.Tuple[int, ta.Tuple[int, ...], VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpPrePostDevType, VersionCmpLocalType] # noqa
|
|
52
56
|
VersionComparisonMethod = ta.Callable[[VersionCmpKey, VersionCmpKey], bool]
|
|
53
57
|
|
|
58
|
+
# ../../omlish/lite/asyncio/asyncio.py
|
|
59
|
+
AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
|
|
60
|
+
|
|
54
61
|
# ../../omlish/lite/cached.py
|
|
55
62
|
T = ta.TypeVar('T')
|
|
56
63
|
CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
|
@@ -474,11 +481,74 @@ def canonicalize_version(
|
|
|
474
481
|
return ''.join(parts)
|
|
475
482
|
|
|
476
483
|
|
|
484
|
+
########################################
|
|
485
|
+
# ../../../omlish/lite/asyncio/asyncio.py
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
##
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
ASYNCIO_DEFAULT_BUFFER_LIMIT = 2 ** 16
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
async def asyncio_open_stream_reader(
|
|
495
|
+
f: ta.IO,
|
|
496
|
+
loop: ta.Any = None,
|
|
497
|
+
*,
|
|
498
|
+
limit: int = ASYNCIO_DEFAULT_BUFFER_LIMIT,
|
|
499
|
+
) -> asyncio.StreamReader:
|
|
500
|
+
if loop is None:
|
|
501
|
+
loop = asyncio.get_running_loop()
|
|
502
|
+
|
|
503
|
+
reader = asyncio.StreamReader(limit=limit, loop=loop)
|
|
504
|
+
await loop.connect_read_pipe(
|
|
505
|
+
lambda: asyncio.StreamReaderProtocol(reader, loop=loop),
|
|
506
|
+
f,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
return reader
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
async def asyncio_open_stream_writer(
|
|
513
|
+
f: ta.IO,
|
|
514
|
+
loop: ta.Any = None,
|
|
515
|
+
) -> asyncio.StreamWriter:
|
|
516
|
+
if loop is None:
|
|
517
|
+
loop = asyncio.get_running_loop()
|
|
518
|
+
|
|
519
|
+
writer_transport, writer_protocol = await loop.connect_write_pipe(
|
|
520
|
+
lambda: asyncio.streams.FlowControlMixin(loop=loop),
|
|
521
|
+
f,
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
return asyncio.streams.StreamWriter(
|
|
525
|
+
writer_transport,
|
|
526
|
+
writer_protocol,
|
|
527
|
+
None,
|
|
528
|
+
loop,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
##
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def asyncio_maybe_timeout(
|
|
536
|
+
fut: AwaitableT,
|
|
537
|
+
timeout: ta.Optional[float] = None,
|
|
538
|
+
) -> AwaitableT:
|
|
539
|
+
if timeout is not None:
|
|
540
|
+
fut = asyncio.wait_for(fut, timeout) # type: ignore
|
|
541
|
+
return fut
|
|
542
|
+
|
|
543
|
+
|
|
477
544
|
########################################
|
|
478
545
|
# ../../../omlish/lite/cached.py
|
|
479
546
|
|
|
480
547
|
|
|
481
|
-
|
|
548
|
+
##
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
class _AbstractCachedNullary:
|
|
482
552
|
def __init__(self, fn):
|
|
483
553
|
super().__init__()
|
|
484
554
|
self._fn = fn
|
|
@@ -486,17 +556,25 @@ class _cached_nullary: # noqa
|
|
|
486
556
|
functools.update_wrapper(self, fn)
|
|
487
557
|
|
|
488
558
|
def __call__(self, *args, **kwargs): # noqa
|
|
489
|
-
|
|
490
|
-
self._value = self._fn()
|
|
491
|
-
return self._value
|
|
559
|
+
raise TypeError
|
|
492
560
|
|
|
493
561
|
def __get__(self, instance, owner): # noqa
|
|
494
562
|
bound = instance.__dict__[self._fn.__name__] = self.__class__(self._fn.__get__(instance, owner))
|
|
495
563
|
return bound
|
|
496
564
|
|
|
497
565
|
|
|
566
|
+
##
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
class _CachedNullary(_AbstractCachedNullary):
|
|
570
|
+
def __call__(self, *args, **kwargs): # noqa
|
|
571
|
+
if self._value is self._missing:
|
|
572
|
+
self._value = self._fn()
|
|
573
|
+
return self._value
|
|
574
|
+
|
|
575
|
+
|
|
498
576
|
def cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
|
|
499
|
-
return
|
|
577
|
+
return _CachedNullary(fn)
|
|
500
578
|
|
|
501
579
|
|
|
502
580
|
def static_init(fn: CallableT) -> CallableT:
|
|
@@ -505,6 +583,20 @@ def static_init(fn: CallableT) -> CallableT:
|
|
|
505
583
|
return fn
|
|
506
584
|
|
|
507
585
|
|
|
586
|
+
##
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
class _AsyncCachedNullary(_AbstractCachedNullary):
|
|
590
|
+
async def __call__(self, *args, **kwargs):
|
|
591
|
+
if self._value is self._missing:
|
|
592
|
+
self._value = await self._fn()
|
|
593
|
+
return self._value
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
|
|
597
|
+
return _AsyncCachedNullary(fn)
|
|
598
|
+
|
|
599
|
+
|
|
508
600
|
########################################
|
|
509
601
|
# ../../../omlish/lite/check.py
|
|
510
602
|
|
|
@@ -1637,6 +1729,8 @@ class InterpSpecifier:
|
|
|
1637
1729
|
s, o = InterpOpts.parse_suffix(s)
|
|
1638
1730
|
if not any(s.startswith(o) for o in Specifier.OPERATORS):
|
|
1639
1731
|
s = '~=' + s
|
|
1732
|
+
if s.count('.') < 2:
|
|
1733
|
+
s += '.0'
|
|
1640
1734
|
return cls(
|
|
1641
1735
|
specifier=Specifier(s),
|
|
1642
1736
|
opts=o,
|
|
@@ -1686,7 +1780,7 @@ def subprocess_maybe_shell_wrap_exec(*args: str) -> ta.Tuple[str, ...]:
|
|
|
1686
1780
|
return args
|
|
1687
1781
|
|
|
1688
1782
|
|
|
1689
|
-
def
|
|
1783
|
+
def prepare_subprocess_invocation(
|
|
1690
1784
|
*args: str,
|
|
1691
1785
|
env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
|
|
1692
1786
|
extra_env: ta.Optional[ta.Mapping[str, ta.Any]] = None,
|
|
@@ -1694,9 +1788,9 @@ def _prepare_subprocess_invocation(
|
|
|
1694
1788
|
shell: bool = False,
|
|
1695
1789
|
**kwargs: ta.Any,
|
|
1696
1790
|
) -> ta.Tuple[ta.Tuple[ta.Any, ...], ta.Dict[str, ta.Any]]:
|
|
1697
|
-
log.debug(args)
|
|
1791
|
+
log.debug('prepare_subprocess_invocation: args=%r', args)
|
|
1698
1792
|
if extra_env:
|
|
1699
|
-
log.debug(extra_env)
|
|
1793
|
+
log.debug('prepare_subprocess_invocation: extra_env=%r', extra_env)
|
|
1700
1794
|
|
|
1701
1795
|
if extra_env:
|
|
1702
1796
|
env = {**(env if env is not None else os.environ), **extra_env}
|
|
@@ -1715,14 +1809,46 @@ def _prepare_subprocess_invocation(
|
|
|
1715
1809
|
)
|
|
1716
1810
|
|
|
1717
1811
|
|
|
1718
|
-
|
|
1719
|
-
args, kwargs = _prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
|
|
1720
|
-
return subprocess.check_call(args, **kwargs) # type: ignore
|
|
1812
|
+
##
|
|
1721
1813
|
|
|
1722
1814
|
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1815
|
+
@contextlib.contextmanager
|
|
1816
|
+
def subprocess_common_context(*args: ta.Any, **kwargs: ta.Any) -> ta.Iterator[None]:
|
|
1817
|
+
start_time = time.time()
|
|
1818
|
+
try:
|
|
1819
|
+
log.debug('subprocess_common_context.try: args=%r', args)
|
|
1820
|
+
yield
|
|
1821
|
+
|
|
1822
|
+
except Exception as exc: # noqa
|
|
1823
|
+
log.debug('subprocess_common_context.except: exc=%r', exc)
|
|
1824
|
+
raise
|
|
1825
|
+
|
|
1826
|
+
finally:
|
|
1827
|
+
end_time = time.time()
|
|
1828
|
+
elapsed_s = end_time - start_time
|
|
1829
|
+
log.debug('subprocess_common_context.finally: elapsed_s=%f args=%r', elapsed_s, args)
|
|
1830
|
+
|
|
1831
|
+
|
|
1832
|
+
##
|
|
1833
|
+
|
|
1834
|
+
|
|
1835
|
+
def subprocess_check_call(
|
|
1836
|
+
*args: str,
|
|
1837
|
+
stdout: ta.Any = sys.stderr,
|
|
1838
|
+
**kwargs: ta.Any,
|
|
1839
|
+
) -> None:
|
|
1840
|
+
args, kwargs = prepare_subprocess_invocation(*args, stdout=stdout, **kwargs)
|
|
1841
|
+
with subprocess_common_context(*args, **kwargs):
|
|
1842
|
+
return subprocess.check_call(args, **kwargs) # type: ignore
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
def subprocess_check_output(
|
|
1846
|
+
*args: str,
|
|
1847
|
+
**kwargs: ta.Any,
|
|
1848
|
+
) -> bytes:
|
|
1849
|
+
args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
|
|
1850
|
+
with subprocess_common_context(*args, **kwargs):
|
|
1851
|
+
return subprocess.check_output(args, **kwargs)
|
|
1726
1852
|
|
|
1727
1853
|
|
|
1728
1854
|
def subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
|
|
@@ -1738,16 +1864,31 @@ DEFAULT_SUBPROCESS_TRY_EXCEPTIONS: ta.Tuple[ta.Type[Exception], ...] = (
|
|
|
1738
1864
|
)
|
|
1739
1865
|
|
|
1740
1866
|
|
|
1741
|
-
def
|
|
1742
|
-
|
|
1867
|
+
def _subprocess_try_run(
|
|
1868
|
+
fn: ta.Callable[..., T],
|
|
1869
|
+
*args: ta.Any,
|
|
1743
1870
|
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
1744
1871
|
**kwargs: ta.Any,
|
|
1745
|
-
) ->
|
|
1872
|
+
) -> ta.Union[T, Exception]:
|
|
1746
1873
|
try:
|
|
1747
|
-
|
|
1874
|
+
return fn(*args, **kwargs)
|
|
1748
1875
|
except try_exceptions as e: # noqa
|
|
1749
1876
|
if log.isEnabledFor(logging.DEBUG):
|
|
1750
1877
|
log.exception('command failed')
|
|
1878
|
+
return e
|
|
1879
|
+
|
|
1880
|
+
|
|
1881
|
+
def subprocess_try_call(
|
|
1882
|
+
*args: str,
|
|
1883
|
+
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
1884
|
+
**kwargs: ta.Any,
|
|
1885
|
+
) -> bool:
|
|
1886
|
+
if isinstance(_subprocess_try_run(
|
|
1887
|
+
subprocess_check_call,
|
|
1888
|
+
*args,
|
|
1889
|
+
try_exceptions=try_exceptions,
|
|
1890
|
+
**kwargs,
|
|
1891
|
+
), Exception):
|
|
1751
1892
|
return False
|
|
1752
1893
|
else:
|
|
1753
1894
|
return True
|
|
@@ -1758,12 +1899,15 @@ def subprocess_try_output(
|
|
|
1758
1899
|
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
1759
1900
|
**kwargs: ta.Any,
|
|
1760
1901
|
) -> ta.Optional[bytes]:
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1902
|
+
if isinstance(ret := _subprocess_try_run(
|
|
1903
|
+
subprocess_check_output,
|
|
1904
|
+
*args,
|
|
1905
|
+
try_exceptions=try_exceptions,
|
|
1906
|
+
**kwargs,
|
|
1907
|
+
), Exception):
|
|
1766
1908
|
return None
|
|
1909
|
+
else:
|
|
1910
|
+
return ret
|
|
1767
1911
|
|
|
1768
1912
|
|
|
1769
1913
|
def subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
|
|
@@ -1789,6 +1933,285 @@ def subprocess_close(
|
|
|
1789
1933
|
proc.wait(timeout)
|
|
1790
1934
|
|
|
1791
1935
|
|
|
1936
|
+
########################################
|
|
1937
|
+
# ../../../omlish/lite/asyncio/subprocesses.py
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
##
|
|
1941
|
+
|
|
1942
|
+
|
|
1943
|
+
@contextlib.asynccontextmanager
|
|
1944
|
+
async def asyncio_subprocess_popen(
|
|
1945
|
+
*cmd: str,
|
|
1946
|
+
shell: bool = False,
|
|
1947
|
+
timeout: ta.Optional[float] = None,
|
|
1948
|
+
**kwargs: ta.Any,
|
|
1949
|
+
) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
|
|
1950
|
+
fac: ta.Any
|
|
1951
|
+
if shell:
|
|
1952
|
+
fac = functools.partial(
|
|
1953
|
+
asyncio.create_subprocess_shell,
|
|
1954
|
+
check_single(cmd),
|
|
1955
|
+
)
|
|
1956
|
+
else:
|
|
1957
|
+
fac = functools.partial(
|
|
1958
|
+
asyncio.create_subprocess_exec,
|
|
1959
|
+
*cmd,
|
|
1960
|
+
)
|
|
1961
|
+
|
|
1962
|
+
with subprocess_common_context(
|
|
1963
|
+
*cmd,
|
|
1964
|
+
shell=shell,
|
|
1965
|
+
timeout=timeout,
|
|
1966
|
+
**kwargs,
|
|
1967
|
+
):
|
|
1968
|
+
proc: asyncio.subprocess.Process
|
|
1969
|
+
proc = await fac(**kwargs)
|
|
1970
|
+
try:
|
|
1971
|
+
yield proc
|
|
1972
|
+
|
|
1973
|
+
finally:
|
|
1974
|
+
await asyncio_maybe_timeout(proc.wait(), timeout)
|
|
1975
|
+
|
|
1976
|
+
|
|
1977
|
+
##
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
class AsyncioProcessCommunicator:
|
|
1981
|
+
def __init__(
|
|
1982
|
+
self,
|
|
1983
|
+
proc: asyncio.subprocess.Process,
|
|
1984
|
+
loop: ta.Optional[ta.Any] = None,
|
|
1985
|
+
) -> None:
|
|
1986
|
+
super().__init__()
|
|
1987
|
+
|
|
1988
|
+
if loop is None:
|
|
1989
|
+
loop = asyncio.get_running_loop()
|
|
1990
|
+
|
|
1991
|
+
self._proc = proc
|
|
1992
|
+
self._loop = loop
|
|
1993
|
+
|
|
1994
|
+
self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check_isinstance(
|
|
1995
|
+
proc._transport, # type: ignore # noqa
|
|
1996
|
+
asyncio.base_subprocess.BaseSubprocessTransport,
|
|
1997
|
+
)
|
|
1998
|
+
|
|
1999
|
+
@property
|
|
2000
|
+
def _debug(self) -> bool:
|
|
2001
|
+
return self._loop.get_debug()
|
|
2002
|
+
|
|
2003
|
+
async def _feed_stdin(self, input: bytes) -> None: # noqa
|
|
2004
|
+
stdin = check_not_none(self._proc.stdin)
|
|
2005
|
+
try:
|
|
2006
|
+
if input is not None:
|
|
2007
|
+
stdin.write(input)
|
|
2008
|
+
if self._debug:
|
|
2009
|
+
log.debug('%r communicate: feed stdin (%s bytes)', self, len(input))
|
|
2010
|
+
|
|
2011
|
+
await stdin.drain()
|
|
2012
|
+
|
|
2013
|
+
except (BrokenPipeError, ConnectionResetError) as exc:
|
|
2014
|
+
# communicate() ignores BrokenPipeError and ConnectionResetError. write() and drain() can raise these
|
|
2015
|
+
# exceptions.
|
|
2016
|
+
if self._debug:
|
|
2017
|
+
log.debug('%r communicate: stdin got %r', self, exc)
|
|
2018
|
+
|
|
2019
|
+
if self._debug:
|
|
2020
|
+
log.debug('%r communicate: close stdin', self)
|
|
2021
|
+
|
|
2022
|
+
stdin.close()
|
|
2023
|
+
|
|
2024
|
+
async def _noop(self) -> None:
|
|
2025
|
+
return None
|
|
2026
|
+
|
|
2027
|
+
async def _read_stream(self, fd: int) -> bytes:
|
|
2028
|
+
transport: ta.Any = check_not_none(self._transport.get_pipe_transport(fd))
|
|
2029
|
+
|
|
2030
|
+
if fd == 2:
|
|
2031
|
+
stream = check_not_none(self._proc.stderr)
|
|
2032
|
+
else:
|
|
2033
|
+
check_equal(fd, 1)
|
|
2034
|
+
stream = check_not_none(self._proc.stdout)
|
|
2035
|
+
|
|
2036
|
+
if self._debug:
|
|
2037
|
+
name = 'stdout' if fd == 1 else 'stderr'
|
|
2038
|
+
log.debug('%r communicate: read %s', self, name)
|
|
2039
|
+
|
|
2040
|
+
output = await stream.read()
|
|
2041
|
+
|
|
2042
|
+
if self._debug:
|
|
2043
|
+
name = 'stdout' if fd == 1 else 'stderr'
|
|
2044
|
+
log.debug('%r communicate: close %s', self, name)
|
|
2045
|
+
|
|
2046
|
+
transport.close()
|
|
2047
|
+
|
|
2048
|
+
return output
|
|
2049
|
+
|
|
2050
|
+
class Communication(ta.NamedTuple):
|
|
2051
|
+
stdout: ta.Optional[bytes]
|
|
2052
|
+
stderr: ta.Optional[bytes]
|
|
2053
|
+
|
|
2054
|
+
async def _communicate(
|
|
2055
|
+
self,
|
|
2056
|
+
input: ta.Any = None, # noqa
|
|
2057
|
+
) -> Communication:
|
|
2058
|
+
stdin_fut: ta.Any
|
|
2059
|
+
if self._proc.stdin is not None:
|
|
2060
|
+
stdin_fut = self._feed_stdin(input)
|
|
2061
|
+
else:
|
|
2062
|
+
stdin_fut = self._noop()
|
|
2063
|
+
|
|
2064
|
+
stdout_fut: ta.Any
|
|
2065
|
+
if self._proc.stdout is not None:
|
|
2066
|
+
stdout_fut = self._read_stream(1)
|
|
2067
|
+
else:
|
|
2068
|
+
stdout_fut = self._noop()
|
|
2069
|
+
|
|
2070
|
+
stderr_fut: ta.Any
|
|
2071
|
+
if self._proc.stderr is not None:
|
|
2072
|
+
stderr_fut = self._read_stream(2)
|
|
2073
|
+
else:
|
|
2074
|
+
stderr_fut = self._noop()
|
|
2075
|
+
|
|
2076
|
+
stdin_res, stdout_res, stderr_res = await asyncio.gather(stdin_fut, stdout_fut, stderr_fut)
|
|
2077
|
+
|
|
2078
|
+
await self._proc.wait()
|
|
2079
|
+
|
|
2080
|
+
return AsyncioProcessCommunicator.Communication(stdout_res, stderr_res)
|
|
2081
|
+
|
|
2082
|
+
async def communicate(
|
|
2083
|
+
self,
|
|
2084
|
+
input: ta.Any = None, # noqa
|
|
2085
|
+
timeout: ta.Optional[float] = None,
|
|
2086
|
+
) -> Communication:
|
|
2087
|
+
return await asyncio_maybe_timeout(self._communicate(input), timeout)
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
async def asyncio_subprocess_communicate(
|
|
2091
|
+
proc: asyncio.subprocess.Process,
|
|
2092
|
+
input: ta.Any = None, # noqa
|
|
2093
|
+
timeout: ta.Optional[float] = None,
|
|
2094
|
+
) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
|
|
2095
|
+
return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
|
|
2096
|
+
|
|
2097
|
+
|
|
2098
|
+
##
|
|
2099
|
+
|
|
2100
|
+
|
|
2101
|
+
async def _asyncio_subprocess_check_run(
|
|
2102
|
+
*args: str,
|
|
2103
|
+
input: ta.Any = None, # noqa
|
|
2104
|
+
timeout: ta.Optional[float] = None,
|
|
2105
|
+
**kwargs: ta.Any,
|
|
2106
|
+
) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
|
|
2107
|
+
args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
|
|
2108
|
+
|
|
2109
|
+
proc: asyncio.subprocess.Process
|
|
2110
|
+
async with asyncio_subprocess_popen(*args, **kwargs) as proc:
|
|
2111
|
+
stdout, stderr = await asyncio_subprocess_communicate(proc, input, timeout)
|
|
2112
|
+
|
|
2113
|
+
if proc.returncode:
|
|
2114
|
+
raise subprocess.CalledProcessError(
|
|
2115
|
+
proc.returncode,
|
|
2116
|
+
args,
|
|
2117
|
+
output=stdout,
|
|
2118
|
+
stderr=stderr,
|
|
2119
|
+
)
|
|
2120
|
+
|
|
2121
|
+
return stdout, stderr
|
|
2122
|
+
|
|
2123
|
+
|
|
2124
|
+
async def asyncio_subprocess_check_call(
|
|
2125
|
+
*args: str,
|
|
2126
|
+
stdout: ta.Any = sys.stderr,
|
|
2127
|
+
input: ta.Any = None, # noqa
|
|
2128
|
+
timeout: ta.Optional[float] = None,
|
|
2129
|
+
**kwargs: ta.Any,
|
|
2130
|
+
) -> None:
|
|
2131
|
+
_, _ = await _asyncio_subprocess_check_run(
|
|
2132
|
+
*args,
|
|
2133
|
+
stdout=stdout,
|
|
2134
|
+
input=input,
|
|
2135
|
+
timeout=timeout,
|
|
2136
|
+
**kwargs,
|
|
2137
|
+
)
|
|
2138
|
+
|
|
2139
|
+
|
|
2140
|
+
async def asyncio_subprocess_check_output(
|
|
2141
|
+
*args: str,
|
|
2142
|
+
input: ta.Any = None, # noqa
|
|
2143
|
+
timeout: ta.Optional[float] = None,
|
|
2144
|
+
**kwargs: ta.Any,
|
|
2145
|
+
) -> bytes:
|
|
2146
|
+
stdout, stderr = await _asyncio_subprocess_check_run(
|
|
2147
|
+
*args,
|
|
2148
|
+
stdout=asyncio.subprocess.PIPE,
|
|
2149
|
+
input=input,
|
|
2150
|
+
timeout=timeout,
|
|
2151
|
+
**kwargs,
|
|
2152
|
+
)
|
|
2153
|
+
|
|
2154
|
+
return check_not_none(stdout)
|
|
2155
|
+
|
|
2156
|
+
|
|
2157
|
+
async def asyncio_subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
|
|
2158
|
+
return (await asyncio_subprocess_check_output(*args, **kwargs)).decode().strip()
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
##
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
async def _asyncio_subprocess_try_run(
|
|
2165
|
+
fn: ta.Callable[..., ta.Awaitable[T]],
|
|
2166
|
+
*args: ta.Any,
|
|
2167
|
+
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
2168
|
+
**kwargs: ta.Any,
|
|
2169
|
+
) -> ta.Union[T, Exception]:
|
|
2170
|
+
try:
|
|
2171
|
+
return await fn(*args, **kwargs)
|
|
2172
|
+
except try_exceptions as e: # noqa
|
|
2173
|
+
if log.isEnabledFor(logging.DEBUG):
|
|
2174
|
+
log.exception('command failed')
|
|
2175
|
+
return e
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
async def asyncio_subprocess_try_call(
|
|
2179
|
+
*args: str,
|
|
2180
|
+
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
2181
|
+
**kwargs: ta.Any,
|
|
2182
|
+
) -> bool:
|
|
2183
|
+
if isinstance(await _asyncio_subprocess_try_run(
|
|
2184
|
+
asyncio_subprocess_check_call,
|
|
2185
|
+
*args,
|
|
2186
|
+
try_exceptions=try_exceptions,
|
|
2187
|
+
**kwargs,
|
|
2188
|
+
), Exception):
|
|
2189
|
+
return False
|
|
2190
|
+
else:
|
|
2191
|
+
return True
|
|
2192
|
+
|
|
2193
|
+
|
|
2194
|
+
async def asyncio_subprocess_try_output(
|
|
2195
|
+
*args: str,
|
|
2196
|
+
try_exceptions: ta.Tuple[ta.Type[Exception], ...] = DEFAULT_SUBPROCESS_TRY_EXCEPTIONS,
|
|
2197
|
+
**kwargs: ta.Any,
|
|
2198
|
+
) -> ta.Optional[bytes]:
|
|
2199
|
+
if isinstance(ret := await _asyncio_subprocess_try_run(
|
|
2200
|
+
asyncio_subprocess_check_output,
|
|
2201
|
+
*args,
|
|
2202
|
+
try_exceptions=try_exceptions,
|
|
2203
|
+
**kwargs,
|
|
2204
|
+
), Exception):
|
|
2205
|
+
return None
|
|
2206
|
+
else:
|
|
2207
|
+
return ret
|
|
2208
|
+
|
|
2209
|
+
|
|
2210
|
+
async def asyncio_subprocess_try_output_str(*args: str, **kwargs: ta.Any) -> ta.Optional[str]:
|
|
2211
|
+
out = await asyncio_subprocess_try_output(*args, **kwargs)
|
|
2212
|
+
return out.decode().strip() if out is not None else None
|
|
2213
|
+
|
|
2214
|
+
|
|
1792
2215
|
########################################
|
|
1793
2216
|
# ../inspect.py
|
|
1794
2217
|
|
|
@@ -1823,7 +2246,6 @@ class InterpInspection:
|
|
|
1823
2246
|
|
|
1824
2247
|
|
|
1825
2248
|
class InterpInspector:
|
|
1826
|
-
|
|
1827
2249
|
def __init__(self) -> None:
|
|
1828
2250
|
super().__init__()
|
|
1829
2251
|
|
|
@@ -1863,17 +2285,17 @@ class InterpInspector:
|
|
|
1863
2285
|
def running(cls) -> 'InterpInspection':
|
|
1864
2286
|
return cls._build_inspection(sys.executable, eval(cls._INSPECTION_CODE)) # noqa
|
|
1865
2287
|
|
|
1866
|
-
def _inspect(self, exe: str) -> InterpInspection:
|
|
1867
|
-
output =
|
|
2288
|
+
async def _inspect(self, exe: str) -> InterpInspection:
|
|
2289
|
+
output = await asyncio_subprocess_check_output(exe, '-c', f'print({self._INSPECTION_CODE})', quiet=True)
|
|
1868
2290
|
return self._build_inspection(exe, output.decode())
|
|
1869
2291
|
|
|
1870
|
-
def inspect(self, exe: str) -> ta.Optional[InterpInspection]:
|
|
2292
|
+
async def inspect(self, exe: str) -> ta.Optional[InterpInspection]:
|
|
1871
2293
|
try:
|
|
1872
2294
|
return self._cache[exe]
|
|
1873
2295
|
except KeyError:
|
|
1874
2296
|
ret: ta.Optional[InterpInspection]
|
|
1875
2297
|
try:
|
|
1876
|
-
ret = self._inspect(exe)
|
|
2298
|
+
ret = await self._inspect(exe)
|
|
1877
2299
|
except Exception as e: # noqa
|
|
1878
2300
|
if log.isEnabledFor(logging.DEBUG):
|
|
1879
2301
|
log.exception('Failed to inspect interp: %s', exe)
|
|
@@ -1912,17 +2334,17 @@ class InterpProvider(abc.ABC):
|
|
|
1912
2334
|
setattr(cls, 'name', snake_case(cls.__name__[:-len(sfx)]))
|
|
1913
2335
|
|
|
1914
2336
|
@abc.abstractmethod
|
|
1915
|
-
def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2337
|
+
def get_installed_versions(self, spec: InterpSpecifier) -> ta.Awaitable[ta.Sequence[InterpVersion]]:
|
|
1916
2338
|
raise NotImplementedError
|
|
1917
2339
|
|
|
1918
2340
|
@abc.abstractmethod
|
|
1919
|
-
def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2341
|
+
def get_installed_version(self, version: InterpVersion) -> ta.Awaitable[Interp]:
|
|
1920
2342
|
raise NotImplementedError
|
|
1921
2343
|
|
|
1922
|
-
def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2344
|
+
async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
1923
2345
|
return []
|
|
1924
2346
|
|
|
1925
|
-
def install_version(self, version: InterpVersion) -> Interp:
|
|
2347
|
+
async def install_version(self, version: InterpVersion) -> Interp:
|
|
1926
2348
|
raise TypeError
|
|
1927
2349
|
|
|
1928
2350
|
|
|
@@ -1934,10 +2356,10 @@ class RunningInterpProvider(InterpProvider):
|
|
|
1934
2356
|
def version(self) -> InterpVersion:
|
|
1935
2357
|
return InterpInspector.running().iv
|
|
1936
2358
|
|
|
1937
|
-
def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2359
|
+
async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
1938
2360
|
return [self.version()]
|
|
1939
2361
|
|
|
1940
|
-
def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2362
|
+
async def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
1941
2363
|
if version != self.version():
|
|
1942
2364
|
raise KeyError(version)
|
|
1943
2365
|
return Interp(
|
|
@@ -1965,7 +2387,6 @@ TODO:
|
|
|
1965
2387
|
|
|
1966
2388
|
|
|
1967
2389
|
class Pyenv:
|
|
1968
|
-
|
|
1969
2390
|
def __init__(
|
|
1970
2391
|
self,
|
|
1971
2392
|
*,
|
|
@@ -1978,13 +2399,13 @@ class Pyenv:
|
|
|
1978
2399
|
|
|
1979
2400
|
self._root_kw = root
|
|
1980
2401
|
|
|
1981
|
-
@
|
|
1982
|
-
def root(self) -> ta.Optional[str]:
|
|
2402
|
+
@async_cached_nullary
|
|
2403
|
+
async def root(self) -> ta.Optional[str]:
|
|
1983
2404
|
if self._root_kw is not None:
|
|
1984
2405
|
return self._root_kw
|
|
1985
2406
|
|
|
1986
2407
|
if shutil.which('pyenv'):
|
|
1987
|
-
return
|
|
2408
|
+
return await asyncio_subprocess_check_output_str('pyenv', 'root')
|
|
1988
2409
|
|
|
1989
2410
|
d = os.path.expanduser('~/.pyenv')
|
|
1990
2411
|
if os.path.isdir(d) and os.path.isfile(os.path.join(d, 'bin', 'pyenv')):
|
|
@@ -1992,12 +2413,12 @@ class Pyenv:
|
|
|
1992
2413
|
|
|
1993
2414
|
return None
|
|
1994
2415
|
|
|
1995
|
-
@
|
|
1996
|
-
def exe(self) -> str:
|
|
1997
|
-
return os.path.join(check_not_none(self.root()), 'bin', 'pyenv')
|
|
2416
|
+
@async_cached_nullary
|
|
2417
|
+
async def exe(self) -> str:
|
|
2418
|
+
return os.path.join(check_not_none(await self.root()), 'bin', 'pyenv')
|
|
1998
2419
|
|
|
1999
|
-
def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
|
|
2000
|
-
if (root := self.root()) is None:
|
|
2420
|
+
async def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
|
|
2421
|
+
if (root := await self.root()) is None:
|
|
2001
2422
|
return []
|
|
2002
2423
|
ret = []
|
|
2003
2424
|
vp = os.path.join(root, 'versions')
|
|
@@ -2009,11 +2430,11 @@ class Pyenv:
|
|
|
2009
2430
|
ret.append((dn, ep))
|
|
2010
2431
|
return ret
|
|
2011
2432
|
|
|
2012
|
-
def installable_versions(self) -> ta.List[str]:
|
|
2013
|
-
if self.root() is None:
|
|
2433
|
+
async def installable_versions(self) -> ta.List[str]:
|
|
2434
|
+
if await self.root() is None:
|
|
2014
2435
|
return []
|
|
2015
2436
|
ret = []
|
|
2016
|
-
s =
|
|
2437
|
+
s = await asyncio_subprocess_check_output_str(await self.exe(), 'install', '--list')
|
|
2017
2438
|
for l in s.splitlines():
|
|
2018
2439
|
if not l.startswith(' '):
|
|
2019
2440
|
continue
|
|
@@ -2023,12 +2444,12 @@ class Pyenv:
|
|
|
2023
2444
|
ret.append(l)
|
|
2024
2445
|
return ret
|
|
2025
2446
|
|
|
2026
|
-
def update(self) -> bool:
|
|
2027
|
-
if (root := self.root()) is None:
|
|
2447
|
+
async def update(self) -> bool:
|
|
2448
|
+
if (root := await self.root()) is None:
|
|
2028
2449
|
return False
|
|
2029
2450
|
if not os.path.isdir(os.path.join(root, '.git')):
|
|
2030
2451
|
return False
|
|
2031
|
-
|
|
2452
|
+
await asyncio_subprocess_check_call('git', 'pull', cwd=root)
|
|
2032
2453
|
return True
|
|
2033
2454
|
|
|
2034
2455
|
|
|
@@ -2089,17 +2510,16 @@ THREADED_PYENV_INSTALL_OPTS = PyenvInstallOpts(conf_opts=['--disable-gil'])
|
|
|
2089
2510
|
|
|
2090
2511
|
class PyenvInstallOptsProvider(abc.ABC):
|
|
2091
2512
|
@abc.abstractmethod
|
|
2092
|
-
def opts(self) -> PyenvInstallOpts:
|
|
2513
|
+
def opts(self) -> ta.Awaitable[PyenvInstallOpts]:
|
|
2093
2514
|
raise NotImplementedError
|
|
2094
2515
|
|
|
2095
2516
|
|
|
2096
2517
|
class LinuxPyenvInstallOpts(PyenvInstallOptsProvider):
|
|
2097
|
-
def opts(self) -> PyenvInstallOpts:
|
|
2518
|
+
async def opts(self) -> PyenvInstallOpts:
|
|
2098
2519
|
return PyenvInstallOpts()
|
|
2099
2520
|
|
|
2100
2521
|
|
|
2101
2522
|
class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
|
|
2102
|
-
|
|
2103
2523
|
@cached_nullary
|
|
2104
2524
|
def framework_opts(self) -> PyenvInstallOpts:
|
|
2105
2525
|
return PyenvInstallOpts(conf_opts=['--enable-framework'])
|
|
@@ -2115,12 +2535,12 @@ class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
|
|
|
2115
2535
|
'zlib',
|
|
2116
2536
|
]
|
|
2117
2537
|
|
|
2118
|
-
@
|
|
2119
|
-
def brew_deps_opts(self) -> PyenvInstallOpts:
|
|
2538
|
+
@async_cached_nullary
|
|
2539
|
+
async def brew_deps_opts(self) -> PyenvInstallOpts:
|
|
2120
2540
|
cflags = []
|
|
2121
2541
|
ldflags = []
|
|
2122
2542
|
for dep in self.BREW_DEPS:
|
|
2123
|
-
dep_prefix =
|
|
2543
|
+
dep_prefix = await asyncio_subprocess_check_output_str('brew', '--prefix', dep)
|
|
2124
2544
|
cflags.append(f'-I{dep_prefix}/include')
|
|
2125
2545
|
ldflags.append(f'-L{dep_prefix}/lib')
|
|
2126
2546
|
return PyenvInstallOpts(
|
|
@@ -2128,13 +2548,13 @@ class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
|
|
|
2128
2548
|
ldflags=ldflags,
|
|
2129
2549
|
)
|
|
2130
2550
|
|
|
2131
|
-
@
|
|
2132
|
-
def brew_tcl_opts(self) -> PyenvInstallOpts:
|
|
2133
|
-
if
|
|
2551
|
+
@async_cached_nullary
|
|
2552
|
+
async def brew_tcl_opts(self) -> PyenvInstallOpts:
|
|
2553
|
+
if await asyncio_subprocess_try_output('brew', '--prefix', 'tcl-tk') is None:
|
|
2134
2554
|
return PyenvInstallOpts()
|
|
2135
2555
|
|
|
2136
|
-
tcl_tk_prefix =
|
|
2137
|
-
tcl_tk_ver_str =
|
|
2556
|
+
tcl_tk_prefix = await asyncio_subprocess_check_output_str('brew', '--prefix', 'tcl-tk')
|
|
2557
|
+
tcl_tk_ver_str = await asyncio_subprocess_check_output_str('brew', 'ls', '--versions', 'tcl-tk')
|
|
2138
2558
|
tcl_tk_ver = '.'.join(tcl_tk_ver_str.split()[1].split('.')[:2])
|
|
2139
2559
|
|
|
2140
2560
|
return PyenvInstallOpts(conf_opts=[
|
|
@@ -2149,11 +2569,11 @@ class DarwinPyenvInstallOpts(PyenvInstallOptsProvider):
|
|
|
2149
2569
|
# pkg_config_path += ':' + os.environ['PKG_CONFIG_PATH']
|
|
2150
2570
|
# return PyenvInstallOpts(env={'PKG_CONFIG_PATH': pkg_config_path})
|
|
2151
2571
|
|
|
2152
|
-
def opts(self) -> PyenvInstallOpts:
|
|
2572
|
+
async def opts(self) -> PyenvInstallOpts:
|
|
2153
2573
|
return PyenvInstallOpts().merge(
|
|
2154
2574
|
self.framework_opts(),
|
|
2155
|
-
self.brew_deps_opts(),
|
|
2156
|
-
self.brew_tcl_opts(),
|
|
2575
|
+
await self.brew_deps_opts(),
|
|
2576
|
+
await self.brew_tcl_opts(),
|
|
2157
2577
|
# self.brew_ssl_opts(),
|
|
2158
2578
|
)
|
|
2159
2579
|
|
|
@@ -2185,20 +2605,8 @@ class PyenvVersionInstaller:
|
|
|
2185
2605
|
) -> None:
|
|
2186
2606
|
super().__init__()
|
|
2187
2607
|
|
|
2188
|
-
if no_default_opts:
|
|
2189
|
-
if opts is None:
|
|
2190
|
-
opts = PyenvInstallOpts()
|
|
2191
|
-
else:
|
|
2192
|
-
lst = [opts if opts is not None else DEFAULT_PYENV_INSTALL_OPTS]
|
|
2193
|
-
if interp_opts.debug:
|
|
2194
|
-
lst.append(DEBUG_PYENV_INSTALL_OPTS)
|
|
2195
|
-
if interp_opts.threaded:
|
|
2196
|
-
lst.append(THREADED_PYENV_INSTALL_OPTS)
|
|
2197
|
-
lst.append(PLATFORM_PYENV_INSTALL_OPTS[sys.platform].opts())
|
|
2198
|
-
opts = PyenvInstallOpts().merge(*lst)
|
|
2199
|
-
|
|
2200
2608
|
self._version = version
|
|
2201
|
-
self.
|
|
2609
|
+
self._given_opts = opts
|
|
2202
2610
|
self._interp_opts = interp_opts
|
|
2203
2611
|
self._given_install_name = install_name
|
|
2204
2612
|
|
|
@@ -2209,9 +2617,21 @@ class PyenvVersionInstaller:
|
|
|
2209
2617
|
def version(self) -> str:
|
|
2210
2618
|
return self._version
|
|
2211
2619
|
|
|
2212
|
-
@
|
|
2213
|
-
def opts(self) -> PyenvInstallOpts:
|
|
2214
|
-
|
|
2620
|
+
@async_cached_nullary
|
|
2621
|
+
async def opts(self) -> PyenvInstallOpts:
|
|
2622
|
+
opts = self._given_opts
|
|
2623
|
+
if self._no_default_opts:
|
|
2624
|
+
if opts is None:
|
|
2625
|
+
opts = PyenvInstallOpts()
|
|
2626
|
+
else:
|
|
2627
|
+
lst = [self._given_opts if self._given_opts is not None else DEFAULT_PYENV_INSTALL_OPTS]
|
|
2628
|
+
if self._interp_opts.debug:
|
|
2629
|
+
lst.append(DEBUG_PYENV_INSTALL_OPTS)
|
|
2630
|
+
if self._interp_opts.threaded:
|
|
2631
|
+
lst.append(THREADED_PYENV_INSTALL_OPTS)
|
|
2632
|
+
lst.append(await PLATFORM_PYENV_INSTALL_OPTS[sys.platform].opts())
|
|
2633
|
+
opts = PyenvInstallOpts().merge(*lst)
|
|
2634
|
+
return opts
|
|
2215
2635
|
|
|
2216
2636
|
@cached_nullary
|
|
2217
2637
|
def install_name(self) -> str:
|
|
@@ -2219,17 +2639,18 @@ class PyenvVersionInstaller:
|
|
|
2219
2639
|
return self._given_install_name
|
|
2220
2640
|
return self._version + ('-debug' if self._interp_opts.debug else '')
|
|
2221
2641
|
|
|
2222
|
-
@
|
|
2223
|
-
def install_dir(self) -> str:
|
|
2224
|
-
return str(os.path.join(check_not_none(self._pyenv.root()), 'versions', self.install_name()))
|
|
2642
|
+
@async_cached_nullary
|
|
2643
|
+
async def install_dir(self) -> str:
|
|
2644
|
+
return str(os.path.join(check_not_none(await self._pyenv.root()), 'versions', self.install_name()))
|
|
2225
2645
|
|
|
2226
|
-
@
|
|
2227
|
-
def install(self) -> str:
|
|
2228
|
-
|
|
2646
|
+
@async_cached_nullary
|
|
2647
|
+
async def install(self) -> str:
|
|
2648
|
+
opts = await self.opts()
|
|
2649
|
+
env = {**os.environ, **opts.env}
|
|
2229
2650
|
for k, l in [
|
|
2230
|
-
('CFLAGS',
|
|
2231
|
-
('LDFLAGS',
|
|
2232
|
-
('PYTHON_CONFIGURE_OPTS',
|
|
2651
|
+
('CFLAGS', opts.cflags),
|
|
2652
|
+
('LDFLAGS', opts.ldflags),
|
|
2653
|
+
('PYTHON_CONFIGURE_OPTS', opts.conf_opts),
|
|
2233
2654
|
]:
|
|
2234
2655
|
v = ' '.join(l)
|
|
2235
2656
|
if k in os.environ:
|
|
@@ -2237,13 +2658,13 @@ class PyenvVersionInstaller:
|
|
|
2237
2658
|
env[k] = v
|
|
2238
2659
|
|
|
2239
2660
|
conf_args = [
|
|
2240
|
-
*
|
|
2661
|
+
*opts.opts,
|
|
2241
2662
|
self._version,
|
|
2242
2663
|
]
|
|
2243
2664
|
|
|
2244
2665
|
if self._given_install_name is not None:
|
|
2245
2666
|
full_args = [
|
|
2246
|
-
os.path.join(check_not_none(self._pyenv.root()), 'plugins', 'python-build', 'bin', 'python-build'),
|
|
2667
|
+
os.path.join(check_not_none(await self._pyenv.root()), 'plugins', 'python-build', 'bin', 'python-build'), # noqa
|
|
2247
2668
|
*conf_args,
|
|
2248
2669
|
self.install_dir(),
|
|
2249
2670
|
]
|
|
@@ -2254,12 +2675,12 @@ class PyenvVersionInstaller:
|
|
|
2254
2675
|
*conf_args,
|
|
2255
2676
|
]
|
|
2256
2677
|
|
|
2257
|
-
|
|
2678
|
+
await asyncio_subprocess_check_call(
|
|
2258
2679
|
*full_args,
|
|
2259
2680
|
env=env,
|
|
2260
2681
|
)
|
|
2261
2682
|
|
|
2262
|
-
exe = os.path.join(self.install_dir(), 'bin', 'python')
|
|
2683
|
+
exe = os.path.join(await self.install_dir(), 'bin', 'python')
|
|
2263
2684
|
if not os.path.isfile(exe):
|
|
2264
2685
|
raise RuntimeError(f'Interpreter not found: {exe}')
|
|
2265
2686
|
return exe
|
|
@@ -2269,7 +2690,6 @@ class PyenvVersionInstaller:
|
|
|
2269
2690
|
|
|
2270
2691
|
|
|
2271
2692
|
class PyenvInterpProvider(InterpProvider):
|
|
2272
|
-
|
|
2273
2693
|
def __init__(
|
|
2274
2694
|
self,
|
|
2275
2695
|
pyenv: Pyenv = Pyenv(),
|
|
@@ -2312,11 +2732,11 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2312
2732
|
exe: str
|
|
2313
2733
|
version: InterpVersion
|
|
2314
2734
|
|
|
2315
|
-
def _make_installed(self, vn: str, ep: str) -> ta.Optional[Installed]:
|
|
2735
|
+
async def _make_installed(self, vn: str, ep: str) -> ta.Optional[Installed]:
|
|
2316
2736
|
iv: ta.Optional[InterpVersion]
|
|
2317
2737
|
if self._inspect:
|
|
2318
2738
|
try:
|
|
2319
|
-
iv = check_not_none(self._inspector.inspect(ep)).iv
|
|
2739
|
+
iv = check_not_none(await self._inspector.inspect(ep)).iv
|
|
2320
2740
|
except Exception as e: # noqa
|
|
2321
2741
|
return None
|
|
2322
2742
|
else:
|
|
@@ -2329,10 +2749,10 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2329
2749
|
version=iv,
|
|
2330
2750
|
)
|
|
2331
2751
|
|
|
2332
|
-
def installed(self) -> ta.Sequence[Installed]:
|
|
2752
|
+
async def installed(self) -> ta.Sequence[Installed]:
|
|
2333
2753
|
ret: ta.List[PyenvInterpProvider.Installed] = []
|
|
2334
|
-
for vn, ep in self._pyenv.version_exes():
|
|
2335
|
-
if (i := self._make_installed(vn, ep)) is None:
|
|
2754
|
+
for vn, ep in await self._pyenv.version_exes():
|
|
2755
|
+
if (i := await self._make_installed(vn, ep)) is None:
|
|
2336
2756
|
log.debug('Invalid pyenv version: %s', vn)
|
|
2337
2757
|
continue
|
|
2338
2758
|
ret.append(i)
|
|
@@ -2340,11 +2760,11 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2340
2760
|
|
|
2341
2761
|
#
|
|
2342
2762
|
|
|
2343
|
-
def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2344
|
-
return [i.version for i in self.installed()]
|
|
2763
|
+
async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2764
|
+
return [i.version for i in await self.installed()]
|
|
2345
2765
|
|
|
2346
|
-
def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2347
|
-
for i in self.installed():
|
|
2766
|
+
async def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2767
|
+
for i in await self.installed():
|
|
2348
2768
|
if i.version == version:
|
|
2349
2769
|
return Interp(
|
|
2350
2770
|
exe=i.exe,
|
|
@@ -2354,10 +2774,10 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2354
2774
|
|
|
2355
2775
|
#
|
|
2356
2776
|
|
|
2357
|
-
def _get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2777
|
+
async def _get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2358
2778
|
lst = []
|
|
2359
2779
|
|
|
2360
|
-
for vs in self._pyenv.installable_versions():
|
|
2780
|
+
for vs in await self._pyenv.installable_versions():
|
|
2361
2781
|
if (iv := self.guess_version(vs)) is None:
|
|
2362
2782
|
continue
|
|
2363
2783
|
if iv.opts.debug:
|
|
@@ -2367,16 +2787,16 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2367
2787
|
|
|
2368
2788
|
return lst
|
|
2369
2789
|
|
|
2370
|
-
def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2371
|
-
lst = self._get_installable_versions(spec)
|
|
2790
|
+
async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2791
|
+
lst = await self._get_installable_versions(spec)
|
|
2372
2792
|
|
|
2373
2793
|
if self._try_update and not any(v in spec for v in lst):
|
|
2374
2794
|
if self._pyenv.update():
|
|
2375
|
-
lst = self._get_installable_versions(spec)
|
|
2795
|
+
lst = await self._get_installable_versions(spec)
|
|
2376
2796
|
|
|
2377
2797
|
return lst
|
|
2378
2798
|
|
|
2379
|
-
def install_version(self, version: InterpVersion) -> Interp:
|
|
2799
|
+
async def install_version(self, version: InterpVersion) -> Interp:
|
|
2380
2800
|
inst_version = str(version.version)
|
|
2381
2801
|
inst_opts = version.opts
|
|
2382
2802
|
if inst_opts.threaded:
|
|
@@ -2388,7 +2808,7 @@ class PyenvInterpProvider(InterpProvider):
|
|
|
2388
2808
|
interp_opts=inst_opts,
|
|
2389
2809
|
)
|
|
2390
2810
|
|
|
2391
|
-
exe = installer.install()
|
|
2811
|
+
exe = await installer.install()
|
|
2392
2812
|
return Interp(exe, version)
|
|
2393
2813
|
|
|
2394
2814
|
|
|
@@ -2467,7 +2887,7 @@ class SystemInterpProvider(InterpProvider):
|
|
|
2467
2887
|
|
|
2468
2888
|
#
|
|
2469
2889
|
|
|
2470
|
-
def get_exe_version(self, exe: str) -> ta.Optional[InterpVersion]:
|
|
2890
|
+
async def get_exe_version(self, exe: str) -> ta.Optional[InterpVersion]:
|
|
2471
2891
|
if not self.inspect:
|
|
2472
2892
|
s = os.path.basename(exe)
|
|
2473
2893
|
if s.startswith('python'):
|
|
@@ -2477,13 +2897,13 @@ class SystemInterpProvider(InterpProvider):
|
|
|
2477
2897
|
return InterpVersion.parse(s)
|
|
2478
2898
|
except InvalidVersion:
|
|
2479
2899
|
pass
|
|
2480
|
-
ii = self.inspector.inspect(exe)
|
|
2900
|
+
ii = await self.inspector.inspect(exe)
|
|
2481
2901
|
return ii.iv if ii is not None else None
|
|
2482
2902
|
|
|
2483
|
-
def exe_versions(self) -> ta.Sequence[ta.Tuple[str, InterpVersion]]:
|
|
2903
|
+
async def exe_versions(self) -> ta.Sequence[ta.Tuple[str, InterpVersion]]:
|
|
2484
2904
|
lst = []
|
|
2485
2905
|
for e in self.exes():
|
|
2486
|
-
if (ev := self.get_exe_version(e)) is None:
|
|
2906
|
+
if (ev := await self.get_exe_version(e)) is None:
|
|
2487
2907
|
log.debug('Invalid system version: %s', e)
|
|
2488
2908
|
continue
|
|
2489
2909
|
lst.append((e, ev))
|
|
@@ -2491,11 +2911,11 @@ class SystemInterpProvider(InterpProvider):
|
|
|
2491
2911
|
|
|
2492
2912
|
#
|
|
2493
2913
|
|
|
2494
|
-
def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2495
|
-
return [ev for e, ev in self.exe_versions()]
|
|
2914
|
+
async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
2915
|
+
return [ev for e, ev in await self.exe_versions()]
|
|
2496
2916
|
|
|
2497
|
-
def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2498
|
-
for e, ev in self.exe_versions():
|
|
2917
|
+
async def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
2918
|
+
for e, ev in await self.exe_versions():
|
|
2499
2919
|
if ev != version:
|
|
2500
2920
|
continue
|
|
2501
2921
|
return Interp(
|
|
@@ -2520,13 +2940,14 @@ class InterpResolver:
|
|
|
2520
2940
|
providers: ta.Sequence[ta.Tuple[str, InterpProvider]],
|
|
2521
2941
|
) -> None:
|
|
2522
2942
|
super().__init__()
|
|
2943
|
+
|
|
2523
2944
|
self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers)
|
|
2524
2945
|
|
|
2525
|
-
def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
|
|
2946
|
+
async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
|
|
2526
2947
|
lst = [
|
|
2527
2948
|
(i, si)
|
|
2528
2949
|
for i, p in enumerate(self._providers.values())
|
|
2529
|
-
for si in p.get_installed_versions(spec)
|
|
2950
|
+
for si in await p.get_installed_versions(spec)
|
|
2530
2951
|
if spec.contains(si)
|
|
2531
2952
|
]
|
|
2532
2953
|
|
|
@@ -2538,16 +2959,16 @@ class InterpResolver:
|
|
|
2538
2959
|
bp = list(self._providers.values())[bi]
|
|
2539
2960
|
return (bp, bv)
|
|
2540
2961
|
|
|
2541
|
-
def resolve(
|
|
2962
|
+
async def resolve(
|
|
2542
2963
|
self,
|
|
2543
2964
|
spec: InterpSpecifier,
|
|
2544
2965
|
*,
|
|
2545
2966
|
install: bool = False,
|
|
2546
2967
|
) -> ta.Optional[Interp]:
|
|
2547
|
-
tup = self._resolve_installed(spec)
|
|
2968
|
+
tup = await self._resolve_installed(spec)
|
|
2548
2969
|
if tup is not None:
|
|
2549
2970
|
bp, bv = tup
|
|
2550
|
-
return bp.get_installed_version(bv)
|
|
2971
|
+
return await bp.get_installed_version(bv)
|
|
2551
2972
|
|
|
2552
2973
|
if not install:
|
|
2553
2974
|
return None
|
|
@@ -2555,21 +2976,21 @@ class InterpResolver:
|
|
|
2555
2976
|
tp = list(self._providers.values())[0] # noqa
|
|
2556
2977
|
|
|
2557
2978
|
sv = sorted(
|
|
2558
|
-
[s for s in tp.get_installable_versions(spec) if s in spec],
|
|
2979
|
+
[s for s in await tp.get_installable_versions(spec) if s in spec],
|
|
2559
2980
|
key=lambda s: s.version,
|
|
2560
2981
|
)
|
|
2561
2982
|
if not sv:
|
|
2562
2983
|
return None
|
|
2563
2984
|
|
|
2564
2985
|
bv = sv[-1]
|
|
2565
|
-
return tp.install_version(bv)
|
|
2986
|
+
return await tp.install_version(bv)
|
|
2566
2987
|
|
|
2567
|
-
def list(self, spec: InterpSpecifier) -> None:
|
|
2988
|
+
async def list(self, spec: InterpSpecifier) -> None:
|
|
2568
2989
|
print('installed:')
|
|
2569
2990
|
for n, p in self._providers.items():
|
|
2570
2991
|
lst = [
|
|
2571
2992
|
si
|
|
2572
|
-
for si in p.get_installed_versions(spec)
|
|
2993
|
+
for si in await p.get_installed_versions(spec)
|
|
2573
2994
|
if spec.contains(si)
|
|
2574
2995
|
]
|
|
2575
2996
|
if lst:
|
|
@@ -2583,7 +3004,7 @@ class InterpResolver:
|
|
|
2583
3004
|
for n, p in self._providers.items():
|
|
2584
3005
|
lst = [
|
|
2585
3006
|
si
|
|
2586
|
-
for si in p.get_installable_versions(spec)
|
|
3007
|
+
for si in await p.get_installable_versions(spec)
|
|
2587
3008
|
if spec.contains(si)
|
|
2588
3009
|
]
|
|
2589
3010
|
if lst:
|
|
@@ -2606,20 +3027,20 @@ DEFAULT_INTERP_RESOLVER = InterpResolver([(p.name, p) for p in [
|
|
|
2606
3027
|
# cli.py
|
|
2607
3028
|
|
|
2608
3029
|
|
|
2609
|
-
def _list_cmd(args) -> None:
|
|
3030
|
+
async def _list_cmd(args) -> None:
|
|
2610
3031
|
r = DEFAULT_INTERP_RESOLVER
|
|
2611
3032
|
s = InterpSpecifier.parse(args.version)
|
|
2612
|
-
r.list(s)
|
|
3033
|
+
await r.list(s)
|
|
2613
3034
|
|
|
2614
3035
|
|
|
2615
|
-
def _resolve_cmd(args) -> None:
|
|
3036
|
+
async def _resolve_cmd(args) -> None:
|
|
2616
3037
|
if args.provider:
|
|
2617
3038
|
p = INTERP_PROVIDER_TYPES_BY_NAME[args.provider]()
|
|
2618
3039
|
r = InterpResolver([(p.name, p)])
|
|
2619
3040
|
else:
|
|
2620
3041
|
r = DEFAULT_INTERP_RESOLVER
|
|
2621
3042
|
s = InterpSpecifier.parse(args.version)
|
|
2622
|
-
print(check_not_none(r.resolve(s, install=bool(args.install))).exe)
|
|
3043
|
+
print(check_not_none(await r.resolve(s, install=bool(args.install))).exe)
|
|
2623
3044
|
|
|
2624
3045
|
|
|
2625
3046
|
def _build_parser() -> argparse.ArgumentParser:
|
|
@@ -2642,7 +3063,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2642
3063
|
return parser
|
|
2643
3064
|
|
|
2644
3065
|
|
|
2645
|
-
def
|
|
3066
|
+
async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
2646
3067
|
check_runtime_version()
|
|
2647
3068
|
configure_standard_logging()
|
|
2648
3069
|
|
|
@@ -2651,7 +3072,11 @@ def _main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
|
2651
3072
|
if not getattr(args, 'func', None):
|
|
2652
3073
|
parser.print_help()
|
|
2653
3074
|
else:
|
|
2654
|
-
args.func(args)
|
|
3075
|
+
await args.func(args)
|
|
3076
|
+
|
|
3077
|
+
|
|
3078
|
+
def _main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
|
|
3079
|
+
asyncio.run(_async_main(argv))
|
|
2655
3080
|
|
|
2656
3081
|
|
|
2657
3082
|
if __name__ == '__main__':
|