omdev 0.0.0.dev43__tar.gz → 0.0.0.dev45__tar.gz

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.

Files changed (129) hide show
  1. {omdev-0.0.0.dev43/omdev.egg-info → omdev-0.0.0.dev45}/PKG-INFO +2 -2
  2. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/.manifests.json +5 -5
  3. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cli/__main__.py +1 -1
  4. omdev-0.0.0.dev45/omdev/cli/clicli.py +71 -0
  5. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cli/install.py +32 -11
  6. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cli/main.py +12 -1
  7. omdev-0.0.0.dev45/omdev/cli/managers.py +107 -0
  8. omdev-0.0.0.dev45/omdev/tools/gittools.py +70 -0
  9. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/piptools.py +1 -1
  10. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45/omdev.egg-info}/PKG-INFO +2 -2
  11. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev.egg-info/SOURCES.txt +2 -1
  12. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev.egg-info/requires.txt +1 -1
  13. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/pyproject.toml +2 -2
  14. omdev-0.0.0.dev43/omdev/cli/clicmds.py +0 -83
  15. omdev-0.0.0.dev43/omdev/tools/gittools.py +0 -28
  16. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/LICENSE +0 -0
  17. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/MANIFEST.in +0 -0
  18. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/README.rst +0 -0
  19. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/__about__.py +0 -0
  20. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/__init__.py +0 -0
  21. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/amalg/__init__.py +0 -0
  22. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/amalg/__main__.py +0 -0
  23. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/amalg/amalg.py +0 -0
  24. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/bracepy.py +0 -0
  25. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/__init__.py +0 -0
  26. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/__init__.py +0 -0
  27. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/cache.py +0 -0
  28. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/contexts.py +0 -0
  29. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/currents.py +0 -0
  30. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/fns.py +0 -0
  31. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/resolvers.py +0 -0
  32. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/storage.py +0 -0
  33. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/compute/types.py +0 -0
  34. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/__init__.py +0 -0
  35. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/actions.py +0 -0
  36. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/cache.py +0 -0
  37. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/consts.py +0 -0
  38. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/defaults.py +0 -0
  39. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/manifests.py +0 -0
  40. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cache/data/specs.py +0 -0
  41. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/__init__.py +0 -0
  42. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_boilerplate.cc +0 -0
  43. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/LICENSE +0 -0
  44. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/__init__.py +0 -0
  45. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/build_ext.py +0 -0
  46. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
  47. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
  48. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/compilers/options.py +0 -0
  49. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
  50. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/dir_util.py +0 -0
  51. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/errors.py +0 -0
  52. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/extension.py +0 -0
  53. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/file_util.py +0 -0
  54. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/modified.py +0 -0
  55. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/spawn.py +0 -0
  56. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/sysconfig.py +0 -0
  57. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/util.py +0 -0
  58. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/_distutils/version.py +0 -0
  59. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/build.py +0 -0
  60. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/cmake.py +0 -0
  61. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/importhook.py +0 -0
  62. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/magic.py +0 -0
  63. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cexts/scan.py +0 -0
  64. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/classdot.py +0 -0
  65. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cli/__init__.py +0 -0
  66. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cli/types.py +0 -0
  67. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/cmake.py +0 -0
  68. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/findimports.py +0 -0
  69. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/findmagic.py +0 -0
  70. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/git.py +0 -0
  71. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/__init__.py +0 -0
  72. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/__main__.py +0 -0
  73. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/cli.py +0 -0
  74. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/inspect.py +0 -0
  75. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/providers.py +0 -0
  76. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/pyenv.py +0 -0
  77. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/resolvers.py +0 -0
  78. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/standalone.py +0 -0
  79. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/system.py +0 -0
  80. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/interp/types.py +0 -0
  81. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/manifests/__init__.py +0 -0
  82. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/manifests/build.py +0 -0
  83. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/manifests/load.py +0 -0
  84. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/manifests/types.py +0 -0
  85. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/mypy/__init__.py +0 -0
  86. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/mypy/debug.py +0 -0
  87. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/packaging/__init__.py +0 -0
  88. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/packaging/names.py +0 -0
  89. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/packaging/requires.py +0 -0
  90. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/packaging/specifiers.py +0 -0
  91. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/packaging/versions.py +0 -0
  92. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/__init__.py +0 -0
  93. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/__main__.py +0 -0
  94. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/base.py +0 -0
  95. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/git.py +0 -0
  96. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/lite.py +0 -0
  97. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/precheck.py +0 -0
  98. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/precheck/scripts.py +0 -0
  99. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/__init__.py +0 -0
  100. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/__main__.py +0 -0
  101. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/cexts.py +0 -0
  102. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/cli.py +0 -0
  103. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/configs.py +0 -0
  104. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/pkg.py +0 -0
  105. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/pyproject/reqs.py +0 -0
  106. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/revisions.py +0 -0
  107. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/__init__.py +0 -0
  108. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/bumpversion.py +0 -0
  109. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/execrss.py +0 -0
  110. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/exectime.py +0 -0
  111. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/importtrace.py +0 -0
  112. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/interp.py +0 -0
  113. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/scripts/pyproject.py +0 -0
  114. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/secrets.py +0 -0
  115. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tokens.py +0 -0
  116. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/toml/__init__.py +0 -0
  117. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/toml/parser.py +0 -0
  118. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/toml/writer.py +0 -0
  119. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/__init__.py +0 -0
  120. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/dockertools.py +0 -0
  121. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/importscan.py +0 -0
  122. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/proftools.py +0 -0
  123. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/rst.py +0 -0
  124. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/tools/sqlrepl.py +0 -0
  125. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev/wheelfile.py +0 -0
  126. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev.egg-info/dependency_links.txt +0 -0
  127. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev.egg-info/entry_points.txt +0 -0
  128. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/omdev.egg-info/top_level.txt +0 -0
  129. {omdev-0.0.0.dev43 → omdev-0.0.0.dev45}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev43
