omlish 0.0.0.dev70__py3-none-any.whl → 0.0.0.dev72__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.
Files changed (35) hide show
  1. omlish/__about__.py +3 -3
  2. omlish/dataclasses/impl/internals.py +1 -0
  3. omlish/dataclasses/impl/metaclass.py +22 -5
  4. omlish/dataclasses/impl/params.py +4 -2
  5. omlish/diag/_pycharm/runhack.py +9 -4
  6. omlish/formats/json/cli.py +3 -0
  7. omlish/http/__init__.py +17 -0
  8. omlish/http/clients.py +239 -0
  9. omlish/http/consts.py +4 -0
  10. omlish/http/headers.py +181 -0
  11. omlish/sql/queries/__init__.py +79 -0
  12. omlish/sql/queries/base.py +21 -0
  13. omlish/sql/queries/binary.py +48 -0
  14. omlish/sql/queries/exprs.py +54 -0
  15. omlish/sql/queries/idents.py +29 -0
  16. omlish/sql/queries/multi.py +41 -0
  17. omlish/sql/queries/names.py +34 -0
  18. omlish/sql/queries/relations.py +39 -0
  19. omlish/sql/queries/selects.py +50 -0
  20. omlish/sql/queries/std.py +29 -0
  21. omlish/sql/queries/stmts.py +28 -0
  22. omlish/sql/queries/unary.py +29 -0
  23. omlish/sql/tabledefs/__init__.py +11 -0
  24. omlish/sql/tabledefs/alchemy.py +26 -0
  25. omlish/sql/tabledefs/dtypes.py +22 -0
  26. omlish/sql/tabledefs/elements.py +88 -0
  27. omlish/sql/tabledefs/lower.py +49 -0
  28. omlish/sql/tabledefs/marshal.py +19 -0
  29. omlish/sql/tabledefs/tabledefs.py +52 -0
  30. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/METADATA +3 -3
  31. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/RECORD +35 -14
  32. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/LICENSE +0 -0
  33. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/WHEEL +0 -0
  34. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/entry_points.txt +0 -0
  35. {omlish-0.0.0.dev70.dist-info → omlish-0.0.0.dev72.dist-info}/top_level.txt +0 -0
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev70'
2
- __revision__ = '8d6f6c3ead70cde56b9d8040a05d9f91f6dd90ff'
1
+ __version__ = '0.0.0.dev72'
2
+ __revision__ = '4448e03bbb77cb149e46eeefb0e9e61faed2a494'
3
3
 
4
4
 
5
5
  #
@@ -37,7 +37,7 @@ class Project(ProjectBase):
37
37
 
38
38
  'greenlet ~= 3.1',
39
39
 
40
- 'trio ~= 0.26',
40
+ 'trio ~= 0.27',
41
41
  'trio-asyncio ~= 0.15',
42
42
  ],
43
43
 
@@ -17,6 +17,7 @@ POST_INIT_NAME = dc._POST_INIT_NAME # type: ignore # noqa
17
17
 
18
18
  Params = dc._DataclassParams # type: ignore # noqa
19
19
 
20
+
20
21
  """
21
22
  @dc.dataclass(frozen=True)
22
23
  class Params:
@@ -1,6 +1,7 @@
1
1
  """
2
2
  TODO:
