omdev 0.0.0.dev150__py3-none-any.whl → 0.0.0.dev152__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.

@@ -102,7 +102,7 @@ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
102
102
  # ../../omlish/lite/check.py
103
103
  SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
104
104
  CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None] # ta.TypeAlias
105
- CheckLateConfigureFn = ta.Callable[['Checks'], None]
105
+ CheckLateConfigureFn = ta.Callable[['Checks'], None] # ta.TypeAlias
106
106
  CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
107
107
  CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
108
108
  CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
@@ -112,8 +112,11 @@ UnparsedVersion = ta.Union['Version', str]
112
112
  UnparsedVersionVar = ta.TypeVar('UnparsedVersionVar', bound=UnparsedVersion)
113
113
  CallableVersionOperator = ta.Callable[['Version', str], bool]
114
114
 
115
+ # ../../omlish/argparse/cli.py
116
+ ArgparseCommandFn = ta.Callable[[], ta.Optional[int]] # ta.TypeAlias
117
+
115
118
  # ../../omlish/lite/subprocesses.py
116
- SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull']
119
+ SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
117
120
 
118
121
 
119
122
  ########################################
@@ -3253,6 +3256,278 @@ class SpecifierSet(BaseSpecifier):
3253
3256
  return iter(filtered)
3254
3257
 
3255
3258
 
