ominfra 0.0.0.dev205__py3-none-any.whl → 0.0.0.dev206__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ominfra might be problematic. Click here for more details.

File without changes
@@ -0,0 +1,4 @@
1
+ if __name__ == '__main__':
2
+ from .cli import _main # noqa
3
+
4
+ _main()
@@ -0,0 +1,12 @@
1
+ import gzip
2
+ import typing as ta
3
+
4
+ from omlish import lang
5
+ from omlish.formats import json
6
+
7
+
8
+ @lang.cached_function()
9
+ def load_instance_types() -> ta.Mapping[str, ta.Mapping[str, ta.Any]]:
10
+ raw = lang.get_relative_resources(globals=globals())['cache.json.gz'].read_bytes()
11
+ data = gzip.decompress(raw)
12
+ return json.loads(data)
@@ -0,0 +1,80 @@
1
+ import datetime
2
+ import gzip
3
+ import os.path
4
+ import typing as ta
5
+
6
+ from omdev.secrets import load_secrets
7
+ from omlish import lang
8
+ from omlish import secrets as sec
9
+ from omlish.argparse import all as ap
10
+ from omlish.formats import json
11
+
12
+ from .cache import load_instance_types
13
+
14
+
15
+ if ta.TYPE_CHECKING:
16
+ import boto3
17
+ else:
18
+ boto3 = lang.proxy_import('boto3')
19
+
20
+
21
+ # Use a hardcoded gz mtime to prevent the gz file from changing when the contents don't. We still have the git metadata
22
+ # to track modifications.
23
+ FIXED_CACHE_TIMESTAMP = datetime.datetime(2025, 1, 1, tzinfo=datetime.UTC).timestamp()
24
+
25
+
26
+ @lang.cached_function
27
+ def _get_secrets() -> sec.Secrets:
28
+ return load_secrets()
29
+
30
+
31
+ def get_ec2_instance_types(session: boto3.Session) -> dict[str, dict[str, ta.Any]]:
32
+ ec2 = session.client('ec2')
33
+ next_token = None
34
+ dct = {}
35
+ while True:
36
+ resp = ec2.describe_instance_types(**(dict(NextToken=next_token) if next_token else {}))
37
+ for instance_type in resp['InstanceTypes']:
38
+ name = instance_type['InstanceType']
39
+ dct[name] = instance_type
40
+ next_token = resp.get('NextToken')
41
+ if not next_token:
42
+ break
43
+ dct = dict(sorted(dct.items(), key=lambda t: t[0]))
44
+ return dct
45
+
46
+
47
+ class Cli(ap.Cli):
48
+ @ap.cmd()
49
+ def fetch(self) -> None:
50
+ cfg = _get_secrets()
51
+
52
+ session = boto3.Session(
53
+ aws_access_key_id=cfg.get('aws_access_key_id').reveal(),
54
+ aws_secret_access_key=cfg.get('aws_secret_access_key').reveal(),
55
+ region_name=cfg.get('aws_region').reveal(),
56
+ )
57
+
58
+ instance_types = get_ec2_instance_types(session)
59
+
60
+ cache_file = os.path.join(os.path.dirname(__file__), 'cache.json.gz')
61
+ with open(cache_file, 'wb') as f:
62
+ with gzip.GzipFile(
63
+ fileobj=f,
64
+ mode='w',
65
+ mtime=FIXED_CACHE_TIMESTAMP,
66
+ ) as gf:
67
+ gf.write(json.dumps_compact(instance_types).encode('utf-8'))
68
+
69
+ @ap.cmd()
70
+ def dump(self) -> None:
71
+ dct = load_instance_types()
72
+ print(json.dumps_pretty(dct))
73
+
74
+
75
+ def _main() -> None:
76
+ Cli()()
77
+
78
+
79
+ if __name__ == '__main__':
80
+ _main()
@@ -1,7 +1,9 @@
1
- import dataclasses as dc
2
1
  import typing as ta
3
2
 
3
+ from omlish import cached
4
4
  from omlish import check
5
+ from omlish import collections as col
6
+ from omlish import dataclasses as dc
5
7
  from omlish import lang
6
8
 
7
9
 
@@ -21,17 +23,10 @@ class TagList:
21
23
  ##
22
24
 
23
25
 
24
- class MEMBER_NAME(lang.Marker): # noqa
25
- pass
26
-
27
-
28
26
  class SHAPE_NAME(lang.Marker): # noqa
29
27
  pass
30
28
 
31
29
 