3
+ Version: 0.0.0.dev45
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: ~=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish==0.0.0.dev43
15
+ Requires-Dist: omlish==0.0.0.dev45
16
16
  Provides-Extra: all
17
17
  Requires-Dist: pycparser~=2.22; extra == "all"
18
18
  Requires-Dist: cffi~=1.17; extra == "all"
@@ -36,14 +36,14 @@
36
36
  }
37
37
  },
38
38
  {
39
- "module": ".cli.clicmds",
39
+ "module": ".cli.clicli",
40
40
  "attr": "_CLI_MODULE",
41
- "file": "omdev/cli/clicmds.py",
42
- "line": 57,
41
+ "file": "omdev/cli/clicli.py",
42
+ "line": 62,
43
43
  "value": {
44
44
  "$.cli.types.CliModule": {
45
45
  "cmd_name": "cli",
46
- "mod_name": "omdev.cli.clicmds"
46
+ "mod_name": "omdev.cli.clicli"
47
47
  }
48
48
  }
49
49
  },
@@ -135,7 +135,7 @@
135
135
  "module": ".tools.gittools",
136
136
  "attr": "_CLI_MODULE",
137
137
  "file": "omdev/tools/gittools.py",
138
- "line": 22,
138
+ "line": 64,
139
139
  "value": {
140
140
  "$.cli.types.CliModule": {
141
141
  "cmd_name": "git",
@@ -1,4 +1,4 @@
1
1
  if __name__ == '__main__':
2
- from .main import _main
2
+ from .main import _main # noqa
3
3
 
4
4
  _main()
@@ -0,0 +1,71 @@
1
+ import inspect
2
+ import os
3
+ import subprocess
4
+ import sys
5
+
6
+ from omlish import __about__
7
+ from omlish import argparse as ap
8
+
9
+ from . import install
10
+ from .types import CliModule
11
+
12
+
13
+ class CliCli(ap.Cli):
14
+
15
+ @ap.command(name='version')
16
+ def print_version(self) -> None:
17
+ print(__about__.__version__)
18
+
19
+ @ap.command(name='revision')
20
+ def print_revision(self) -> None:
21
+ print(__about__.__revision__)
22
+
23
+ @ap.command(
24
+ ap.arg('extra_deps', nargs='*'),
25
+ )
26
+ def reinstall(self) -> None:
27
+ mod_name = globals()['__spec__'].name
28
+ tool_name = '.'.join([mod_name.partition('.')[0], 'tools', 'piptools'])
29
+
30
+ out = subprocess.check_output([
31
+ sys.executable,
32
+ '-m',
33
+ tool_name,
34
+ 'list-root-dists',
35
+ ]).decode()
36
+
37
+ deps = sorted(
38
+ ({s for l in out.splitlines() if (s := l.strip())} | set(self.args.extra_deps or []))
39
+ - {install.DEFAULT_CLI_PKG} # noqa
40
+ )
41
+
42
+ if deps:
43
+ print('Reinstalling with following additional dependencies:')
44
+ print('\n'.join(' ' + d for d in deps))
45
+ else:
46
+ print('No additional dependencies detected.')
47
+ print()
48
+ print('Continue with reinstall? (ctrl-c to cancel)')
49
+ input()
50
+
51
+ install_src = inspect.getsource(install)
52
+
53
+ os.execl(
54
+ sys.executable,
55
+ sys.executable,
56
+ '-c',
57
+ install_src,
58
+ *deps,
59
+ )
60
+
61
+
62
+ # @omlish-manifest
63
+ _CLI_MODULE = CliModule('cli', __name__)
64
+
65
+
66
+ def _main() -> None:
67
+ CliCli()()
68
+
69
+
70
+ if __name__ == '__main__':
71
+ _main()
@@ -32,7 +32,7 @@ class InstallOpts:
32
32
  extras: ta.Sequence[str] = dc.field(default_factory=list)
33
33
 
34
34
 
35
- class InstallMgr(abc.ABC):
35
+ class InstallManager(abc.ABC):
36
36
  @abc.abstractmethod
37
37
  def is_available(self) -> bool:
38
38
  raise NotImplementedError
@@ -46,7 +46,7 @@ class InstallMgr(abc.ABC):
46
46
  raise NotImplementedError
47
47
 
48
48
 
49
- class UvxInstallMgr(InstallMgr):
49
+ class UvxInstallManager(InstallManager):
50
50
  def is_available(self) -> bool:
51
51
  return bool(shutil.which('uv'))
52
52
 
@@ -80,15 +80,25 @@ class UvxInstallMgr(InstallMgr):
80
80
  *itertools.chain.from_iterable(['--with', e] for e in (opts.extras or [])),
81
81
  ])