3
- - Enum
3
+ - Rewrite lol
4
+ - Enum - enforce Abstract or Final
4
5
  """
5
6
  import abc
6
7
  import collections
@@ -13,6 +14,7 @@ from .api import field # noqa
13
14
  from .params import MetaclassParams
14
15
  from .params import get_metaclass_params
15
16
  from .params import get_params
17
+ from .params import get_params_extras
16
18
 
17
19
 
18
20
  T = ta.TypeVar('T')
@@ -34,22 +36,35 @@ def confer_kwargs(
34
36
  for base in bases:
35
37
  if not dc.is_dataclass(base):
36
38
  continue
39
+
37
40
  if not (bmp := get_metaclass_params(base)).confer:
38
41
  continue
42
+
39
43
  for ck in bmp.confer:
40
44
  if ck in kwargs:
41
45
  continue
46
+
42
47
  if ck in (
43
48
  'frozen',
44
- 'generic_init',
45
49
  'kw_only',
50
+ ):
51
+ confer_kwarg(out, ck, getattr(get_params(base), ck))
52
+
53
+ elif ck in (
54
+ 'cache_hash',
55
+ 'generic_init',
46
56
  'reorder',
47
57
  ):
48
- confer_kwarg(out, ck, get_params(base).frozen)
49
- elif ck == 'confer':
50
- confer_kwarg(out, 'confer', bmp.confer)
58
+ confer_kwarg(out, ck, getattr(get_params_extras(base), ck))
59
+
60
+ elif ck in (
61
+ 'confer',
62
+ ):
63
+ confer_kwarg(out, ck, getattr(bmp, ck))
64
+
51
65
  else:
52
66
  raise KeyError(ck)
67
+
53
68
  return out
54
69
 
55
70
 
@@ -112,6 +127,7 @@ class Frozen(
112
127
  frozen=True,
113
128
  confer=frozenset([
114
129
  'frozen',
130
+ 'cache_hash',
115
131
  'confer',
116
132
  ]),
117
133
  ):
@@ -124,6 +140,7 @@ class Box(
124
140
  generic_init=True,
125
141
  confer=frozenset([
126
142
  'frozen',
143
+ 'cache_hash',
127
144
  'generic_init',
128
145
  'confer',
129
146
  ]),
@@ -1,5 +1,6 @@
1
1
  """
2
- Field:
2
+ @dc.dataclass(frozen=True)
3
+ class Field_:
3
4
  name: str | None = None
4
5
  type: Any = None
5
6
  default: Any | MISSING = MISSING
@@ -14,7 +15,8 @@ Field:
14
15
  _field_type: Any = None
15
16
 
16
17
 
17
- Params:
18
+ @dc.dataclass(frozen=True)
19
+ class Params_:
18
20
  init: bool = True
19
21
  repr: bool = True
20
22
  eq: bool = True
@@ -1038,11 +1038,13 @@ class ExecDecider:
1038
1038
  if not isinstance(tgt, FileTarget):
1039
1039
  return None
1040
1040
 
1041
- new_file = os.path.abspath(tgt.file)
1041
+ abs_file = os.path.abspath(tgt.file)
1042
+ if os.path.commonpath([abs_file, self._root_dir]) != self._root_dir:
1043
+ return None
1042
1044
 
1043
1045
  return ExecDecision(
1044
1046
  tgt.replace(
1045
- file=new_file,
1047
+ file=abs_file,
1046
1048
  ),
1047
1049
  cwd=self._root_dir,
1048
1050
  )
@@ -1070,8 +1072,11 @@ class ExecDecider:
1070
1072
  if not (isinstance(dt, FileTarget) and dt.file.endswith('.py')):
1071
1073
  return None
1072
1074
 
1073
- af = os.path.abspath(dt.file)
1074
- rp = os.path.relpath(af, self._root_dir).split(os.path.sep)
1075
+ abs_file = os.path.abspath(dt.file)
1076
+ if os.path.commonpath([abs_file, self._root_dir]) != self._root_dir:
1077
+ return None
1078
+
1079
+ rp = os.path.relpath(abs_file, self._root_dir).split(os.path.sep)
1075
1080
  mod = '.'.join([*rp[:-1], rp[-1][:-3]])