3259
+ ########################################
3260
+ # ../../../omlish/argparse/cli.py
3261
+ """
3262
+ TODO:
3263
+ - default command
3264
+ - auto match all underscores to hyphens
3265
+ - pre-run, post-run hooks
3266
+ - exitstack?
3267
+ """
3268
+
3269
+
3270
+ ##
3271
+
3272
+
3273
+ @dc.dataclass(eq=False)
3274
+ class ArgparseArg:
3275
+ args: ta.Sequence[ta.Any]
3276
+ kwargs: ta.Mapping[str, ta.Any]
3277
+ dest: ta.Optional[str] = None
3278
+
3279
+ def __get__(self, instance, owner=None):
3280
+ if instance is None:
3281
+ return self
3282
+ return getattr(instance.args, self.dest) # type: ignore
3283
+
3284
+
3285
+ def argparse_arg(*args, **kwargs) -> ArgparseArg:
3286
+ return ArgparseArg(args, kwargs)
3287
+
3288
+
3289
+ #
3290
+
3291
+
3292
+ @dc.dataclass(eq=False)
3293
+ class ArgparseCommand:
3294
+ name: str
3295
+ fn: ArgparseCommandFn
3296
+ args: ta.Sequence[ArgparseArg] = () # noqa
3297
+
3298
+ # _: dc.KW_ONLY
3299
+
3300
+ aliases: ta.Optional[ta.Sequence[str]] = None
3301
+ parent: ta.Optional['ArgparseCommand'] = None
3302
+ accepts_unknown: bool = False
3303
+
3304
+ def __post_init__(self) -> None:
3305
+ def check_name(s: str) -> None:
3306
+ check.isinstance(s, str)
3307
+ check.not_in('_', s)
3308
+ check.not_empty(s)
3309
+ check_name(self.name)
3310
+ check.not_isinstance(self.aliases, str)
3311
+ for a in self.aliases or []:
3312
+ check_name(a)
3313
+
3314
+ check.arg(callable(self.fn))
3315
+ check.arg(all(isinstance(a, ArgparseArg) for a in self.args))
3316
+ check.isinstance(self.parent, (ArgparseCommand, type(None)))
3317
+ check.isinstance(self.accepts_unknown, bool)
3318
+
3319
+ functools.update_wrapper(self, self.fn)
3320
+
3321
+ def __get__(self, instance, owner=None):
3322
+ if instance is None:
3323
+ return self
3324
+ return dc.replace(self, fn=self.fn.__get__(instance, owner)) # noqa
3325
+
3326
+ def __call__(self, *args, **kwargs) -> ta.Optional[int]:
3327
+ return self.fn(*args, **kwargs)
3328
+
3329
+
3330
+ def argparse_command(
3331
+ *args: ArgparseArg,
3332
+ name: ta.Optional[str] = None,
3333
+ aliases: ta.Optional[ta.Iterable[str]] = None,
3334
+ parent: ta.Optional[ArgparseCommand] = None,
3335
+ accepts_unknown: bool = False,
3336
+ ) -> ta.Any: # ta.Callable[[ArgparseCommandFn], ArgparseCommand]: # FIXME
3337
+ for arg in args:
3338
+ check.isinstance(arg, ArgparseArg)
3339
+ check.isinstance(name, (str, type(None)))
3340
+ check.isinstance(parent, (ArgparseCommand, type(None)))
3341
+ check.not_isinstance(aliases, str)
3342
+
3343
+ def inner(fn):
3344
+ return ArgparseCommand(
3345
+ (name if name is not None else fn.__name__).replace('_', '-'),
3346
+ fn,
3347
+ args,
3348
+ aliases=tuple(aliases) if aliases is not None else None,
3349
+ parent=parent,
3350
+ accepts_unknown=accepts_unknown,
3351
+ )
3352
+
3353
+ return inner
3354
+
3355
+
3356
+ ##
3357
+
3358
+
3359
+ def _get_argparse_arg_ann_kwargs(ann: ta.Any) -> ta.Mapping[str, ta.Any]:
3360
+ if ann is str:
3361
+ return {}
3362
+ elif ann is int:
3363
+ return {'type': int}
3364
+ elif ann is bool:
3365
+ return {'action': 'store_true'}
3366
+ elif ann is list:
3367
+ return {'action': 'append'}
3368
+ else:
3369
+ raise TypeError(ann)
3370
+
3371
+
3372
+ class _ArgparseCliAnnotationBox:
3373
+ def __init__(self, annotations: ta.Mapping[str, ta.Any]) -> None:
3374
+ super().__init__()
3375
+ self.__annotations__ = annotations # type: ignore
3376
+
3377
+
3378
+ class ArgparseCli:
3379
+ def __init__(self, argv: ta.Optional[ta.Sequence[str]] = None) -> None:
3380
+ super().__init__()
3381
+
3382
+ self._argv = argv if argv is not None else sys.argv[1:]
3383
+
3384
+ self._args, self._unknown_args = self.get_parser().parse_known_args(self._argv)
3385
+
3386
+ #
3387
+
3388
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
3389
+ super().__init_subclass__(**kwargs)
3390
+
3391
+ ns = cls.__dict__
3392
+ objs = {}
3393
+ mro = cls.__mro__[::-1]
3394
+ for bns in [bcls.__dict__ for bcls in reversed(mro)] + [ns]:
3395
+ bseen = set() # type: ignore
3396
+ for k, v in bns.items():
3397
+ if isinstance(v, (ArgparseCommand, ArgparseArg)):
3398
+ check.not_in(v, bseen)
3399
+ bseen.add(v)
3400
+ objs[k] = v
3401
+ elif k in objs:
3402
+ del [k]
3403
+
3404
+ #
3405
+
3406
+ anns = ta.get_type_hints(_ArgparseCliAnnotationBox({
3407
+ **{k: v for bcls in reversed(mro) for k, v in getattr(bcls, '__annotations__', {}).items()},
3408
+ **ns.get('__annotations__', {}),
3409
+ }), globalns=ns.get('__globals__', {}))
3410
+
3411
+ #
3412
+
3413
+ if '_parser' in ns:
3414
+ parser = check.isinstance(ns['_parser'], argparse.ArgumentParser)
3415
+ else:
3416
+ parser = argparse.ArgumentParser()
3417
+ setattr(cls, '_parser', parser)
3418
+
3419
+ #
3420
+
3421
+ subparsers = parser.add_subparsers()
3422
+
3423
+ for att, obj in objs.items():
3424
+ if isinstance(obj, ArgparseCommand):
3425
+ if obj.parent is not None:
3426
+ raise NotImplementedError
3427
+
3428
+ for cn in [obj.name, *(obj.aliases or [])]:
3429
+ subparser = subparsers.add_parser(cn)
3430
+
3431
+ for arg in (obj.args or []):
3432
+ if (
3433
+ len(arg.args) == 1 and
3434
+ isinstance(arg.args[0], str) and
3435
+ not (n := check.isinstance(arg.args[0], str)).startswith('-') and
3436
+ 'metavar' not in arg.kwargs
3437
+ ):
3438
+ subparser.add_argument(
3439
+ n.replace('-', '_'),
3440
+ **arg.kwargs,
3441
+ metavar=n,
3442
+ )
3443
+ else:
3444
+ subparser.add_argument(*arg.args, **arg.kwargs)
3445
+
3446
+ subparser.set_defaults(_cmd=obj)
3447
+
3448
+ elif isinstance(obj, ArgparseArg):
3449
+ if att in anns:
3450
+ ann_kwargs = _get_argparse_arg_ann_kwargs(anns[att])
3451
+ obj.kwargs = {**ann_kwargs, **obj.kwargs}
3452
+
3453
+ if not obj.dest:
3454
+ if 'dest' in obj.kwargs:
3455
+ obj.dest = obj.kwargs['dest']
3456
+ else:
3457
+ obj.dest = obj.kwargs['dest'] = att # type: ignore
3458
+
3459
+ parser.add_argument(*obj.args, **obj.kwargs)
3460
+
3461
+ else:
3462
+ raise TypeError(obj)
3463
+
3464
+ #
3465
+
3466
+ _parser: ta.ClassVar[argparse.ArgumentParser]
3467
+
3468
+ @classmethod
3469
+ def get_parser(cls) -> argparse.ArgumentParser:
3470
+ return cls._parser
3471
+
3472
+ @property
3473
+ def argv(self) -> ta.Sequence[str]:
3474
+ return self._argv
3475
+
3476
+ @property
3477
+ def args(self) -> argparse.Namespace:
3478
+ return self._args
3479
+
3480
+ @property
3481
+ def unknown_args(self) -> ta.Sequence[str]:
3482
+ return self._unknown_args
3483
+
3484
+ #
3485
+
3486
+ def _bind_cli_cmd(self, cmd: ArgparseCommand) -> ta.Callable:
3487
+ return cmd.__get__(self, type(self))
3488
+
3489
+ def prepare_cli_run(self) -> ta.Optional[ta.Callable]:
3490
+ cmd = getattr(self.args, '_cmd', None)
3491
+
3492
+ if self._unknown_args and not (cmd is not None and cmd.accepts_unknown):
3493
+ msg = f'unrecognized arguments: {" ".join(self._unknown_args)}'
3494
+ if (parser := self.get_parser()).exit_on_error: # type: ignore
3495
+ parser.error(msg)
3496
+ else:
3497
+ raise argparse.ArgumentError(None, msg)
3498
+
3499
+ if cmd is None:
3500
+ self.get_parser().print_help()
3501
+ return None
3502
+
3503
+ return self._bind_cli_cmd(cmd)
3504
+
3505
+ #
3506
+
3507
+ def cli_run(self) -> ta.Optional[int]:
3508
+ if (fn := self.prepare_cli_run()) is None:
3509
+ return 0
3510
+
3511
+ return fn()
3512
+
3513
+ def cli_run_and_exit(self) -> ta.NoReturn:
3514
+ sys.exit(rc if isinstance(rc := self.cli_run(), int) else 0)
3515
+
3516
+ def __call__(self, *, exit: bool = False) -> ta.Optional[int]: # noqa
3517
+ if exit:
3518
+ return self.cli_run_and_exit()
3519
+ else:
3520
+ return self.cli_run()
3521
+
3522
+ #
3523
+
3524
+ async def async_cli_run(self) -> ta.Optional[int]:
3525
+ if (fn := self.prepare_cli_run()) is None:
3526
+ return 0
3527
+
3528
+ return await fn()
3529
+
3530
+
3256
3531
  ########################################
