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 | *.tar.gz | ||||||
| .vscode/* | .vscode/* | ||||||
| !.vscode/launch.json | !.vscode/launch.json | ||||||
|  | python/build | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ mypy_path = | |||||||
|     mypy-stubs, |     mypy-stubs, | ||||||
|     deps/com.github.aiortc.aiortc/src, |     deps/com.github.aiortc.aiortc/src, | ||||||
|     mypy-stubs/marisa-trie-types, |     mypy-stubs/marisa-trie-types, | ||||||
|  |     mypy-stubs/types-debugpy, | ||||||
|     python |     python | ||||||
| 
 | 
 | ||||||
| plugins = | 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): | def pass_ssh_osx(argv): | ||||||
|     assert isinstance(argv, list) and all([isinstance(o, str) for o in argv]) |     assert isinstance(argv, list) and all([isinstance(o, str) for o in argv]) | ||||||
|     parser = optparse.OptionParser() |     parser = optparse.OptionParser() | ||||||
| @ -1415,6 +1421,17 @@ def pass_ssh_osx(argv): | |||||||
|         default=None, |         default=None, | ||||||
|         type=str, |         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( |     parser.add_option( | ||||||
|         '--debug', |         '--debug', | ||||||
|         dest='debug', |         dest='debug', | ||||||
| @ -1424,6 +1441,11 @@ def pass_ssh_osx(argv): | |||||||
|     assert sys.platform in ['darwin', 'linux'] |     assert sys.platform in ['darwin', 'linux'] | ||||||
|     options, args = parser.parse_args(argv) |     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 options.clipboard_copy is None: | ||||||
|         if sys.platform == 'linux': |         if sys.platform == 'linux': | ||||||
|             options.clipboard_copy  = 'wl-copy' |             options.clipboard_copy  = 'wl-copy' | ||||||
| @ -1596,23 +1618,30 @@ def pass_ssh_osx(argv): | |||||||
|             assert not password is None |             assert not password is None | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         try: |         if options.mode is pass_ssh_osx_t.kwargs_t.Mode.clipboard: | ||||||
|             clipboard_set(password) |             try: | ||||||
|             get_time = lambda : datetime.datetime.now().timestamp() |                 clipboard_set(password) | ||||||
|             start = get_time() |                 get_time = lambda : datetime.datetime.now().timestamp() | ||||||
|             while True: |                 start = get_time() | ||||||
|                 cur = get_time() |                 while True: | ||||||
|                 remains = 10 - (cur - start) |                     cur = get_time() | ||||||
|                 if remains <= 1e-8: |                     remains = 10 - (cur - start) | ||||||
|                     break |                     if remains <= 1e-8: | ||||||
|                 else: |                         break | ||||||
|                     print('\r%5.2fs remains' % remains, end='') |                     else: | ||||||
|                 time.sleep(0.1) |                         print('\r%5.2fs remains' % remains, end='') | ||||||
|         except KeyboardInterrupt: |                     time.sleep(0.1) | ||||||
|             pass |             except KeyboardInterrupt: | ||||||
|  |                 pass | ||||||
| 
 | 
 | ||||||
|         clipboard_set('') |             clipboard_set('') | ||||||
|         print('\rcleared cliboard\n', end='') |             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: | def vpn(argv: list[str]) -> None: | ||||||
|     python_path : list[str] |     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