omdev 0.0.0.dev212__py3-none-any.whl → 0.0.0.dev214__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.
omdev/.manifests.json CHANGED
@@ -267,7 +267,7 @@
267
267
  "module": ".tools.docker",
268
268
  "attr": "_CLI_MODULE",
269
269
  "file": "omdev/tools/docker.py",
270
- "line": 258,
270
+ "line": 264,
271
271
  "value": {
272
272
  "$.cli.types.CliModule": {
273
273
  "cmd_name": "docker",
omdev/cc/cdeps.py CHANGED
@@ -5,6 +5,7 @@ import typing as ta
5
5
  from omlish import cached
6
6
  from omlish import lang
7
7
  from omlish import marshal as msh
8
+ from omlish.configs import all as configs
8
9
 
9
10
 
10
11
  @dc.dataclass(frozen=True)
@@ -20,19 +21,51 @@ class Cdep:
20
21
 
21
22
  #
22
23
 
24
+ sources: ta.Sequence[str] | None = None
23
25
  include: ta.Sequence[str] | None = None
24
26
 
25
27
  #
26
28
 
27
29
  @dc.dataclass(frozen=True)
28
30
  class Cmake:
29
- fetch_content_url: str | None = None
31
+ @dc.dataclass(frozen=True)
32
+ class FetchContent:
33
+ url: str | None = None
34
+
35
+ @dc.dataclass(frozen=True)
36
+ class Git:
37
+ repository: str | None = None
38
+ tag: str | None = None
39
+
40
+ git: Git | None = None
41
+
42
+ fetch_content: FetchContent | None = None
30
43
 
31
44
  cmake: Cmake | None = None
32
45
 
33
46
 
47
+ def process_marshaled_cdep(obj: ta.Any) -> ta.Any:
48
+ obj = configs.processing.matched_rewrite(
49
+ lambda s: s if isinstance(s, str) else ''.join(s),
50
+ obj,
51
+ ('sources', None),
52
+ ('include', None),
53
+ )
54
+
55
+ return obj
56
+
57
+
34
58
  @cached.function
35
59
  def load_cdeps() -> ta.Mapping[str, Cdep]:
36
60
  src = lang.get_relative_resources(globals=globals())['cdeps.toml'].read_text()
37
61
  dct = tomllib.loads(src)
62
+
63
+ dct = {
64
+ **dct,
65
+ 'deps': {
66
+ k: process_marshaled_cdep(v)
67
+ for k, v in dct.get('deps', {}).items()
68
+ },
69
+ }
70
+
38
71
  return msh.unmarshal(dct.get('deps', {}), ta.Mapping[str, Cdep]) # type: ignore
omdev/cc/cdeps.toml CHANGED
@@ -1,3 +1,18 @@
1
+ [deps.httplib]
2
+ include = ['.']
3
+
4
+ [deps.httplib.git]
5
+ url = 'https://github.com/yhirose/cpp-httplib'
6
+ rev = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
7
+ subtrees = ['httplib.h']
8
+
9
+ [deps.httplib.cmake.fetch_content.git]
10
+ repository = 'https://github.com/yhirose/cpp-httplib.git'
11
+ tag = 'a7bc00e3307fecdb4d67545e93be7b88cfb1e186'
12
+
13
+
14
+ #
15
+
1
16
  [deps.json]
2
17
  include = ['single_include']
3
18
 
@@ -6,8 +21,9 @@ url = 'https://github.com/nlohmann/json'
6
21
  rev = '9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03'
7
22
  subtrees = ['single_include']
8
23
 
9
- [deps.json.cmake]
10
- fetch_content_url = 'https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz'
24
+ [deps.json.cmake.fetch_content]
25
+ url = 'https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz'
26
+
11
27
 
12
28
  #
13
29
 
@@ -19,6 +35,7 @@ url = 'https://github.com/pybind/pybind11'
19
35
  rev = '945e251a6ce7273058b36214d94415e9c9530b8e'
20
36
  subtrees = ['include']
21
37
 
38
+
22
39
  #
23
40
 
24
41
  [deps.ut]
omdev/cc/cli.py CHANGED
@@ -18,6 +18,8 @@ Freestanding options:
18
18
  TODO:
19
19
  - cext interop
20
20
  - gen cmake
21
+ - fix CFLAGS/CCFLAGS/CPPFLAGS/CXXFLAGS
22
+ - jit-gen cmake mode? multi-src builds
21
23
  """
22
24
  import os
23
25
  import shlex
@@ -35,6 +37,7 @@ from .. import magic
35
37
  from ..cache import data as dcache
36
38
  from .cdeps import Cdep
37
39
  from .cdeps import load_cdeps
40
+ from .cdeps import process_marshaled_cdep
38
41
 
39
42
 
40
43
  class Cli(ap.Cli):
@@ -64,16 +67,22 @@ class Cli(ap.Cli):
64
67
  if src_magic.key == '@omlish-cdeps':
65
68
  for dep in check.isinstance(src_magic.prepared, ta.Sequence):
66
69
  if isinstance(dep, ta.Mapping):
67
- dep = msh.unmarshal(dep, Cdep) # type: ignore
70
+ dep = process_marshaled_cdep(dep)
71
+ dep = msh.unmarshal(dep, Cdep)
68
72
  else:
69
73
  dep = load_cdeps()[check.isinstance(dep, str)]
70
74
 
75
+ if dep.sources:
76
+ # TODO
77
+ raise NotImplementedError
78
+
71
79
  dep_spec = dcache.GitSpec(
72
80
  url=dep.git.url,
73
81
  rev=dep.git.rev,
74
82
  subtrees=dep.git.subtrees,
75
83
  )
76
84
  dep_dir = dcache.default().get(dep_spec)
85
+
77
86
  for dep_inc in dep.include or []:
78
87
  inc_dir = os.path.join(dep_dir, dep_inc)
79
88
  check.state(os.path.isdir(inc_dir))
@@ -96,6 +105,9 @@ class Cli(ap.Cli):
96
105
  if cflags := os.environ.get('CFLAGS'):
97
106
  sh_parts.append(cflags) # Explicitly shell-unquoted
98
107
 
108
+ if ldflags := os.environ.get('LDFLAGS'):
109
+ sh_parts.append(ldflags) # Explicitly shell-unquoted
110
+
99
111
  sh_parts.extend([
100
112
  '-std=c++20',
101
113
  shlex.quote(os.path.abspath(src_file)),
omdev/ci/__init__.py CHANGED
@@ -0,0 +1 @@
1
+ # @omlish-lite
omdev/ci/cache.py CHANGED
@@ -1,12 +1,14 @@
1
1
  # ruff: noqa: UP006 UP007
2
- # @omlish-lite
3
2
  import abc
4
3
  import os.path
5
- import shlex
6
4
  import shutil
7
5
  import typing as ta
8
6
 
9
- from .shell import ShellCmd
7
+ from omlish.lite.cached import cached_nullary
8
+ from omlish.lite.check import check
9
+ from omlish.lite.logs import log
10
+
11
+ from .consts import CI_CACHE_VERSION
10
12
 
11
13
 
12
14
  ##
@@ -14,12 +16,35 @@ from .shell import ShellCmd
14
16
 
15
17
  @abc.abstractmethod
16
18
  class FileCache(abc.ABC):
19
+ def __init__(
20
+ self,
21
+ *,
22
+ version: int = CI_CACHE_VERSION,
23
+ ) -> None:
24
+ super().__init__()
25
+
26
+ check.isinstance(version, int)
27
+ check.arg(version >= 0)
28
+ self._version = version
29
+
30
+ @property
31
+ def version(self) -> int:
32
+ return self._version
33
+
34
+ #
35
+
17
36
  @abc.abstractmethod
18
- def get_file(self, key: str) -> ta.Optional[str]:
37
+ def get_file(self, key: str) -> ta.Awaitable[ta.Optional[str]]:
19
38
  raise NotImplementedError
20
39
 
21
40
  @abc.abstractmethod
22
- def put_file(self, key: str, file_path: str) -> ta.Optional[str]:
41
+ def put_file(
42
+ self,
43
+ key: str,
44
+ file_path: str,
45
+ *,
46
+ steal: bool = False,
47
+ ) -> ta.Awaitable[str]:
23
48
  raise NotImplementedError
24
49
 
25
50
 
@@ -27,142 +52,96 @@ class FileCache(abc.ABC):
27
52
 
28
53
 
29
54
  class DirectoryFileCache(FileCache):
30
- def __init__(self, dir: str) -> None: # noqa
31
- super().__init__()
32
-
33
- self._dir = dir
34
-
35
- #
36
-
37
- def get_cache_file_path(
55
+ def __init__(
38
56
  self,
39
- key: str,
57
+ dir: str, # noqa
40
58
  *,
41
- make_dirs: bool = False,
42
- ) -> str:
43
- if make_dirs:
44
- os.makedirs(self._dir, exist_ok=True)
45
- return os.path.join(self._dir, key)
59
+ no_create: bool = False,
60
+ no_purge: bool = False,
61
+ **kwargs: ta.Any,
62
+ ) -> None: # noqa
63
+ super().__init__(**kwargs)
46
64
 
47
- def format_incomplete_file(self, f: str) -> str:
48
- return os.path.join(os.path.dirname(f), f'_{os.path.basename(f)}.incomplete')
65
+ self._dir = dir
66
+ self._no_create = no_create
67
+ self._no_purge = no_purge
49
68
 
50
69
  #
51
70
 
52
- def get_file(self, key: str) -> ta.Optional[str]:
53
- cache_file_path = self.get_cache_file_path(key)
54
- if not os.path.exists(cache_file_path):
55
- return None
56
- return cache_file_path
57
-
58
- def put_file(self, key: str, file_path: str) -> None:
59
- cache_file_path = self.get_cache_file_path(key, make_dirs=True)
60
- shutil.copyfile(file_path, cache_file_path)
61
-
62
-
63
- ##
64
-
65
-
66
- class ShellCache(abc.ABC):
67
- @abc.abstractmethod
68
- def get_file_cmd(self, key: str) -> ta.Optional[ShellCmd]:
69
- raise NotImplementedError
70
-
71
- class PutFileCmdContext(abc.ABC):
72
- def __init__(self) -> None:
73
- super().__init__()
74
-
75
- self._state: ta.Literal['open', 'committed', 'aborted'] = 'open'
76
-
77
- @property
78
- def state(self) -> ta.Literal['open', 'committed', 'aborted']:
79
- return self._state
71
+ VERSION_FILE_NAME = '.ci-cache-version'
80
72
 
81
- #
73
+ @cached_nullary
74
+ def setup_dir(self) -> None:
75
+ version_file = os.path.join(self._dir, self.VERSION_FILE_NAME)
82
76
 
83
- @property
84
- @abc.abstractmethod
85
- def cmd(self) -> ShellCmd:
86
- raise NotImplementedError
77
+ if self._no_create:
78
+ check.state(os.path.isdir(self._dir))
87
79
 
88
- #
80
+ elif not os.path.isdir(self._dir):
81
+ os.makedirs(self._dir)
82
+ with open(version_file, 'w') as f:
83
+ f.write(str(self._version))
84
+ return
89
85
 
90
- def __enter__(self):
91
- return self
86
+ with open(version_file) as f:
87
+ dir_version = int(f.read().strip())
92
88
 
93
- def __exit__(self, exc_type, exc_val, exc_tb):
94
- if exc_val is None:
95
- self.commit()
96
- else:
97
- self.abort()
89
+ if dir_version == self._version:
90
+ return
98
91
 
99
- #
92
+ if self._no_purge:
93
+ raise RuntimeError(f'{dir_version=} != {self._version=}')
100
94
 
101
- @abc.abstractmethod
102
- def _commit(self) -> None:
103
- raise NotImplementedError
95
+ dirs = [n for n in sorted(os.listdir(self._dir)) if os.path.isdir(os.path.join(self._dir, n))]
96
+ if dirs:
97
+ raise RuntimeError(
98
+ f'Refusing to remove stale cache dir {self._dir!r} '
99
+ f'due to present directories: {", ".join(dirs)}',
100
+ )
104
101
 
105
- def commit(self) -> None:
106
- if self._state == 'committed':
107
- return
108
- elif self._state == 'open':
109
- self._commit()
110
- self._state = 'committed'
111
- else:
112
- raise RuntimeError(self._state)
102
+ for n in sorted(os.listdir(self._dir)):
103
+ if n.startswith('.'):
104
+ continue
105
+ fp = os.path.join(self._dir, n)
106
+ check.state(os.path.isfile(fp))
107
+ log.debug('Purging stale cache file: %s', fp)
108
+ os.unlink(fp)
113
109
 
114
- #
115
-
116
- @abc.abstractmethod
117
- def _abort(self) -> None:
118
- raise NotImplementedError
119
-
120
- def abort(self) -> None:
121
- if self._state == 'aborted':
122
- return
123
- elif self._state == 'open':
124
- self._abort()
125
- self._state = 'committed'
126
- else:
127
- raise RuntimeError(self._state)
128
-
129
- @abc.abstractmethod
130
- def put_file_cmd(self, key: str) -> PutFileCmdContext:
131
- raise NotImplementedError
110
+ os.unlink(version_file)
132
111
 
112
+ with open(version_file, 'w') as f:
113
+ f.write(str(self._version))
133
114
 
134
- #
115
+ #
135
116
 
117
+ def get_cache_file_path(
118
+ self,
119
+ key: str,
120
+ ) -> str:
121
+ self.setup_dir()
122
+ return os.path.join(self._dir, key)
136
123
 
137
- class DirectoryShellCache(ShellCache):
138
- def __init__(self, dfc: DirectoryFileCache) -> None:
139
- super().__init__()
124
+ def format_incomplete_file(self, f: str) -> str:
125
+ return os.path.join(os.path.dirname(f), f'_{os.path.basename(f)}.incomplete')
140
126
 
141
- self._dfc = dfc
127
+ #
142
128
 
143
- def get_file_cmd(self, key: str) -> ta.Optional[ShellCmd]:
144
- f = self._dfc.get_file(key)
145
- if f is None:
129
+ async def get_file(self, key: str) -> ta.Optional[str]:
130
+ cache_file_path = self.get_cache_file_path(key)
131
+ if not os.path.exists(cache_file_path):
146
132
  return None
147
- return ShellCmd(f'cat {shlex.quote(f)}')
148
-
149
- class _PutFileCmdContext(ShellCache.PutFileCmdContext): # noqa
150
- def __init__(self, tf: str, f: str) -> None:
151
- super().__init__()
152
-
153
- self._tf = tf
154
- self._f = f
155
-
156
- @property
157
- def cmd(self) -> ShellCmd:
158
- return ShellCmd(f'cat > {shlex.quote(self._tf)}')
159
-
160
- def _commit(self) -> None:
161
- os.replace(self._tf, self._f)
162
-
163
- def _abort(self) -> None:
164
- os.unlink(self._tf)
133
+ return cache_file_path
165
134
 
166
- def put_file_cmd(self, key: str) -> ShellCache.PutFileCmdContext:
167
- f = self._dfc.get_cache_file_path(key, make_dirs=True)
168
- return self._PutFileCmdContext(self._dfc.format_incomplete_file(f), f)
135
+ async def put_file(
136
+ self,
137
+ key: str,
138
+ file_path: str,
139
+ *,
140
+ steal: bool = False,
141
+ ) -> str:
142
+ cache_file_path = self.get_cache_file_path(key)
143
+ if steal:
144
+ shutil.move(file_path, cache_file_path)
145
+ else:
146
+ shutil.copyfile(file_path, cache_file_path)
147
+ return cache_file_path