32
- ##
33
-
34
-
35
30
  def common_metadata(
36
31
  *,
37
32
  shape_name: str | None = None,
@@ -55,9 +50,58 @@ def shape_metadata(
55
50
  return md
56
51
 
57
52
 
53
+ class ShapeInfo:
54
+ def __init__(
55
+ self,
56
+ cls: type['Shape'],
57
+ metadata: ta.Mapping[ta.Any, ta.Any],
58
+ ) -> None:
59
+ super().__init__()
60
+
61
+ self._cls = check.issubclass(cls, Shape)
62
+ self._metadata = metadata
63
+
64
+ @property
65
+ def cls(self) -> type['Shape']:
66
+ return self._cls
67
+
68
+ @property
69
+ def metadata(self) -> ta.Mapping[ta.Any, ta.Any]:
70
+ return self._metadata
71
+
72
+ #
73
+
74
+ @cached.function
75
+ def fields(self) -> ta.Sequence[dc.Field]:
76
+ check.state(dc.is_immediate_dataclass(self._cls))
77
+ fls = dc.fields(self._cls)
78
+ return fls # noqa
79
+
80
+ @cached.function
81
+ def fields_by_name(self) -> ta.Mapping[str, dc.Field]:
82
+ return col.make_map_by(lambda fl: fl.name, self.fields(), strict=True)
83
+
84
+ @cached.function
85
+ def fields_by_member_name(self) -> ta.Mapping[str, dc.Field]:
86
+ return col.make_map(
87
+ [(n, f) for f in self.fields() if (n := f.metadata.get(MEMBER_NAME)) is not None],
88
+ strict=True,
89
+ )
90
+
91
+ @cached.function
92
+ def fields_by_serialization_name(self) -> ta.Mapping[str, dc.Field]:
93
+ l = []
94
+ for f in self.fields():
95
+ if sn := f.metadata.get(SERIALIZATION_NAME):
96
+ l.append((sn, f))
97
+ elif mn := f.metadata.get(MEMBER_NAME):
98
+ l.append((mn, f))
99
+ return col.make_map(l, strict=True)
100
+
101
+
58
102
  @dc.dataclass(frozen=True)
59
103
  class Shape:
60
- __shape_metadata__: ta.ClassVar[ta.Mapping[ta.Any, ta.Any]]
104
+ __shape__: ShapeInfo
61
105
 
62
106
  def __init_subclass__(
63
107
  cls,
@@ -67,23 +111,39 @@ class Shape:
67
111
  ) -> None:
68
112
  super().__init_subclass__(**kwargs)
69
113
 
70
- check.state(not hasattr(cls, '__shape_metadata__'))
114
+ check.state(not hasattr(cls, '__shape__'))
71
115
 
72
- cls.__shape_metadata__ = shape_metadata(**kwargs)
116
+ info = ShapeInfo(
117
+ cls,
118
+ shape_metadata(**kwargs),
119
+ )
120
+
121
+ cls.__shape__ = info
73
122
 
74
123
 
75
124
  ##
76
125
 
77
126
 
127
+ class MEMBER_NAME(lang.Marker): # noqa
128
+ pass
129
+
130
+
131
+ class SERIALIZATION_NAME(lang.Marker): # noqa
132
+ pass
133
+
134
+
78
135
  def field_metadata(
79
136
  *,
80
137
  member_name: str | None = None,
138
+ serialization_name: str | None = None,
81
139
  **kwargs: ta.Any,
82
140
  ) -> dict[ta.Any, ta.Any]:
83
141
  md = {**common_metadata(**kwargs)}
84
142
 
85
143
  if member_name is not None:
86
144
  md[MEMBER_NAME] = member_name
145
+ if serialization_name is not None:
146
+ md[SERIALIZATION_NAME] = serialization_name
87
147
 
88
148
  return md
89
149
 
@@ -317,8 +317,10 @@ class ModelGen:
317
317
  fn = self.demangle_name(mn)
318
318
  mds = [
319
319
  f'member_name={mn!r}',
320
- f'shape_name={ms.name!r}',
321
320
  ]
321
+ if msn := ms.serialization.get('name'):
322
+ mds.append(f'serialization_name={msn!r}')
323
+ mds.append(f'shape_name={ms.name!r}')
322
324
  ma = self.get_type_ann(
323
325
  ms.name,
324
326
  unquoted_names=unquoted_names,
@@ -508,3 +510,7 @@ class ModelGen:
508
510
  self.gen_all_operations(out)
509
511
 
510
512
  return out.getvalue()
513
+
514
+
515
+ if __name__ == '__main__':
516
+ raise RuntimeError('Use cli')