1076
1081
  new_dt = ModuleTarget(
1077
1082
  mod,
@@ -13,6 +13,7 @@ from .render import JsonRenderer
13
13
 
14
14
 
15
15
  if ta.TYPE_CHECKING:
16
+ import ast
16
17
  import tomllib
17
18
 
18
19
  import yaml
@@ -21,6 +22,7 @@ if ta.TYPE_CHECKING:
21
22
  from .. import props
22
23
 
23
24
  else:
25
+ ast = lang.proxy_import('ast')
24
26
  tomllib = lang.proxy_import('tomllib')
25
27
 
26
28
  yaml = lang.proxy_import('yaml')
@@ -50,6 +52,7 @@ class Formats(enum.Enum):
50
52
  TOML = Format(['toml'], lambda f: tomllib.loads(f.read()))
51
53
  ENV = Format(['env', 'dotenv'], lambda f: dotenv.dotenv_values(stream=f))
52
54
  PROPS = Format(['properties', 'props'], lambda f: dict(props.Properties().load(f.read())))
55
+ PY = Format(['py', 'python', 'repr'], lambda f: ast.literal_eval(f.read()))
53
56
 
54
57
 
55
58
  FORMATS_BY_NAME: ta.Mapping[str, Format] = {
omlish/http/__init__.py CHANGED
@@ -1,5 +1,16 @@
1
1
  from . import consts # noqa
2
2
 
3
+ from .clients import ( # noqa
4
+ HttpClient,
5
+ HttpClientError,
6
+ HttpRequest,
7
+ HttpResponse,
8
+ HttpxHttpClient,
9
+ UrllibHttpClient,
10
+ client,
11
+ request,
12
+ )
13
+
3
14
  from .cookies import ( # noqa
4
15
  CookieTooBigError,
5
16
  dump_cookie,
@@ -16,6 +27,12 @@ from .encodings import ( # noqa
16
27
  latin1_encode,
17
28
  )
18
29
 
30
+ from .headers import ( # noqa
31
+ CanHttpHeaders,
32
+ HttpHeaders,
33
+ headers,
34
+ )
35
+
19
36
  from .json import ( # noqa
20
37
  JSON_TAGGER,
21
38
  JsonTag,
omlish/http/clients.py ADDED
@@ -0,0 +1,239 @@
1
+ """
2
+ TODO:
3
+ - check=False
4
+ - return non-200 HttpResponses
5
+ - async
6
+ - stream
7
+ """
8
+ import abc
9
+ import http.client
10
+ import typing as ta
11
+ import urllib.error
12
+ import urllib.request
13
+
14
+ from .. import cached
15
+ from .. import dataclasses as dc
16
+ from .. import lang
17
+ from .headers import CanHttpHeaders
18
+ from .headers import HttpHeaders
19
+
20
+
21
+ if ta.TYPE_CHECKING:
22
+ import httpx
23
+ else:
24
+ httpx = lang.proxy_import('httpx')
25
+
26
+
27
+ ##
28
+
29
+
30
+ DEFAULT_ENCODING = 'utf-8'
31
+
32
+
33
+ def is_success_status(status: int) -> bool:
34
+ return 200 <= status < 300
35
+
36
+
37
+ ##
38
+
39
+
40
+ @dc.dataclass(frozen=True)
41
+ class HttpRequest(lang.Final):
42
+ url: str
43
+ method: str | None = None # noqa
44
+
45
+ _: dc.KW_ONLY
46
+
47
+ headers: CanHttpHeaders | None = dc.xfield(None, repr=dc.truthy_repr)
48
+ data: bytes | str | None = dc.xfield(None, repr_fn=lambda v: '...' if v is not None else None)
49
+
50
+ timeout_s: float | None = None
51
+
52
+ #
53
+
54
+ @property
55
+ def method_or_default(self) -> str:
56
+ if self.method is not None:
57
+ return self.method
58
+ if self.data is not None:
59
+ return 'POST'
60
+ return 'GET'
61
+
62
+ @cached.property
63
+ def headers_(self) -> HttpHeaders | None:
64
+ return HttpHeaders(self.headers) if self.headers is not None else None
65
+
66
+
67
+ @dc.dataclass(frozen=True, kw_only=True)
68
+ class HttpResponse(lang.Final):
69
+ status: int
70
+
71
+ headers: HttpHeaders | None = dc.xfield(None, repr=dc.truthy_repr)
72
+ data: bytes | None = dc.xfield(None, repr_fn=lambda v: '...' if v is not None else None)
73
+
74
+ request: HttpRequest
75
+ underlying: ta.Any = dc.field(default=None, repr=False)
76
+
77
+ #
78
+
79
+ @property
80
+ def is_success(self) -> bool:
81
+ return is_success_status(self.status)
82
+
83
+
84
+ class HttpClientError(Exception):
85
+ @property
86
+ def cause(self) -> BaseException | None:
87
+ return self.__cause__
88
+
89
+
90
+ @dc.dataclass(frozen=True)
91
+ class HttpStatusError(HttpClientError):
92
+ response: HttpResponse
93
+
94
+
95
+ class HttpClient(lang.Abstract):
96
+ def __enter__(self) -> ta.Self:
97
+ return self
98
+
99
+ def __exit__(self, exc_type, exc_val, exc_tb):
100
+ pass
101
+
102
+ def request(
103
+ self,
104
+ req: HttpRequest,
105
+ *,
106
+ check: bool = False,
107
+ ) -> HttpResponse:
108
+ resp = self._request(req)
109
+
110
+ if check and not resp.is_success:
111
+ if isinstance(resp.underlying, Exception):
112
+ cause = resp.underlying
113
+ else:
114
+ cause = None
115
+ raise HttpStatusError(resp) from cause
116
+
117
+ return resp
118
+
119
+ @abc.abstractmethod
120
+ def _request(self, req: HttpRequest) -> HttpResponse:
121
+ raise NotImplementedError
122
+
123
+
124
+ ##
125
+
126
+
127
+ class UrllibHttpClient(HttpClient):
128
+ def _request(self, req: HttpRequest) -> HttpResponse:
129
+ d: ta.Any
130
+ if (d := req.data) is not None:
131
+ if isinstance(d, str):
132
+ d = d.encode(DEFAULT_ENCODING)
133
+
134
+ # urllib headers are dumb dicts [1], and keys *must* be strings or it will automatically add problematic default
135
+ # headers because it doesn't see string keys in its header dict [2]. frustratingly it has no problem accepting
136
+ # bytes keys though [3].
137
+ # [1]: https://github.com/python/cpython/blob/232b303e4ca47892f544294bf42e31dc34f0ec72/Lib/urllib/request.py#L319-L325 # noqa
138
+ # [2]: https://github.com/python/cpython/blob/232b303e4ca47892f544294bf42e31dc34f0ec72/Lib/urllib/request.py#L1276-L1279 # noqa
139
+ # [3]: https://github.com/python/cpython/blob/232b303e4ca47892f544294bf42e31dc34f0ec72/Lib/http/client.py#L1300-L1301 # noqa
140
+ h: dict[str, str] = {}
141
+ if hs := req.headers_:
142
+ for k, v in hs.strict_dct.items():
143
+ h[k.decode('ascii')] = v.decode('ascii')
144
+
145
+ try:
146
+ with urllib.request.urlopen( # noqa
147
+ urllib.request.Request( # noqa
148
+ req.url,
149
+ method=req.method_or_default,
150
+ headers=h,
151
+ data=d,
152
+ ),
153
+ timeout=req.timeout_s,
154
+ ) as resp:
155
+ return HttpResponse(
156
+ status=resp.status,
157
+ headers=HttpHeaders(resp.headers.items()),
158
+ data=resp.read(),
159
+ request=req,
160
+ underlying=resp,
161
+ )
162
+
163
+ except urllib.error.HTTPError as e:
164
+ return HttpResponse(
165
+ status=e.code,
166
+ headers=HttpHeaders(e.headers.items()),
167
+ data=e.read(),
168
+ request=req,
169
+ underlying=e,
170
+ )
171
+
172
+ except (urllib.error.URLError, http.client.HTTPException) as e:
173
+ raise HttpClientError from e
174
+
175
+
176
+ ##
177
+
178
+
179
+ class HttpxHttpClient(HttpClient):
180
+ def _request(self, req: HttpRequest) -> HttpResponse:
181
+ try:
182
+ response = httpx.request(
183
+ method=req.method_or_default,
184
+ url=req.url,
185
+ headers=req.headers_ or None, # type: ignore
186
+ content=req.data,
187
+ timeout=req.timeout_s,
188
+ )
189
+
190
+ return HttpResponse(
191
+ status=response.status_code,
192
+ headers=HttpHeaders(response.headers.raw),
193
+ data=response.content,
194
+ request=req,
195
+ underlying=response,
196
+ )
197
+
198
+ except httpx.HTTPError as e:
199
+ raise HttpClientError from e
200
+
201
+
202
+ ##
203
+
204
+
205
+ def client() -> HttpClient:
206
+ return UrllibHttpClient()
207
+
208
+
209
+ def request(
210
+ url: str,
211
+ method: str | None = None,
212
+ *,
213
+ headers: CanHttpHeaders | None = None,
214
+ data: bytes | str | None = None,
215
+
216
+ timeout_s: float | None = None,
217
+
218
+ check: bool = False,
219
+
220
+ **kwargs: ta.Any,
221
+ ) -> HttpResponse:
222
+ req = HttpRequest(
223
+ url,
224
+ method=method,
225
+
226
+ headers=headers,
227
+ data=data,
228
+
229
+ timeout_s=timeout_s,
230
+
231
+ **kwargs,
232
+ )
233
+
234
+ with client() as cli:
235
+ return cli.request(
236
+ req,
237
+
238
+ check=check,
239
+ )
omlish/http/consts.py CHANGED
@@ -64,5 +64,9 @@ BEARER_AUTH_HEADER_PREFIX = b'Bearer '
64
64
  BASIC_AUTH_HEADER_PREFIX = b'Basic '
65
65
 
66
66
 
67
+ def format_bearer_auth_header(token: str | bytes) -> bytes:
68
+ return BEARER_AUTH_HEADER_PREFIX + (token.encode('ascii') if isinstance(token, str) else token)
69
+
70
+
67
71
  def format_basic_auth_header(username: str, password: str) -> bytes:
68
72
  return BASIC_AUTH_HEADER_PREFIX + base64.b64encode(':'.join([username, password]).encode())
omlish/http/headers.py ADDED
@@ -0,0 +1,181 @@
1
+ import typing as ta
2
+
3
+ from .. import cached
4
+ from .. import check
5
+ from .. import collections as col
6
+
7
+
8
+ StrOrBytes: ta.TypeAlias = str | bytes
9
+
10
+ CanHttpHeaders: ta.TypeAlias = ta.Union[
11
+ 'HttpHeaders',
12
+
13
+ ta.Mapping[str, str],
14
+ ta.Mapping[str, ta.Sequence[str]],
15
+
16
+ ta.Mapping[bytes, bytes],
17
+ ta.Mapping[bytes, ta.Sequence[bytes]],
18
+
19
+ ta.Mapping[StrOrBytes, StrOrBytes],
20
+ ta.Mapping[StrOrBytes, ta.Sequence[StrOrBytes]],
21
+
22
+ ta.Mapping[StrOrBytes, StrOrBytes | ta.Sequence[StrOrBytes]],
23
+
24
+ ta.Sequence[tuple[str, str]],
25
+ ta.Sequence[tuple[bytes, bytes]],
26
+ ta.Sequence[tuple[StrOrBytes, StrOrBytes]],
27
+ ]
28
+
29
+
30
+ class HttpHeaders:
31
+ def __init__(self, src: CanHttpHeaders) -> None:
32
+ super().__init__()
33
+
34
+ if isinstance(src, HttpHeaders):
35
+ check.is_(src, self)
36
+ return
37
+
38
+ # TODO: optimized storage, 'use-whats-given'
39
+ lst: list[tuple[bytes, bytes]] = []
40
+ if isinstance(src, ta.Mapping):
41
+ for k, v in src.items():
42
+ if isinstance(v, (str, bytes)):
43
+ lst.append((self._as_bytes(k), self._as_bytes(v)))
44
+ else:
45
+ for e in v:
46
+ lst.append((self._as_bytes(k), self._as_bytes(e)))
47
+
48
+ elif isinstance(src, (str, bytes)): # type: ignore
49
+ raise TypeError(src)
50
+
51
+ elif isinstance(src, ta.Sequence):
52
+ for t in src:
53
+ if isinstance(t, (str, bytes)):
54
+ raise TypeError(t)
55
+
56
+ k, v = t
57
+ lst.append((self._as_bytes(k), self._as_bytes(v)))
58
+
59
+ else:
60
+ raise TypeError(src)
61
+
62
+ self._lst = lst
63
+
64
+ def __new__(cls, obj: CanHttpHeaders) -> 'HttpHeaders':
65
+ if isinstance(obj, HttpHeaders):
66
+ return obj
67
+
68
+ return super().__new__(cls)
69
+
70
+ #
71
+
72
+ # https://github.com/pgjones/hypercorn/commit/13f385be7277f407a9a361c958820515e16e217e
73
+ ENCODING: ta.ClassVar[str] = 'latin1'
74
+
75
+ @classmethod
76
+ def _as_bytes(cls, o: StrOrBytes) -> bytes:
77
+ if isinstance(o, bytes):
78
+ return o
79
+ elif isinstance(o, str):
80
+ return o.encode(cls.ENCODING)
81
+ else:
82
+ raise TypeError(o)
83
+
84
+ #
85
+
86
+ @cached.function
87
+ def __repr__(self) -> str:
88
+ return f'{self.__class__.__name__}({{{", ".join(repr(k) for k in self.single_str_dct)}}})'
89
+
90
+ #
91
+
92
+ @property
93
+ def raw(self) -> ta.Sequence[tuple[bytes, bytes]]:
94
+ return self._lst
95
+
96
+ @classmethod
97
+ def _as_key(cls, o: StrOrBytes) -> bytes:
98
+ return cls._as_bytes(o).lower()
99
+
100
+ @cached.property
101
+ def normalized(self) -> ta.Sequence[tuple[bytes, bytes]]:
102
+ return [(self._as_key(k), v) for k, v in self._lst]
103
+
104
+ #
105
+
106
+ @cached.property
107
+ def multi_dct(self) -> ta.Mapping[bytes, ta.Sequence[bytes]]:
108
+ return col.multi_map(self.normalized)
109
+
110
+ @cached.property
111
+ def single_dct(self) -> ta.Mapping[bytes, bytes]:
112
+ return {k: v[0] for k, v in self.multi_dct.items() if len(v) == 1}
113
+
114
+ @cached.property
115
+ def strict_dct(self) -> ta.Mapping[bytes, bytes]:
116
+ return col.make_map(self.normalized, strict=True)
117
+
118
+ #
119
+
120
+ @cached.property
121
+ def strs(self) -> ta.Sequence[tuple[str, str]]:
122
+ return tuple((k.decode(self.ENCODING), v.decode(self.ENCODING)) for k, v in self.normalized)
123
+
124
+ @cached.property
125
+ def multi_str_dct(self) -> ta.Mapping[str, ta.Sequence[str]]:
126
+ return col.multi_map(self.strs)
127
+
128
+ @cached.property
129
+ def single_str_dct(self) -> ta.Mapping[str, str]:
130
+ return {k: v[0] for k, v in self.multi_str_dct.items() if len(v) == 1}
131
+
132
+ @cached.property
133
+ def strict_str_dct(self) -> ta.Mapping[str, str]:
134
+ return col.make_map(self.strs, strict=True)
135
+
136
+ #
137
+
138
+ def __bool__(self) -> bool:
139
+ return bool(self._lst)
140
+
141
+ def __len__(self) -> int:
142
+ return len(self._lst)
143
+
144
+ def __iter__(self) -> ta.Iterator[tuple[bytes, bytes]]:
145
+ return iter(self._lst)
146
+
147
+ @ta.overload
148
+ def __getitem__(self, item: str) -> ta.Sequence[str]:
149
+ ...
150
+
151
+ @ta.overload
152
+ def __getitem__(self, item: bytes) -> ta.Sequence[bytes]:
153
+ ...
154
+
155
+ @ta.overload
156
+ def __getitem__(self, item: int) -> StrOrBytes:
157
+ ...
158
+
159
+ @ta.overload
160
+ def __getitem__(self, item: slice) -> ta.Sequence[StrOrBytes]:
161
+ ...
162
+
163
+ def __getitem__(self, item):
164
+ if isinstance(item, (int, slice)):
165
+ return self._lst[item]
166
+ elif isinstance(item, str):
167
+ return self.multi_str_dct[item.lower()]
168
+ elif isinstance(item, bytes):
169
+ return self.multi_dct[self._as_key(item)]
170
+ else:
171
+ raise TypeError(item)
172
+
173
+ def keys(self) -> ta.Iterable[bytes]:
174
+ return self.multi_dct.keys()
175
+
176
+ def items(self) -> ta.Iterable[tuple[bytes, bytes]]:
177
+ return self._lst
178
+
179
+
180
+ def headers(src: CanHttpHeaders) -> HttpHeaders:
181
+ return HttpHeaders(src)
@@ -0,0 +1,79 @@
1
+ from .base import ( # noqa
2
+ Builder,
3
+ Node,
4
+ Value,
5
+ )
6
+
7
+ from .binary import ( # noqa
8
+ Binary,
9
+ BinaryBuilder,
10
+ BinaryOp,
11
+ BinaryOps,
12
+ )
13
+
14
+ from .exprs import ( # noqa
15
+ CanExpr,
16
+ CanLiteral,
17
+ Expr,
18
+ ExprBuilder,
19
+ Literal,
20
+ NameExpr,
21
+ )
22
+
23
+ from .idents import ( # noqa
24
+ CanIdent,
25
+ Ident,
26
+ IdentBuilder,
27
+ )
28
+
29
+ from .multi import ( # noqa
30
+ Multi,
31
+ MultiBuilder,
32
+ MultiOp,
33
+ MultiOps,
34
+ )
35
+
36
+ from .names import ( # noqa
37
+ CanName,
38
+ Name,
39
+ NameBuilder,
40
+ )
41
+
42
+ from .relations import ( # noqa
43
+ CanRelation,
44
+ CanTable,
45
+ Relation,
46
+ RelationBuilder,
47
+ Table,
48
+ )
49
+
50
+ from .selects import ( # noqa
51
+ CanRelation,
52
+ Select,
53
+ SelectBuilder,
54
+ SelectItem,
55
+ )
56
+
57
+ from .std import ( # noqa
58
+ StdBuilder,
59
+ )
60
+
61
+ from .stmts import ( # noqa
62
+ CanExpr,
63
+ ExprStmt,
64
+ Stmt,
65
+ StmtBuilder,
66
+ )
67
+
68
+ from .unary import ( # noqa
69
+ Unary,
70
+ UnaryBuilder,
71
+ UnaryOp,
72
+ UnaryOps,
73
+ )
74
+
75
+
76
+ ##
77
+
78
+
79
+ Q = StdBuilder()