3257
3532
  # ../../../omlish/lite/logs.py
3258
3533
  """
@@ -6601,52 +6876,7 @@ DEFAULT_INTERP_RESOLVER = InterpResolver([(p.name, p) for p in [
6601
6876
 
6602
6877
 
6603
6878
  ########################################
6604
- # cli.py
6605
-
6606
-
6607
- ##
6608
-
6609
-
6610
- @dc.dataclass(frozen=True)
6611
- class VersionsFile:
6612
- name: ta.Optional[str] = '.versions'
6613
-
6614
- @staticmethod
6615
- def parse(s: str) -> ta.Mapping[str, str]:
6616
- return {
6617
- k: v
6618
- for l in s.splitlines()
6619
- if (sl := l.split('#')[0].strip())
6620
- for k, _, v in (sl.partition('='),)
6621
- }
6622
-
6623
- @cached_nullary
6624
- def contents(self) -> ta.Mapping[str, str]:
6625
- if not self.name or not os.path.exists(self.name):
6626
- return {}
6627
- with open(self.name) as f:
6628
- s = f.read()
6629
- return self.parse(s)
6630
-
6631
- @staticmethod
6632
- def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
6633
- pfx = 'PYTHON_'
6634
- return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
6635
-
6636
- @cached_nullary
6637
- def pythons(self) -> ta.Mapping[str, str]:
6638
- return self.get_pythons(self.contents())
6639
-
6640
-
6641
- ##
6642
-
6643
-
6644
- @cached_nullary
6645
- def _script_rel_path() -> str:
6646
- cwd = os.getcwd()
6647
- if not (f := __file__).startswith(cwd):
6648
- raise OSError(f'file {f} not in {cwd}')
6649
- return f[len(cwd):].lstrip(os.sep)
6879
+ # ../venvs.py
6650
6880
 
6651
6881
 
6652
6882
  ##
@@ -6692,12 +6922,12 @@ class Venv:
6692
6922
  return False
6693
6923
 
6694
6924
  log.info('Using interpreter %s', (ie := await self.interp_exe()))
6695
- subprocess_check_call(ie, '-m', 'venv', dn)
6925
+ await asyncio_subprocess_check_call(ie, '-m', 'venv', dn)
6696
6926
 
6697
6927
  ve = self.exe()
6698
6928
  uv = self._cfg.use_uv
6699
6929
 
6700
- subprocess_check_call(
6930
+ await asyncio_subprocess_check_call(
6701
6931
  ve,
6702
6932
  '-m', 'pip',
6703
6933
  'install', '-v', '--upgrade',
@@ -6715,7 +6945,7 @@ class Venv:
6715
6945
  # Caused by: Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: 30s). # noqa
6716
6946
  # UV_CONCURRENT_DOWNLOADS=4 UV_HTTP_TIMEOUT=3600
6717
6947
 
6718
- subprocess_check_call(
6948
+ await asyncio_subprocess_check_call(
6719
6949
  ve,
6720
6950
  '-m',
6721
6951
  *(['uv'] if uv else []),
@@ -6748,6 +6978,55 @@ class Venv:
6748
6978
  return self._resolve_srcs(self._cfg.srcs or [])
6749
6979
 
6750
6980
 
6981
+ ########################################
6982
+ # cli.py
6983
+
6984
+
6985
+ ##
6986
+
6987
+
6988
+ @dc.dataclass(frozen=True)
6989
+ class VersionsFile:
6990
+ name: ta.Optional[str] = '.versions'
6991
+
6992
+ @staticmethod
6993
+ def parse(s: str) -> ta.Mapping[str, str]:
6994
+ return {
6995
+ k: v
6996
+ for l in s.splitlines()
6997
+ if (sl := l.split('#')[0].strip())
6998
+ for k, _, v in (sl.partition('='),)
6999
+ }
7000
+
7001
+ @cached_nullary
7002
+ def contents(self) -> ta.Mapping[str, str]:
7003
+ if not self.name or not os.path.exists(self.name):
7004
+ return {}
7005
+ with open(self.name) as f:
7006
+ s = f.read()
7007
+ return self.parse(s)
7008
+
7009
+ @staticmethod
7010
+ def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
7011
+ pfx = 'PYTHON_'
7012
+ return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
7013
+
7014
+ @cached_nullary
7015
+ def pythons(self) -> ta.Mapping[str, str]:
7016
+ return self.get_pythons(self.contents())
7017
+
7018
+
7019
+ ##
7020
+
7021
+
7022
+ @cached_nullary
7023
+ def _script_rel_path() -> str:
7024
+ cwd = os.getcwd()
7025
+ if not (f := __file__).startswith(cwd):
7026
+ raise OSError(f'file {f} not in {cwd}')
7027
+ return f[len(cwd):].lstrip(os.sep)
7028
+
7029
+
6751
7030
  ##
6752
7031
 
6753
7032
 
@@ -6791,183 +7070,160 @@ class Run:
6791
7070
  ##
6792
7071
 
6793
7072
 
6794
- async def _venv_cmd(args) -> None:
6795
- venv = Run().venvs()[args.name]
6796
- if (sd := venv.cfg.docker) is not None and sd != (cd := args._docker_container): # noqa
6797
- script = ' '.join([
6798
- 'python3',
6799
- shlex.quote(_script_rel_path()),
6800
- f'--_docker_container={shlex.quote(sd)}',
6801
- *map(shlex.quote, sys.argv[1:]),
6802
- ])
7073
+ class PyprojectCli(ArgparseCli):
7074
+ _docker_container = argparse_arg('--_docker_container', help=argparse.SUPPRESS)
6803
7075
 
6804
- docker_env = {
6805
- 'DOCKER_HOST_PLATFORM': os.environ.get('DOCKER_HOST_PLATFORM', sys.platform),
6806
- }
6807
- for e in args.docker_env or []:
6808
- if '=' in e:
6809
- k, _, v = e.split('=')
6810
- docker_env[k] = v
6811
- else:
6812
- docker_env[e] = os.environ.get(e, '')
6813
-
6814
- subprocess_check_call(
6815
- 'docker',
6816
- 'compose',
6817
- '-f', 'docker/compose.yml',
6818
- 'exec',
6819
- *itertools.chain.from_iterable(
6820
- ('-e', f'{k}={v}')
6821
- for k, v in docker_env.items()
6822
- ),
6823
- '-it', sd,
6824
- 'bash', '--login', '-c', script,
6825
- )
6826
-
6827
- return
6828
-
6829
- cmd = args.cmd
6830
- if not cmd:
6831
- await venv.create()
6832
-
6833
- elif cmd == 'python':
6834
- await venv.create()
6835
- os.execl(
6836
- (exe := venv.exe()),
6837
- exe,
6838
- *args.args,
6839
- )
6840
-
6841
- elif cmd == 'exe':
6842
- await venv.create()
6843
- check.arg(not args.args)
6844
- print(venv.exe())
6845
-
6846
- elif cmd == 'run':
6847
- await venv.create()
6848
- sh = check.not_none(shutil.which('bash'))
6849
- script = ' '.join(args.args)
6850
- if not script:
6851
- script = sh
6852
- os.execl(
6853
- (bash := check.not_none(sh)),
6854
- bash,
6855
- '-c',
6856
- f'. {venv.dir_name}/bin/activate && ' + script,
6857
- )
7076
+ @argparse_command(
7077
+ argparse_arg('name'),
7078
+ argparse_arg('-e', '--docker-env', action='append'),
7079
+ argparse_arg('cmd', nargs='?'),
7080
+ argparse_arg('args', nargs=argparse.REMAINDER),
7081
+ )
7082
+ async def venv(self) -> None:
7083
+ venv = Run().venvs()[self.args.name]
7084
+ if (sd := venv.cfg.docker) is not None and sd != (cd := self.args._docker_container): # noqa
7085
+ script = ' '.join([
7086
+ 'python3',
7087
+ shlex.quote(_script_rel_path()),
7088
+ f'--_docker_container={shlex.quote(sd)}',
7089
+ *map(shlex.quote, sys.argv[1:]),
7090
+ ])
6858
7091
 
6859
- elif cmd == 'srcs':
6860
- check.arg(not args.args)
6861
- print('\n'.join(venv.srcs()))
7092
+ docker_env = {
7093
+ 'DOCKER_HOST_PLATFORM': os.environ.get('DOCKER_HOST_PLATFORM', sys.platform),
7094
+ }
7095
+ for e in self.args.docker_env or []:
7096
+ if '=' in e:
7097
+ k, _, v = e.split('=')
7098
+ docker_env[k] = v
7099
+ else:
7100
+ docker_env[e] = os.environ.get(e, '')
7101
+
7102
+ await asyncio_subprocess_check_call(
7103
+ 'docker',
7104
+ 'compose',
7105
+ '-f', 'docker/compose.yml',
7106
+ 'exec',
7107
+ *itertools.chain.from_iterable(
7108
+ ('-e', f'{k}={v}')
7109
+ for k, v in docker_env.items()
7110
+ ),
7111
+ '-it', sd,
7112
+ 'bash', '--login', '-c', script,
7113
+ )
6862
7114
 
6863
- elif cmd == 'test':
6864
- await venv.create()
6865
- subprocess_check_call(venv.exe(), '-m', 'pytest', *(args.args or []), *venv.srcs())
7115
+ return
6866
7116
 
6867
- else:
6868
- raise Exception(f'unknown subcommand: {cmd}')
7117
+ cmd = self.args.cmd
7118
+ if not cmd:
7119
+ await venv.create()
6869
7120
 
7121
+ elif cmd == 'python':
7122
+ await venv.create()
7123
+ os.execl(
7124
+ (exe := venv.exe()),
7125
+ exe,
7126
+ *self.args.args,
7127
+ )
6870
7128
 
6871
- ##
7129
+ elif cmd == 'exe':
7130
+ await venv.create()
7131
+ check.arg(not self.args.args)
7132
+ print(venv.exe())
7133
+
7134
+ elif cmd == 'run':
7135
+ await venv.create()
7136
+ sh = check.not_none(shutil.which('bash'))
7137
+ script = ' '.join(self.args.args)
7138
+ if not script:
7139
+ script = sh
7140
+ os.execl(
7141
+ (bash := check.not_none(sh)),
7142
+ bash,
7143
+ '-c',
7144
+ f'. {venv.dir_name}/bin/activate && ' + script,
7145
+ )
6872
7146
 
7147
+ elif cmd == 'srcs':
7148
+ check.arg(not self.args.args)
7149
+ print('\n'.join(venv.srcs()))
6873
7150
 
6874
- async def _pkg_cmd(args) -> None:
6875
- run = Run()
7151
+ elif cmd == 'test':
7152
+ await venv.create()
7153
+ await asyncio_subprocess_check_call(venv.exe(), '-m', 'pytest', *(self.args.args or []), *venv.srcs())
6876
7154
 
6877
- cmd = args.cmd
6878
- if not cmd:
6879
- raise Exception('must specify command')
7155
+ else:
7156
+ raise Exception(f'unknown subcommand: {cmd}')
7157
+
7158
+ @argparse_command(
7159
+ argparse_arg('-b', '--build', action='store_true'),
7160
+ argparse_arg('-r', '--revision', action='store_true'),
7161
+ argparse_arg('-j', '--jobs', type=int),
7162
+ argparse_arg('cmd', nargs='?'),
7163
+ argparse_arg('args', nargs=argparse.REMAINDER),
7164
+ )
7165
+ async def pkg(self) -> None:
7166
+ run = Run()
6880
7167
 
6881
- elif cmd == 'gen':
6882
- pkgs_root = os.path.join('.pkg')
7168
+ cmd = self.args.cmd
7169
+ if not cmd:
7170
+ raise Exception('must specify command')
6883
7171
 
6884
- if os.path.exists(pkgs_root):
6885
- shutil.rmtree(pkgs_root)
7172
+ elif cmd == 'gen':
7173
+ pkgs_root = os.path.join('.pkg')
6886
7174
 
6887
- build_output_dir = 'dist'
6888
- run_build = bool(args.build)
6889
- add_revision = bool(args.revision)
7175
+ if os.path.exists(pkgs_root):
7176
+ shutil.rmtree(pkgs_root)
6890
7177
 
6891
- if run_build:
6892
- os.makedirs(build_output_dir, exist_ok=True)
7178
+ build_output_dir = 'dist'
7179
+ run_build = bool(self.args.build)
7180
+ add_revision = bool(self.args.revision)
6893
7181
 
6894
- pgs: ta.List[BasePyprojectPackageGenerator] = [
6895
- PyprojectPackageGenerator(
6896
- dir_name,
6897
- pkgs_root,
6898
- )
6899
- for dir_name in run.cfg().pkgs
6900
- ]
6901
- pgs = list(itertools.chain.from_iterable([pg, *pg.children()] for pg in pgs))
7182
+ if run_build:
7183
+ os.makedirs(build_output_dir, exist_ok=True)
6902
7184
 
6903
- num_threads = args.jobs or int(max(mp.cpu_count() // 1.5, 1))
6904
- futs: ta.List[cf.Future]
6905
- with cf.ThreadPoolExecutor(num_threads) as ex:
6906
- futs = [ex.submit(pg.gen) for pg in pgs]
6907
- for fut in futs:
6908
- fut.result()
7185
+ pgs: ta.List[BasePyprojectPackageGenerator] = [
7186
+ PyprojectPackageGenerator(
7187
+ dir_name,
7188
+ pkgs_root,
7189
+ )
7190
+ for dir_name in run.cfg().pkgs
7191
+ ]
7192
+ pgs = list(itertools.chain.from_iterable([pg, *pg.children()] for pg in pgs))
6909
7193
 
6910
- if run_build:
6911
- futs = [
6912
- ex.submit(functools.partial(
6913
- pg.build,
6914
- build_output_dir,
6915
- BasePyprojectPackageGenerator.BuildOpts(
6916
- add_revision=add_revision,
6917
- ),
6918
- ))
6919
- for pg in pgs
6920
- ]
7194
+ num_threads = self.args.jobs or int(max(mp.cpu_count() // 1.5, 1))
7195
+ futs: ta.List[cf.Future]
7196
+ with cf.ThreadPoolExecutor(num_threads) as ex:
7197
+ futs = [ex.submit(pg.gen) for pg in pgs]
6921
7198
  for fut in futs:
6922
7199
  fut.result()
6923
7200
 
6924
- else:
6925
- raise Exception(f'unknown subcommand: {cmd}')
6926
-
7201
+ if run_build:
7202
+ futs = [
7203
+ ex.submit(functools.partial(
7204
+ pg.build,
7205
+ build_output_dir,
7206
+ BasePyprojectPackageGenerator.BuildOpts(
7207
+ add_revision=add_revision,
7208
+ ),
7209
+ ))
7210
+ for pg in pgs
7211
+ ]
7212
+ for fut in futs:
7213
+ fut.result()
6927
7214
 
6928
- ##
6929
-
6930
-
6931
- def _build_parser() -> argparse.ArgumentParser:
6932
- parser = argparse.ArgumentParser()
6933
- parser.add_argument('--_docker_container', help=argparse.SUPPRESS)
6934
-
6935
- subparsers = parser.add_subparsers()
6936
-
6937
- #
6938
-
6939
- parser_venv = subparsers.add_parser('venv')
6940
- parser_venv.add_argument('name')
6941
- parser_venv.add_argument('-e', '--docker-env', action='append')
6942
- parser_venv.add_argument('cmd', nargs='?')
6943
- parser_venv.add_argument('args', nargs=argparse.REMAINDER)
6944
- parser_venv.set_defaults(func=_venv_cmd)
6945
-
6946
- #
7215
+ else:
7216
+ raise Exception(f'unknown subcommand: {cmd}')
6947
7217
 
6948
- parser_pkg = subparsers.add_parser('pkg')
6949
- parser_pkg.add_argument('-b', '--build', action='store_true')
6950
- parser_pkg.add_argument('-r', '--revision', action='store_true')
6951
- parser_pkg.add_argument('-j', '--jobs', type=int)
6952
- parser_pkg.add_argument('cmd', nargs='?')
6953
- parser_pkg.add_argument('args', nargs=argparse.REMAINDER)
6954
- parser_pkg.set_defaults(func=_pkg_cmd)
6955
7218
 
6956
- #
6957
-
6958
- return parser
7219
+ ##
6959
7220
 
6960
7221
 
6961
7222
  async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
6962
7223
  check_runtime_version()
6963
7224
  configure_standard_logging()
6964
7225
 
6965
- parser = _build_parser()
6966
- args = parser.parse_args(argv)
6967
- if not getattr(args, 'func', None):
6968
- parser.print_help()
6969
- else:
6970
- await args.func(args)
7226
+ await PyprojectCli(argv).async_cli_run()
6971
7227
 
6972
7228
 
6973
7229
  def _main(argv: ta.Optional[ta.Sequence[str]] = None) -> None: