ominfra 0.0.0.dev171__py3-none-any.whl → 0.0.0.dev173__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,11 +7,16 @@ import typing as ta
7
7
  from omlish.lite.cached import cached_nullary
8
8
  from omlish.lite.check import check
9
9
 
10
- from .types import DeployApp
11
- from .types import DeployKey
10
+ from .tags import DeployApp
11
+ from .tags import DeployAppKey
12
+ from .tags import DeployKey
13
+ from .tags import KeyDeployTag # noqa
12
14
  from .types import DeployRev
13
15
 
14
16
 
17
+ KeyDeployTagT = ta.TypeVar('KeyDeployTagT', bound='KeyDeployTag')
18
+
19
+
15
20
  ##
16
21
 
17
22
 
@@ -23,6 +28,16 @@ def check_valid_deploy_spec_path(s: str) -> str:
23
28
  return s
24
29
 
25
30
 
31
+ class DeploySpecKeyed(ta.Generic[KeyDeployTagT]):
32
+ @cached_nullary
33
+ def _key_str(self) -> str:
34
+ return hashlib.sha256(repr(self).encode('utf-8')).hexdigest()[:8]
35
+
36
+ @abc.abstractmethod
37
+ def key(self) -> KeyDeployTagT:
38
+ raise NotImplementedError
39
+
40
+
26
41
  ##
27
42
 
28
43
 
@@ -68,7 +83,7 @@ class DeployVenvSpec:
68
83
 
69
84
 
70
85
  @dc.dataclass(frozen=True)
71
- class DeployConfFile:
86
+ class DeployAppConfFile:
72
87
  path: str
73
88
  body: str
74
89
 
@@ -80,7 +95,7 @@ class DeployConfFile:
80
95
 
81
96
 
82
97
  @dc.dataclass(frozen=True)
