Compare commits
No commits in common. "162697475973d02210795b7507da3d67bf78d7cc" and "a6cdf0352329094933dc48ac41b61c71e88d87fa" have entirely different histories.
1626974759
...
a6cdf03523
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,4 +12,3 @@ d2/book1/books
|
||||
*.tar.gz
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
python/build
|
||||
|
@ -3,7 +3,6 @@ mypy_path =
|
||||
mypy-stubs,
|
||||
deps/com.github.aiortc.aiortc/src,
|
||||
mypy-stubs/marisa-trie-types,
|
||||
mypy-stubs/types-debugpy,
|
||||
python
|
||||
|
||||
plugins =
|
||||
|
2
deps/com.github.aiortc.aiortc
vendored
2
deps/com.github.aiortc.aiortc
vendored
@ -1 +1 @@
|
||||
Subproject commit 857be4a1fb1c07e2a239b61ce49b34cdd1698467
|
||||
Subproject commit 1c8f054d29bfa9dae897f6101f95e8eb4f920305
|
@ -1,7 +0,0 @@
|
||||
def listen(
|
||||
addr: tuple[str, int],
|
||||
) -> None: ...
|
||||
|
||||
def wait_for_client() -> None: ...
|
||||
|
||||
def breakpoint() -> None: ...
|
@ -1392,12 +1392,6 @@ server {
|
||||
],
|
||||
)
|
||||
|
||||
class pass_ssh_osx_t:
|
||||
class kwargs_t:
|
||||
class Mode(enum.StrEnum):
|
||||
clipboard = 'clipboard'
|
||||
qrcode = 'qrcode'
|
||||
|
||||
def pass_ssh_osx(argv):
|
||||
assert isinstance(argv, list) and all([isinstance(o, str) for o in argv])
|
||||
parser = optparse.OptionParser()
|
||||
@ -1421,17 +1415,6 @@ def pass_ssh_osx(argv):
|
||||
default=None,
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
'--mode',
|
||||
dest='_mode',
|
||||
choices=[
|
||||
o.value
|
||||
for o in pass_ssh_osx_t.kwargs_t.Mode
|
||||
],
|
||||
default=None,
|
||||
help='a mode to retrieve the password',
|
||||
)
|
||||
parser.add_option(
|
||||
'--debug',
|
||||
dest='debug',
|
||||
@ -1441,11 +1424,6 @@ def pass_ssh_osx(argv):
|
||||
assert sys.platform in ['darwin', 'linux']
|
||||
options, args = parser.parse_args(argv)
|
||||
|
||||
if options._mode is None:
|
||||
options._mode = pass_ssh_osx_t.kwargs_t.Mode.clipboard.value
|
||||
|
||||
options.mode = pass_ssh_osx_t.kwargs_t.Mode(options._mode)
|
||||
|
||||
if options.clipboard_copy is None:
|
||||
if sys.platform == 'linux':
|
||||
options.clipboard_copy = 'wl-copy'
|
||||
@ -1618,30 +1596,23 @@ def pass_ssh_osx(argv):
|
||||
assert not password is None
|
||||
|
||||
|
||||
if options.mode is pass_ssh_osx_t.kwargs_t.Mode.clipboard:
|
||||
try:
|
||||
clipboard_set(password)
|
||||
get_time = lambda : datetime.datetime.now().timestamp()
|
||||
start = get_time()
|
||||
while True:
|
||||
cur = get_time()
|
||||
remains = 10 - (cur - start)
|
||||
if remains <= 1e-8:
|
||||
break
|
||||
else:
|
||||
print('\r%5.2fs remains' % remains, end='')
|
||||
time.sleep(0.1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
try:
|
||||
clipboard_set(password)
|
||||
get_time = lambda : datetime.datetime.now().timestamp()
|
||||
start = get_time()
|
||||
while True:
|
||||
cur = get_time()
|
||||
remains = 10 - (cur - start)
|
||||
if remains <= 1e-8:
|
||||
break
|
||||
else:
|
||||
print('\r%5.2fs remains' % remains, end='')
|
||||
time.sleep(0.1)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
clipboard_set('')
|
||||
print('\rcleared cliboard\n', end='')
|
||||
elif options.mode is pass_ssh_osx_t.kwargs_t.Mode.qrcode:
|
||||
assert subprocess.run(r'''
|
||||
qrencode -t PNG -o - | feh -
|
||||
''', input=password.encode('utf-8'), shell=True).returncode == 0
|
||||
else:
|
||||
raise NotImplementedError
|
||||
clipboard_set('')
|
||||
print('\rcleared cliboard\n', end='')
|
||||
|
||||
def vpn(argv: list[str]) -> None:
|
||||
python_path : list[str]
|
||||
|
@ -1,14 +0,0 @@
|
||||
import logging
|
||||
import asyncio
|
||||
|
||||
from typing import (Any,)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def handle_task_result(fut: asyncio.Future[Any]) -> None:
|
||||
try:
|
||||
fut.result()
|
||||
|
||||
logger.debug(dict(fut=fut, msg='done'), stacklevel=2,)
|
||||
except:
|
||||
logger.exception('', stacklevel=2,)
|
@ -1,284 +0,0 @@
|
||||
import dataclasses
|
||||
import io
|
||||
import glob
|
||||
import os
|
||||
import pathlib
|
||||
import logging
|
||||
import sys
|
||||
import subprocess
|
||||
import shutil
|
||||
import abc
|
||||
|
||||
from .os import shutil_which
|
||||
|
||||
from typing import (
|
||||
Optional,
|
||||
Literal,
|
||||
Any,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Project:
|
||||
source_dir : pathlib.Path
|
||||
build_dir : pathlib.Path
|
||||
dest_dir : pathlib.Path
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Dependency:
|
||||
name: str
|
||||
mode : Literal['pyproject', 'meson', 'meson-python', 'm']
|
||||
source_path : pathlib.Path
|
||||
args: Optional[list[str]] = None
|
||||
|
||||
@dataclasses.dataclass
|
||||
class DistSettings:
|
||||
wheel_dir : pathlib.Path
|
||||
python_path: pathlib.Path
|
||||
env_path: pathlib.Path
|
||||
|
||||
class CLI(abc.ABC):
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def dist_settings(self) -> DistSettings:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def projects(self) -> dict[str, Project]:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def dependencies(self) -> dict[str, Dependency]:
|
||||
raise NotImplementedError
|
||||
|
||||
def deploy_fetch_dist(
|
||||
self,
|
||||
force: bool,
|
||||
) -> None:
|
||||
for k, o in self.dependencies.items():
|
||||
whl_glob = self.dist_settings.wheel_dir / ('*%s*.whl' % o.name.replace('.', '_'))
|
||||
if len(glob.glob(
|
||||
str(whl_glob)
|
||||
)) == 0 or force:
|
||||
if o.source_path.exists():
|
||||
def whl_files_get() -> list[dict[str, Any]]:
|
||||
return [
|
||||
dict(
|
||||
path=o,
|
||||
stat=os.stat(o).st_mtime,
|
||||
)
|
||||
for o in glob.glob(
|
||||
str(whl_glob)
|
||||
)
|
||||
]
|
||||
|
||||
present_files = whl_files_get()
|
||||
|
||||
if o.mode == 'm':
|
||||
if (o.source_path / 'm.py').exists():
|
||||
cmd = [
|
||||
sys.executable,
|
||||
o.source_path / 'm.py',
|
||||
'deploy:wheel',
|
||||
'-o', self.settings.wheel_dir,
|
||||
]
|
||||
|
||||
if not o.args is None:
|
||||
cmd.extend(o.args)
|
||||
|
||||
subprocess.check_call(cmd)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
updated_files = whl_files_get()
|
||||
|
||||
def index_get(o: dict[str, Any]) -> tuple[Any, ...]:
|
||||
return (o['path'], o['stat'])
|
||||
|
||||
present_files_index = {
|
||||
index_get(o) : o
|
||||
for o in present_files
|
||||
}
|
||||
|
||||
new_files : list[dict[str, Any]] = []
|
||||
|
||||
for o in updated_files:
|
||||
entry_index = index_get(o)
|
||||
|
||||
if not entry_index in present_files_index:
|
||||
new_files.append(o)
|
||||
|
||||
if len(new_files) == 0:
|
||||
raise NotImplementedError
|
||||
|
||||
latest_file = sorted(
|
||||
new_files,
|
||||
key=lambda x: x['stat']
|
||||
)[-1]
|
||||
|
||||
subprocess.check_call([
|
||||
self.dist_settings.python_path,
|
||||
'-m', 'pip',
|
||||
'install',
|
||||
latest_file['path'],
|
||||
])
|
||||
|
||||
def deploy_wheel(
|
||||
self,
|
||||
project_name: str,
|
||||
argv: Optional[list[str]] = None,
|
||||
output_dir: Optional[pathlib.Path] = None,
|
||||
force: Optional[bool] = None,
|
||||
env: Optional[dict[str, str]] = None,
|
||||
) -> None:
|
||||
project = self.projects[project_name]
|
||||
|
||||
# subprocess.check_call([
|
||||
# sys.argv[0],
|
||||
# # sys.executable,
|
||||
# '-p', options.project,
|
||||
# Command.meson_setup.value,
|
||||
# ])
|
||||
|
||||
assert argv is None or len(argv) == 0
|
||||
|
||||
self.meson_install(
|
||||
project_name=project_name,
|
||||
force=force,
|
||||
)
|
||||
|
||||
if env is None:
|
||||
env = dict()
|
||||
|
||||
cmd = [
|
||||
sys.executable,
|
||||
'-m',
|
||||
'build',
|
||||
'-w', '-n',
|
||||
'-Csetup-args=-Dmodes=pyproject',
|
||||
'-Cbuild-dir=%s' % str(project.build_dir / 'pyproject'),
|
||||
'-Csetup-args=-Dinstall_path=%s' % str(project.dest_dir),
|
||||
# '-Cbuild-dir=%s' % str(project.build_dir),
|
||||
str(project.source_dir),
|
||||
]
|
||||
|
||||
if not output_dir is None:
|
||||
cmd.extend(['-o', str(output_dir)])
|
||||
|
||||
logger.info(dict(env=env))
|
||||
|
||||
subprocess.check_call(
|
||||
cmd,
|
||||
env=dict(list(os.environ.items())) | env,
|
||||
)
|
||||
|
||||
def meson_install(
|
||||
self,
|
||||
project_name: str,
|
||||
force: Optional[bool] = None,
|
||||
argv: Optional[list[str]] = None,
|
||||
) -> None:
|
||||
project = self.projects[project_name]
|
||||
|
||||
if force is None:
|
||||
force = False
|
||||
|
||||
if argv is None:
|
||||
argv = []
|
||||
|
||||
if force and project.dest_dir.exists():
|
||||
shutil.rmtree(project.dest_dir)
|
||||
|
||||
subprocess.check_call([
|
||||
shutil_which('meson', True,),
|
||||
'install',
|
||||
'-C',
|
||||
project.build_dir / 'meson',
|
||||
'--destdir', project.dest_dir,
|
||||
*argv,
|
||||
])
|
||||
|
||||
for o in glob.glob(
|
||||
str(project.dest_dir / 'lib' / 'pkgconfig' / '*.pc'),
|
||||
recursive=True,
|
||||
):
|
||||
logger.info(dict(
|
||||
path=o,
|
||||
action='patch prefix',
|
||||
))
|
||||
|
||||
with io.open(o, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
with io.open(o, 'w') as f:
|
||||
f.write(
|
||||
content.replace('prefix=/', 'prefix=${pcfiledir}/../../')
|
||||
)
|
||||
def ninja(
|
||||
self,
|
||||
project_name: str,
|
||||
argv: Optional[list[str]] = None,
|
||||
) -> None:
|
||||
project = self.projects[project_name]
|
||||
|
||||
if argv is None:
|
||||
argv = []
|
||||
|
||||
subprocess.check_call([
|
||||
shutil_which('ninja', True),
|
||||
'-C',
|
||||
str(project.build_dir / 'meson'),
|
||||
*argv,
|
||||
])
|
||||
|
||||
def meson_compile(
|
||||
self,
|
||||
project_name: str,
|
||||
argv: Optional[list[str]] = None,
|
||||
) -> None:
|
||||
project = self.projects[project_name]
|
||||
|
||||
if argv is None:
|
||||
argv = []
|
||||
|
||||
subprocess.check_call([
|
||||
shutil_which('meson', True,),
|
||||
'compile',
|
||||
'-C',
|
||||
project.build_dir / 'meson',
|
||||
*argv,
|
||||
])
|
||||
|
||||
def meson_setup(
|
||||
self,
|
||||
project_name: str,
|
||||
force: bool,
|
||||
argv: Optional[list[str]] = None,
|
||||
) -> None:
|
||||
project = self.projects[project_name]
|
||||
|
||||
if argv is None:
|
||||
argv = []
|
||||
|
||||
if force:
|
||||
if (project.build_dir / 'meson').exists():
|
||||
logger.info(dict(action='removing build dir', path=project.build_dir / 'meson'))
|
||||
shutil.rmtree(project.build_dir / 'meson')
|
||||
|
||||
cmd = [
|
||||
shutil_which('meson', True,),
|
||||
'setup',
|
||||
str(project.source_dir),
|
||||
str(project.build_dir / 'meson'),
|
||||
'-Dmodes=["meson"]',
|
||||
# '-Dpkgconfig.relocatable=true',
|
||||
'-Dprefix=/',
|
||||
*argv,
|
||||
]
|
||||
|
||||
logger.info(dict(cmd=cmd))
|
||||
|
||||
subprocess.check_call(cmd)
|
@ -1,114 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import glob
|
||||
import dataclasses
|
||||
import pathlib
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
import logging
|
||||
|
||||
from typing import (Self, Optional,)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class BootstrapSettings:
|
||||
env_path: pathlib.Path
|
||||
python_path: pathlib.Path
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls,
|
||||
base_dir: Optional[pathlib.Path] = None,
|
||||
) -> Self:
|
||||
if base_dir is None:
|
||||
base_dir = pathlib.Path.cwd()
|
||||
|
||||
env_path = base_dir / '.venv'
|
||||
python_path = env_path / 'bin' / 'python3'
|
||||
|
||||
return cls(
|
||||
env_path=env_path,
|
||||
python_path=python_path,
|
||||
)
|
||||
|
||||
def env_bootstrap() -> None:
|
||||
bootstrap_settings = BootstrapSettings.get()
|
||||
|
||||
subprocess.check_call([
|
||||
'uv', 'venv', '--seed', '--offline',
|
||||
str(bootstrap_settings.env_path)
|
||||
])
|
||||
|
||||
subprocess.check_call([
|
||||
'uv',
|
||||
'pip',
|
||||
'install',
|
||||
'-p',
|
||||
bootstrap_settings.python_path,
|
||||
'--offline',
|
||||
'uv',
|
||||
])
|
||||
|
||||
subprocess.check_call([
|
||||
bootstrap_settings.python_path,
|
||||
'-m',
|
||||
'uv', 'pip', 'install',
|
||||
'--offline',
|
||||
'build', 'setuptools', 'meson-python', 'pybind11',
|
||||
])
|
||||
|
||||
early_wheels = glob.glob(
|
||||
str(
|
||||
pathlib.Path(__file__).parent / 'deps' / 'dist' / 'early' / '*.whl'
|
||||
)
|
||||
)
|
||||
if len(early_wheels) > 0:
|
||||
subprocess.check_call([
|
||||
bootstrap_settings.python_path,
|
||||
'-m',
|
||||
'uv', 'pip', 'install',
|
||||
'--offline',
|
||||
*early_wheels,
|
||||
])
|
||||
|
||||
def paths_equal(
|
||||
a: pathlib.Path | str,
|
||||
b: pathlib.Path | str
|
||||
) -> bool:
|
||||
return (
|
||||
os.path.abspath(str(a)) ==
|
||||
os.path.abspath(str(b))
|
||||
)
|
||||
|
||||
def run() -> None:
|
||||
bootstrap_settings = BootstrapSettings.get()
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
if not bootstrap_settings.env_path.exists():
|
||||
env_bootstrap()
|
||||
|
||||
logger.info([sys.executable, sys.argv, bootstrap_settings.python_path])
|
||||
|
||||
if not paths_equal(sys.executable, bootstrap_settings.python_path):
|
||||
os.execv(
|
||||
str(bootstrap_settings.python_path),
|
||||
[
|
||||
str(bootstrap_settings.python_path),
|
||||
*sys.argv,
|
||||
]
|
||||
)
|
||||
|
||||
os.execv(
|
||||
str(bootstrap_settings.python_path),
|
||||
[
|
||||
str(bootstrap_settings.python_path),
|
||||
pathlib.Path(__file__).parent / 'cli.py',
|
||||
*sys.argv[1:],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
@ -1,25 +0,0 @@
|
||||
import shutil
|
||||
|
||||
from typing import (overload, Optional, Literal,)
|
||||
|
||||
@overload
|
||||
def shutil_which(
|
||||
name: str,
|
||||
raise_on_failure: Literal[True],
|
||||
) -> str: ...
|
||||
|
||||
@overload
|
||||
def shutil_which(
|
||||
name: str,
|
||||
raise_on_failure: bool,
|
||||
) -> Optional[str]: ...
|
||||
|
||||
def shutil_which(
|
||||
name: str,
|
||||
raise_on_failure: bool,
|
||||
) -> Optional[str]:
|
||||
res = shutil.which(name)
|
||||
if res is None and raise_on_failure:
|
||||
raise NotImplementedError
|
||||
else:
|
||||
return res
|
Loading…
Reference in New Issue
Block a user