Compare commits
	
		
			6 Commits
		
	
	
		
			a6cdf03523
			...
			1626974759
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1626974759 | |||
| ea63c67280 | |||
| 34c65f7ba5 | |||
| dedff2aee5 | |||
| cb69309307 | |||
| 0a50c26d1d | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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 = | ||||
|  | ||||
							
								
								
									
										2
									
								
								deps/com.github.aiortc.aiortc
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								deps/com.github.aiortc.aiortc
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit 1c8f054d29bfa9dae897f6101f95e8eb4f920305 | ||||
| Subproject commit 857be4a1fb1c07e2a239b61ce49b34cdd1698467 | ||||
							
								
								
									
										7
									
								
								mypy-stubs/types-debugpy/debugpy/__init__.pyi
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										7
									
								
								mypy-stubs/types-debugpy/debugpy/__init__.pyi
									
									
									
									
									
										Normal file
									
								
							| @ -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] | ||||
|  | ||||
							
								
								
									
										14
									
								
								python/online/fxreader/pr34/commands_typed/asyncio.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								python/online/fxreader/pr34/commands_typed/asyncio.py
									
									
									
									
									
										Normal file
									
								
							| @ -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,) | ||||
							
								
								
									
										284
									
								
								python/online/fxreader/pr34/commands_typed/cli.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										284
									
								
								python/online/fxreader/pr34/commands_typed/cli.py
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
							
								
								
									
										114
									
								
								python/online/fxreader/pr34/commands_typed/cli_bootstrap.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										114
									
								
								python/online/fxreader/pr34/commands_typed/cli_bootstrap.py
									
									
									
									
									
										Normal file
									
								
							| @ -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() | ||||
							
								
								
									
										25
									
								
								python/online/fxreader/pr34/commands_typed/os.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										25
									
								
								python/online/fxreader/pr34/commands_typed/os.py
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user