83
- class DeployConfLink(abc.ABC): # noqa
98
+ class DeployAppConfLink(abc.ABC): # noqa
84
99
  """
85
100
  May be either:
86
101
  - @conf(.ext)* - links a single file in root of app conf dir to conf/@conf/@dst(.ext)*
@@ -96,11 +111,11 @@ class DeployConfLink(abc.ABC): # noqa
96
111
  check.equal(self.src.count('/'), 1)
97
112
 
98
113
 
99
- class AppDeployConfLink(DeployConfLink):
114
+ class CurrentOnlyDeployAppConfLink(DeployAppConfLink):
100
115
  pass
101
116
 
102
117
 
103
- class TagDeployConfLink(DeployConfLink):
118
+ class AllActiveDeployAppConfLink(DeployAppConfLink):
104
119
  pass
105
120
 
106
121
 
@@ -108,10 +123,10 @@ class TagDeployConfLink(DeployConfLink):
108
123
 
109
124
 
110
125
  @dc.dataclass(frozen=True)
111
- class DeployConfSpec:
112
- files: ta.Optional[ta.Sequence[DeployConfFile]] = None
126
+ class DeployAppConfSpec:
127
+ files: ta.Optional[ta.Sequence[DeployAppConfFile]] = None
113
128
 
114
- links: ta.Optional[ta.Sequence[DeployConfLink]] = None
129
+ links: ta.Optional[ta.Sequence[DeployAppConfLink]] = None
115
130
 
116
131
  def __post_init__(self) -> None:
117
132
  if self.files:
@@ -125,15 +140,34 @@ class DeployConfSpec:
125
140
 
126
141
 
127
142
  @dc.dataclass(frozen=True)
128
- class DeploySpec:
143
+ class DeployAppSpec(DeploySpecKeyed[DeployAppKey]):
129
144
  app: DeployApp
130
145
 
131
146
  git: DeployGitSpec
132
147
 
133
148
  venv: ta.Optional[DeployVenvSpec] = None
134
149
 
135
- conf: ta.Optional[DeployConfSpec] = None
150
+ conf: ta.Optional[DeployAppConfSpec] = None
136
151
 
137
- @cached_nullary
152
+ # @ta.override
153
+ def key(self) -> DeployAppKey:
154
+ return DeployAppKey(self._key_str())
155
+
156
+
157
+ ##
158
+
159
+
160
+ @dc.dataclass(frozen=True)
161
+ class DeploySpec(DeploySpecKeyed[DeployKey]):
162
+ apps: ta.Sequence[DeployAppSpec]
163
+
164
+ def __post_init__(self) -> None:
165
+ seen: ta.Set[DeployApp] = set()
166
+ for a in self.apps:
167
+ if a.app in seen:
168
+ raise KeyError(a.app)
169
+ seen.add(a.app)
170
+
171
+ # @ta.override
138
172
  def key(self) -> DeployKey:
139
- return DeployKey(hashlib.sha256(repr(self).encode('utf-8')).hexdigest()[:8])
173
+ return DeployKey(self._key_str())
@@ -0,0 +1,225 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import abc
3
+ import dataclasses as dc
4
+ import typing as ta
5
+
6
+ from omlish.lite.check import check
7
+
8
+
9
+ ##
10
+
11
+
12
+ DEPLOY_TAG_SIGIL = '@'
13
+
14
+ DEPLOY_TAG_SEPARATOR = '--'
15
+
16
+ DEPLOY_TAG_DELIMITERS: ta.AbstractSet[str] = frozenset([
17
+ DEPLOY_TAG_SEPARATOR,
18
+ '.',
19
+ ])
20
+
21
+ DEPLOY_TAG_ILLEGAL_STRS: ta.AbstractSet[str] = frozenset([
22
+ DEPLOY_TAG_SIGIL,
23
+ *DEPLOY_TAG_DELIMITERS,
24
+ '/',
25
+ ])
26
+
27
+
28
+ ##
29
+
30
+
31
+ @dc.dataclass(frozen=True)
32
+ class DeployTag(abc.ABC): # noqa
33
+ s: str
34
+
35
+ def __post_init__(self) -> None:
36
+ check.not_in(abc.ABC, type(self).__bases__)
37
+ check.non_empty_str(self.s)
38
+ for ch in DEPLOY_TAG_ILLEGAL_STRS:
39
+ check.state(ch not in self.s)
40
+
41
+ #
42
+
43
+ tag_name: ta.ClassVar[str]
44
+ tag_kwarg: ta.ClassVar[str]
45
+
46
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
47
+ super().__init_subclass__(**kwargs)
48
+
49
+ if abc.ABC in cls.__bases__:
50
+ return
51
+
52
+ for b in cls.__bases__:
53
+ if issubclass(b, DeployTag):
54
+ check.in_(abc.ABC, b.__bases__)
55
+
56
+ check.non_empty_str(tn := cls.tag_name)
57
+ check.equal(tn, tn.lower().strip())
58
+ check.not_in('_', tn)
59
+
60
+ check.state(not hasattr(cls, 'tag_kwarg'))
61
+ cls.tag_kwarg = tn.replace('-', '_')
62
+
63
+
64
+ ##
65
+
66
+
67
+ _DEPLOY_TAGS: ta.Set[ta.Type[DeployTag]] = set()
68
+ DEPLOY_TAGS: ta.AbstractSet[ta.Type[DeployTag]] = _DEPLOY_TAGS
69
+
70
+ _DEPLOY_TAGS_BY_NAME: ta.Dict[str, ta.Type[DeployTag]] = {}
71
+ DEPLOY_TAGS_BY_NAME: ta.Mapping[str, ta.Type[DeployTag]] = _DEPLOY_TAGS_BY_NAME
72
+
73
+ _DEPLOY_TAGS_BY_KWARG: ta.Dict[str, ta.Type[DeployTag]] = {}
74
+ DEPLOY_TAGS_BY_KWARG: ta.Mapping[str, ta.Type[DeployTag]] = _DEPLOY_TAGS_BY_KWARG
75
+
76
+
77
+ def _register_deploy_tag(cls):
78
+ check.not_in(cls.tag_name, _DEPLOY_TAGS_BY_NAME)
79
+ check.not_in(cls.tag_kwarg, _DEPLOY_TAGS_BY_KWARG)
80
+
81
+ _DEPLOY_TAGS.add(cls)
82
+ _DEPLOY_TAGS_BY_NAME[cls.tag_name] = cls
83
+ _DEPLOY_TAGS_BY_KWARG[cls.tag_kwarg] = cls
84
+
85
+ return cls
86
+
87
+
88
+ ##
89
+
90
+
91
+ @_register_deploy_tag
92
+ class DeployTime(DeployTag):
93
+ tag_name: ta.ClassVar[str] = 'time'
94
+
95
+
96
+ ##
97
+
98
+
99
+ class NameDeployTag(DeployTag, abc.ABC): # noqa
100
+ pass
101
+
102
+
103
+ @_register_deploy_tag
104
+ class DeployApp(NameDeployTag):
105
+ tag_name: ta.ClassVar[str] = 'app'
106
+
107
+
108
+ @_register_deploy_tag
109
+ class DeployConf(NameDeployTag):
110
+ tag_name: ta.ClassVar[str] = 'conf'
111
+
112
+
113
+ ##
114
+
115
+
116
+ class KeyDeployTag(DeployTag, abc.ABC): # noqa
117
+ pass
118
+
119
+
120
+ @_register_deploy_tag
121
+ class DeployKey(KeyDeployTag):
122
+ tag_name: ta.ClassVar[str] = 'deploy-key'
123
+
124
+
125
+ @_register_deploy_tag
126
+ class DeployAppKey(KeyDeployTag):
127
+ tag_name: ta.ClassVar[str] = 'app-key'
128
+
129
+
130
+ ##
131
+
132
+
133
+ class RevDeployTag(DeployTag, abc.ABC): # noqa
134
+ pass
135
+
136
+
137
+ @_register_deploy_tag
138
+ class DeployAppRev(RevDeployTag):
139
+ tag_name: ta.ClassVar[str] = 'app-rev'
140
+
141
+
142
+ ##
143
+
144
+
145
+ class DeployTagMap:
146
+ def __init__(
147
+ self,
148
+ *args: DeployTag,
149
+ **kwargs: str,
150
+ ) -> None:
151
+ super().__init__()
152
+
153
+ dct: ta.Dict[ta.Type[DeployTag], DeployTag] = {}
154
+
155
+ for a in args:
156
+ c = type(check.isinstance(a, DeployTag))
157
+ check.not_in(c, dct)
158
+ dct[c] = a
159
+
160
+ for k, v in kwargs.items():
161
+ c = DEPLOY_TAGS_BY_KWARG[k]
162
+ check.not_in(c, dct)
163
+ dct[c] = c(v)
164
+
165
+ self._dct = dct
166
+ self._tup = tuple(sorted((type(t).tag_kwarg, t.s) for t in dct.values()))
167
+
168
+ #
169
+
170
+ def add(self, *args: ta.Any, **kwargs: ta.Any) -> 'DeployTagMap':
171
+ return DeployTagMap(
172
+ *self,
173
+ *args,
174
+ **kwargs,
175
+ )
176
+
177
+ def remove(self, *tags_or_names: ta.Union[ta.Type[DeployTag], str]) -> 'DeployTagMap':
178
+ dcs = {
179
+ check.issubclass(a, DeployTag) if isinstance(a, type) else DEPLOY_TAGS_BY_NAME[a]
180
+ for a in tags_or_names
181
+ }
182
+
183
+ return DeployTagMap(*[
184
+ t
185
+ for t in self._dct.values()
186
+ if t not in dcs
187
+ ])
188
+
189
+ #
190
+
191
+ def __repr__(self) -> str:
192
+ return f'{self.__class__.__name__}({", ".join(f"{k}={v!r}" for k, v in self._tup)})'
193
+
194
+ def __hash__(self) -> int:
195
+ return hash(self._tup)
196
+
197
+ def __eq__(self, other: object) -> bool:
198
+ if isinstance(other, DeployTagMap):
199
+ return self._tup == other._tup
200
+ else:
201
+ return NotImplemented
202
+
203
+ #
204
+
205
+ def __len__(self) -> int:
206
+ return len(self._dct)
207
+
208
+ def __iter__(self) -> ta.Iterator[DeployTag]:
209
+ return iter(self._dct.values())
210
+
211
+ def __getitem__(self, key: ta.Union[ta.Type[DeployTag], str]) -> DeployTag:
212
+ if isinstance(key, str):
213
+ return self._dct[DEPLOY_TAGS_BY_NAME[key]]
214
+ elif isinstance(key, type):
215
+ return self._dct[key]
216
+ else:
217
+ raise TypeError(key)
218
+
219
+ def __contains__(self, key: ta.Union[ta.Type[DeployTag], str]) -> bool:
220
+ if isinstance(key, str):
221
+ return DEPLOY_TAGS_BY_NAME[key] in self._dct
222
+ elif isinstance(key, type):
223
+ return key in self._dct
224
+ else:
225
+ raise TypeError(key)
@@ -1,39 +1,9 @@
1
- import dataclasses as dc
2
1
  import typing as ta
3
2
 
4
- from omlish.lite.check import check
5
-
6
-
7
- DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
8
- DeployPathPlaceholder = ta.Literal['app', 'tag', 'conf'] # ta.TypeAlias
9
-
10
3
 
11
4
  ##
12
5
 
13
6
 
14
7
  DeployHome = ta.NewType('DeployHome', str)
15
8
 
16
- DeployApp = ta.NewType('DeployApp', str)
17
- DeployTag = ta.NewType('DeployTag', str)
18
9
  DeployRev = ta.NewType('DeployRev', str)
19
- DeployKey = ta.NewType('DeployKey', str)
20
-
21
-
22
- ##
23
-
24
-
25
- @dc.dataclass(frozen=True)
26
- class DeployAppTag:
27
- app: DeployApp
28
- tag: DeployTag
29
-
30
- def __post_init__(self) -> None:
31
- for s in [self.app, self.tag]:
32
- check.non_empty_str(s)
33
- check.equal(s, s.strip())
34
-
35
- def placeholders(self) -> ta.Mapping[DeployPathPlaceholder, str]:
36
- return {
37
- 'app': self.app,
38
- 'tag': self.tag,
39
- }
@@ -1,15 +1,12 @@
1
1
  bv=""
2
2
  bx=""
3
3
 
4
- for version in "" 3 3.{8..13}; do
5
- x="python$version"
6
- v=$($x -c "import sys; print(sys.version_info[:])" 2>/dev/null)
7
- if [ $? -eq 0 ]; then
8
- cv=$(echo $v | tr -d "(), ")
9
- if [ -z "$bv" ] || [ "$cv" \> "$bv" ]; then
10
- bv=$cv
11
- bx=$x
12
- fi
4
+ for v in "" 3 3.{8..13}; do
5
+ x="python$v"
6
+ v=$($x -c "import sys; print((\"%02d\" * 3) % sys.version_info[:3])" 2>/dev/null)
7
+ if [ $? -eq 0 ] && ([ -z "$bv" ] || [ "$v" \> "$bv" ]); then
8
+ bv=$v
9
+ bx=$x
13
10
  fi
14
11
  done
15
12