Compare commits

..

6 Commits

Author SHA1 Message Date
1626974759 [+] update packaging
1. update cli and cli_bootstrap;
  1.1. use /meson and /pyproject
    build dirs to fix collision
    for install step;
2024-12-22 18:33:06 +03:00
ea63c67280 [+] update cli module; 2024-12-22 12:06:07 +03:00
34c65f7ba5 [+] update commands
1. add basic cli.py module;
  2. add stubs for debugpy;
2024-12-22 10:31:31 +03:00
dedff2aee5 [+] update repo 2024-12-12 17:03:33 +03:00
cb69309307 [+] update repo
1. add asyncio.handle_task_result;
  2. improve pass_ssh_osx;
  3. update vpn dependency;
2024-12-10 20:28:00 +03:00
0a50c26d1d [+] add qrcode mode for pass ssh osx 2024-12-05 09:03:22 +03:00
9 changed files with 492 additions and 17 deletions

1
.gitignore vendored

@ -12,3 +12,4 @@ d2/book1/books
*.tar.gz
.vscode/*
!.vscode/launch.json
python/build

@ -3,6 +3,7 @@ mypy_path =
mypy-stubs,
deps/com.github.aiortc.aiortc/src,
mypy-stubs/marisa-trie-types,
mypy-stubs/types-debugpy,
python
plugins =

@ -1 +1 @@
Subproject commit 1c8f054d29bfa9dae897f6101f95e8eb4f920305
Subproject commit 857be4a1fb1c07e2a239b61ce49b34cdd1698467

@ -0,0 +1,7 @@
def listen(
addr: tuple[str, int],
) -> None: ...
def wait_for_client() -> None: ...
def breakpoint() -> None: ...

@ -1392,6 +1392,12 @@ 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()
@ -1415,6 +1421,17 @@ 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',
@ -1424,6 +1441,11 @@ 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'
@ -1596,6 +1618,7 @@ 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()
@ -1613,6 +1636,12 @@ def pass_ssh_osx(argv):
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
def vpn(argv: list[str]) -> None:
python_path : list[str]

@ -0,0 +1,14 @@
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,)

@ -0,0 +1,284 @@
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)

@ -0,0 +1,114 @@
#!/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()

@ -0,0 +1,25 @@
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