82
82
 
83
+ subprocess.check_call([
84
+ 'uv', 'tool',
85
+ 'run',
86
+ '--from', opts.cli_pkg,
87
+ 'om',
88
+ '_post_install',
89
+ ])
83
90
 
84
- class PipxInstallMgr(InstallMgr):
91
+
92
+ class PipxInstallManager(InstallManager):
85
93
  def is_available(self) -> bool:
86
94
  return bool(shutil.which('pipx'))
87
95
 
88
- def uninstall(self, cli_pkg: str) -> None:
96
+ def _list_installed(self) -> ta.Any:
89
97
  out = subprocess.check_output(['pipx', 'list', '--json']).decode()
98
+ return json.loads(out)
90
99
 
91
- dct = json.loads(out)
100
+ def uninstall(self, cli_pkg: str) -> None:
101
+ dct = self._list_installed()
92
102
 
93
103
  if cli_pkg not in dct.get('venvs', {}):
94
104
  return
@@ -108,10 +118,19 @@ class PipxInstallMgr(InstallMgr):
108
118
  *itertools.chain.from_iterable(['--preinstall', e] for e in (opts.extras or [])),
109
119
  ])
110
120
 
121
+ dct = self._list_installed()
111
122
 
112
- INSTALL_MGRS = {
113
- 'uvx': UvxInstallMgr(),
114
- 'pipx': PipxInstallMgr(),
123
+ exe = dct['venvs'][opts.cli_pkg]['metadata']['main_package']['app_paths'][0]['__Path__']
124
+
125
+ subprocess.check_call([
126
+ exe,
127
+ '_post_install',
128
+ ])
129
+
130
+
131
+ INSTALL_MANAGERS = {
132
+ 'uvx': UvxInstallManager(),
133
+ 'pipx': PipxInstallManager(),
115
134
  }
116
135
 
117
136
 
@@ -129,22 +148,24 @@ def _main() -> None:
129
148
  if not (cli := args.cli):
130
149
  raise ValueError(f'Must specify cli')
131
150
 
151
+ cli = cli.lower().replace('_', '-')
152
+
132
153
  if not (py := args.py):
133
154
  raise ValueError(f'Must specify py')
134
155
 
135
156
  if mgr := args.mgr:
136
- if (im := INSTALL_MGRS.get(mgr)) is None:
157
+ if (im := INSTALL_MANAGERS.get(mgr)) is None:
137
158
  raise ValueError(f'Unsupported mgr: {mgr}')
138
159
  if not im.is_available():
139
160
  raise ValueError(f'Unavailable mgr: {mgr}')
140
161
  else:
141
- for im in INSTALL_MGRS.values():
162
+ for im in INSTALL_MANAGERS.values():
142
163
  if im.is_available():
143
164
  break
144
165
  else:
145
166
  raise RuntimeError("Can't find install manager")
146
167
 
147
- for m in INSTALL_MGRS.values():
168
+ for m in INSTALL_MANAGERS.values():
148
169
  if m.is_available():
149
170
  m.uninstall(cli)
150
171
 
@@ -23,7 +23,18 @@ from .types import CliModule
23
23
  ##
24
24
 
25
25
 
26
- _CLI_FUNCS: ta.Sequence[CliFunc] = []
26
+ def _post_install() -> None:
27
+ from .managers import setup_install_manager
28
+
29
+ setup_install_manager()
30
+
31
+
32
+ ##
33
+
34
+
35
+ _CLI_FUNCS: ta.Sequence[CliFunc] = [
36
+ CliFunc('_post_install', _post_install),
37
+ ]
27
38
 
28
39
 
29
40
  ##
@@ -0,0 +1,107 @@
1
+ import enum
2
+ import os.path
3
+ import site
4
+ import sys
5
+
6
+
7
+ ##
8
+
9
+
10
+ def _normalize_pkg_name(s: str) -> str:
11
+ return s.lower().replace('_', '-')
12
+
13
+
14
+ CLI_PKG = _normalize_pkg_name(__name__.split('.')[0])
15
+
16
+
17
+ ##
18
+
19
+
20
+ class ManagerType(enum.Enum):
21
+ UVX = 'uvx'
22
+ PIPX = 'pipx'
23
+
24
+
25
+ def _detect_install_manager() -> ManagerType | None:
26
+ if os.path.isfile(fp := os.path.join(sys.prefix, 'uv-receipt.toml')):
27
+ import tomllib
28
+
29
+ with open(fp) as f:
30
+ dct = tomllib.loads(f.read())
31
+
32
+ reqs = dct.get('tool', {}).get('requirements')
33
+ main_pkg = _normalize_pkg_name(reqs[0].get('name', ''))
34
+ if reqs and main_pkg == CLI_PKG:
35
+ return ManagerType.UVX
36
+
37
+ if os.path.isfile(fp := os.path.join(sys.prefix, 'pipx_metadata.json')):
38
+ import json
39
+
40
+ with open(fp) as f:
41
+ dct = json.loads(f.read())
42
+
43
+ main_pkg = _normalize_pkg_name(dct.get('main_package', {}).get('package_or_url', ''))
44
+ if main_pkg == CLI_PKG:
45
+ return ManagerType.PIPX
46
+
47
+ return None
48
+
49
+
50
+ def detect_install_manager() -> ManagerType | None:
51
+ try:
52
+ return globals()['_DETECTED_MANAGER_TYPE']
53
+ except KeyError:
54
+ pass
55
+ ret = globals()['_DETECTED_MANAGER_TYPE'] = _detect_install_manager()
56
+ return ret
57
+
58
+
59
+ ##
60
+ # Python is insistent in prepending sys.path with an empty string (translating to the current working directory),
61
+ # which leads to problems when using the cli in directories containing python packages (such as within this very
62
+ # source tree). This can't be done in cli main as the code frequently spawns other sys.executable processes which
63
+ # wouldn't know to do that, so a .pth file hack is used. Cleaning sys.path solely there is also insufficient as that
64
+ # code runs before the problematic empty string is added, so a sys.meta_path hook is prepended.
65
+ #
66
+ # See:
67
+ # https://github.com/python/cpython/blob/da1e5526aee674bb33c17a498aa3781587b9850c/Python/sysmodule.c#L3939
68
+
69
+
70
+ def _remove_empty_from_sys_path() -> None:
71
+ while '' in sys.path:
72
+ sys.path.remove('')
73
+
74
+
75
+ class _PathHackMetaFinder:
76
+ def find_spec(self, fullname, path, target=None):
77
+ _remove_empty_from_sys_path()
78
+ return None # noqa
79
+
80
+
81
+ def _activate_path_hack() -> None:
82
+ if not any(isinstance(mp, _PathHackMetaFinder) for mp in sys.meta_path):
83
+ sys.meta_path.insert(0, _PathHackMetaFinder())
84
+
85
+
86
+ _PATH_HACK_FILE_NAME = f'{"-".join(__name__.split("."))}-path-hack.pth'
87
+
88
+
89
+ def _install_path_hack_file() -> None:
90
+ sp = site.getsitepackages()[0]
91
+ if os.path.isfile(fp := os.path.join(sp, _PATH_HACK_FILE_NAME)):
92
+ return
93
+
94
+ with open(fp, 'w') as f:
95
+ f.write(f'import {__name__}; {__name__}._activate_path_hack()')
96
+
97
+ _activate_path_hack()
98
+
99
+
100
+ ##
101
+
102
+
103
+ def setup_install_manager() -> None:
104
+ if detect_install_manager() is None:
105
+ return
106
+
107
+ _install_path_hack_file()
@@ -0,0 +1,70 @@
1
+ import os
2
+ import re
3
+ import subprocess
4
+
5
+ from omlish import argparse as ap
6
+ from omlish import logs
7
+
8
+ from ..cli import CliModule
9
+
10
+
11
+ class Cli(ap.Cli):
12
+ @ap.command()
13
+ def blob_sizes(self) -> None:
14
+ # https://stackoverflow.com/a/42544963
15
+ subprocess.check_call( # noqa
16
+ "git rev-list --objects --all | "
17
+ "git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | "
18
+ "sed -n 's/^blob //p' | "
19
+ "sort --numeric-sort --key=2",
20
+ shell=True,
21
+ )
22
+
23
+ #
24
+
25
+ @ap.command()
26
+ def commits_by_date(self) -> None:
27
+ subprocess.check_call(['git log --date=short --pretty=format:%ad | sort | uniq -c'], shell=True) # noqa
28
+
29
+ #
30
+
31
+ _GITHUB_PAT = re.compile(r'((http(s)?://)?(www\./)?github(\.com)?/)?(?P<user>[^/.]+)/(?P<repo>[^/.]+)(/.*)?')
32
+
33
+ @ap.command(
34
+ ap.arg('repo'),
35
+ ap.arg('args', nargs=ap.REMAINDER),
36
+ accepts_unknown=True,
37
+ )
38
+ def clone(self) -> None:
39
+ if not (m := self._GITHUB_PAT.fullmatch(self.args.repo)):
40
+ subprocess.check_call([
41
+ 'git',
42
+ 'clone',
43
+ *self.unknown_args,
44
+ *self.args.args,
45
+ self.args.repo,
46
+ ])
47
+ return
48
+
49
+ user = m.group('user')
50
+ repo = m.group('repo')
51
+
52
+ os.makedirs(user, 0o755, exist_ok=True)
53
+
54
+ subprocess.check_call([
55
+ 'git',
56
+ 'clone',
57
+ *self.unknown_args,
58
+ *self.args.args,
59
+ f'https://github.com/{user}/{repo}.git',
60
+ os.path.join(user, repo),
61
+ ])
62
+
63
+
64
+ # @omlish-manifest
65
+ _CLI_MODULE = CliModule('git', __name__)
66
+
67
+
68
+ if __name__ == '__main__':
69
+ logs.configure_standard_logging('INFO')
70
+ Cli()()
@@ -66,7 +66,7 @@ class Cli(ap.Cli):
66
66
  dist_cn = canonicalize_name(dist.metadata['Name'], validate=True)
67
67
  if dist_cn in dists:
68
68
  # raise NameError(dist_cn)
69
- print(f'!! duplicate dist: {dist_cn}', file=sys.stderr)
69
+ # print(f'!! duplicate dist: {dist_cn}', file=sys.stderr)
70
70
  continue
71
71
 
72
72
  dists.add(dist_cn)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omdev
3
- Version: 0.0.0.dev43
3
+ Version: 0.0.0.dev45
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: ~=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omlish==0.0.0.dev43
15
+ Requires-Dist: omlish==0.0.0.dev45
16
16
  Provides-Extra: all
17
17
  Requires-Dist: pycparser~=2.22; extra == "all"
18
18
  Requires-Dist: cffi~=1.17; extra == "all"
@@ -65,9 +65,10 @@ omdev/cexts/_distutils/compilers/options.py
65
65
  omdev/cexts/_distutils/compilers/unixccompiler.py
66
66
  omdev/cli/__init__.py
67
67
  omdev/cli/__main__.py
68
- omdev/cli/clicmds.py
68
+ omdev/cli/clicli.py
69
69
  omdev/cli/install.py
70
70
  omdev/cli/main.py
71
+ omdev/cli/managers.py
71
72
  omdev/cli/types.py
72
73
  omdev/interp/__init__.py
73
74
  omdev/interp/__main__.py
@@ -1,4 +1,4 @@
1
- omlish==0.0.0.dev43
1
+ omlish==0.0.0.dev45
2
2
 
3
3
  [all]
4
4
  pycparser~=2.22
@@ -12,7 +12,7 @@ authors = [
12
12
  urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = {text = 'BSD-3-Clause'}
14
14
  requires-python = '~=3.12'
15
- version = '0.0.0.dev43'
15
+ version = '0.0.0.dev45'
16
16
  classifiers = [
17
17
  'License :: OSI Approved :: BSD License',
18
18
  'Development Status :: 2 - Pre-Alpha',
@@ -22,7 +22,7 @@ classifiers = [
22
22
  ]
23
23
  description = 'omdev'
24
24
  dependencies = [
25
- 'omlish == 0.0.0.dev43',
25
+ 'omlish == 0.0.0.dev45',
26
26
  ]
27
27
 
28
28
  [project.optional-dependencies]
@@ -1,83 +0,0 @@
1
- import argparse
2
- import inspect
3
- import os
4
- import subprocess
5
- import sys
6
-
7
- from omlish import __about__
8
-
9
- from . import install
10
- from .types import CliModule
11
-
12
-
13
- def _print_version(args) -> None:
14
- print(__about__.__version__)
15
-
16
-
17
- def _print_revision(args) -> None:
18
- print(__about__.__revision__)
19
-
20
-
21
- def _reinstall(args) -> None:
22
- mod_name = globals()['__spec__'].name
23
- tool_name = '.'.join([mod_name.partition('.')[0], 'tools', 'piptools'])
24
-
25
- out = subprocess.check_output([
26
- sys.executable,
27
- '-m',
28
- tool_name,
29
- 'list-root-dists',
30
- ]).decode()
31
-
32
- deps = sorted(
33
- ({s for l in out.splitlines() if (s := l.strip())} | set(args.extra_deps or []))
34
- - {install.DEFAULT_CLI_PKG} # noqa
35
- )
36
-
37
- if deps:
38
- print('Reinstalling with following additional dependencies:')
39
- print('\n'.join(' ' + d for d in deps))
40
- else:
41
- print('No additional dependencies detected.')
42
- print()
43
- print('Continue with reinstall? (ctrl-c to cancel)')
44
- input()
45
-
46
- install_src = inspect.getsource(install)
47
-
48
- os.execl(
49
- sys.executable,
50
- sys.executable,
51
- '-c',
52
- install_src,
53
- *deps,
54
- )
55
-
56
-
57
- # @omlish-manifest
58
- _CLI_MODULE = CliModule('cli', __name__)
59
-
60
-
61
- def _main(argv=None) -> None:
62
- parser = argparse.ArgumentParser()
63
- subparsers = parser.add_subparsers()
64
-
65
- parser_version = subparsers.add_parser('version')
66
- parser_version.set_defaults(func=_print_version)
67
-
68
- parser_revision = subparsers.add_parser('revision')
69
- parser_revision.set_defaults(func=_print_revision)
70
-
71
- parser_reinstall = subparsers.add_parser('reinstall')
72
- parser_reinstall.add_argument('extra_deps', nargs='*')
73
- parser_reinstall.set_defaults(func=_reinstall)
74
-
75
- args = parser.parse_args(argv)
76
- if not getattr(args, 'func', None):
77
- parser.print_help()
78
- else:
79
- args.func(args)
80
-
81
-
82
- if __name__ == '__main__':
83
- _main()
@@ -1,28 +0,0 @@
1
- import subprocess
2
-
3
- from omlish import argparse as ap
4
- from omlish import logs
5
-
6
- from ..cli import CliModule
7
-
8
-
9
- class Cli(ap.Cli):
10
- @ap.command()
11
- def blob_sizes(self) -> None:
12
- # https://stackoverflow.com/a/42544963
13
- subprocess.check_call( # noqa
14
- "git rev-list --objects --all | "
15
- "git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | "
16
- "sed -n 's/^blob //p' | "
17
- "sort --numeric-sort --key=2",
18
- shell=True,
19
- )
20
-
21
-
22
- # @omlish-manifest
23
- _CLI_MODULE = CliModule('git', __name__)
24
-
25
-
26
- if __name__ == '__main__':
27
- logs.configure_standard_logging('INFO')
28
- Cli()()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes