omlish 0.0.0.dev70__py3-none-any.whl → 0.0.0.dev72__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,21 @@
1
+ import typing as ta
2
+
3
+ from ... import dataclasses as dc
4
+ from ... import lang
5
+
6
+
7
+ ##
8
+
9
+
10
+ Value: ta.TypeAlias = ta.Any
11
+
12
+
13
+ ##
14
+
15
+
16
+ class Node(dc.Frozen, lang.Abstract, cache_hash=True):
17
+ pass
18
+
19
+
20
+ class Builder(lang.Abstract):
21
+ pass
@@ -0,0 +1,48 @@
1
+ from ... import check
2
+ from ... import lang
3
+ from .base import Node
4
+ from .exprs import CanExpr
5
+ from .exprs import Expr
6
+ from .exprs import ExprBuilder
7
+
8
+
9
+ ##
10
+
11
+
12
+ class BinaryOp(Node, lang.Final):
13
+ name: str
14
+
15
+
16
+ class BinaryOps(lang.Namespace):
17
+ ADD = BinaryOp('add')
18
+ SUB = BinaryOp('sub')
19
+
20
+ EQ = BinaryOp('eq')
21
+ NE = BinaryOp('ne')
22
+
23
+
24
+ class Binary(Expr, lang.Final):
25
+ op: BinaryOp
26
+ l: Expr
27
+ r: Expr
28
+
29
+
30
+ class BinaryBuilder(ExprBuilder):
31
+ def binary(self, op: BinaryOp, *es: CanExpr) -> Expr:
32
+ check.not_empty(es)
33
+ l = self.expr(es[0])
34
+ for r in es[1:]:
35
+ l = Binary(op, l, self.expr(r))
36
+ return l
37
+
38
+ def add(self, *es: CanExpr) -> Expr:
39
+ return self.binary(BinaryOps.ADD, *es)
40
+
41
+ def sub(self, *es: CanExpr) -> Expr:
42
+ return self.binary(BinaryOps.SUB, *es)
43
+
44
+ def eq(self, *es: CanExpr) -> Expr:
45
+ return self.binary(BinaryOps.EQ, *es)
46
+
47
+ def ne(self, *es: CanExpr) -> Expr:
48
+ return self.binary(BinaryOps.NE, *es)
@@ -0,0 +1,54 @@
1
+ import typing as ta
2
+
3
+ from ... import lang
4
+ from .base import Node
5
+ from .base import Value
6
+ from .idents import Ident
7
+ from .names import CanName
8
+ from .names import Name
9
+ from .names import NameBuilder
10
+
11
+
12
+ ##
13
+
14
+
15
+ class Expr(Node, lang.Abstract):
16
+ pass
17
+
18
+
19
+ class Literal(Expr, lang.Final):
20
+ v: Value
21
+
22
+
23
+ class NameExpr(Expr, lang.Final):
24
+ n: Name
25
+
26
+
27
+ CanLiteral: ta.TypeAlias = Literal | Value
28
+ CanExpr: ta.TypeAlias = Expr | CanName | CanLiteral
29
+
30
+
31
+ class ExprBuilder(NameBuilder):
32
+ def literal(self, o: CanLiteral) -> Literal:
33
+ if isinstance(o, Literal):
34
+ return o
35
+ elif isinstance(o, Node):
36
+ raise TypeError(o)
37
+ else:
38
+ return Literal(o)
39
+
40
+ @ta.final
41
+ def l(self, o: CanLiteral) -> Literal: # noqa
42
+ return self.literal(o)
43
+
44
+ def expr(self, o: CanExpr) -> Expr:
45
+ if isinstance(o, Expr):
46
+ return o
47
+ elif isinstance(o, (Name, Ident)):
48
+ return NameExpr(self.name(o))
49
+ else:
50
+ return self.literal(o)
51
+
52
+ @ta.final
53
+ def e(self, o: CanExpr) -> Expr:
54
+ return self.expr(o)
@@ -0,0 +1,29 @@
1
+ import typing as ta
2
+
3
+ from ... import lang
4
+ from .base import Builder
5
+ from .base import Node
6
+
7
+
8
+ ##
9
+
10
+
11
+ class Ident(Node, lang.Final):
12
+ s: str
13
+
14
+
15
+ CanIdent: ta.TypeAlias = Ident | str
16
+
17
+
18
+ class IdentBuilder(Builder):
19
+ def ident(self, o: CanIdent) -> Ident:
20
+ if isinstance(o, Ident):
21
+ return o
22
+ elif isinstance(o, str):
23
+ return Ident(o)
24
+ else:
25
+ raise TypeError(o)
26
+
27
+ @ta.final
28
+ def i(self, o: CanIdent) -> Ident:
29
+ return self.ident(o)
@@ -0,0 +1,41 @@
1
+ import typing as ta
2
+
3
+ from ... import check
4
+ from ... import dataclasses as dc
5
+ from ... import lang
6
+ from .base import Node
7
+ from .exprs import CanExpr
8
+ from .exprs import Expr
9
+ from .exprs import ExprBuilder
10
+
11
+
12
+ ##
13
+
14
+
15
+ class MultiOp(Node, lang.Final):
16
+ name: str
17
+
18
+
19
+ class MultiOps(lang.Namespace):
20
+ AND = MultiOp('and')
21
+ OR = MultiOp('or')
22
+
23
+
24
+ class Multi(Expr, lang.Final):
25
+ op: MultiOp
26
+ es: ta.Sequence[Expr] = dc.xfield(coerce=tuple)
27
+
28
+
29
+ class MultiBuilder(ExprBuilder):
30
+ def multi(self, op: MultiOp, *es: CanExpr) -> Expr:
31
+ check.not_empty(es)
32
+ if len(es) == 1:
33
+ return self.expr(es[0])
34
+ else:
35
+ return Multi(op, [self.expr(e) for e in es])
36
+
37
+ def and_(self, *es: CanExpr) -> Expr:
38
+ return self.multi(MultiOps.AND, *es)
39
+
40
+ def or_(self, *es: CanExpr) -> Expr:
41
+ return self.multi(MultiOps.OR, *es)
@@ -0,0 +1,34 @@
1
+ import typing as ta
2
+
3
+ from ... import dataclasses as dc
4
+ from ... import lang
5
+ from .base import Node
6
+ from .idents import CanIdent
7
+ from .idents import Ident
8
+ from .idents import IdentBuilder
9
+
10
+
11
+ ##
12
+
13
+
14
+ class Name(Node, lang.Final):
15
+ ps: ta.Sequence[Ident] = dc.xfield(coerce=tuple)
16
+
17
+
18
+ CanName: ta.TypeAlias = Name | CanIdent | ta.Sequence[CanIdent]
19
+
20
+
21
+ class NameBuilder(IdentBuilder):
22
+ def name(self, o: CanName) -> Name:
23
+ if isinstance(o, Name):
24
+ return o
25
+ elif isinstance(o, (Ident, str)):
26
+ return Name([self.ident(o)])
27
+ elif isinstance(o, ta.Sequence):
28
+ return Name([self.ident(p) for p in o])
29
+ else:
30
+ raise TypeError(o)
31
+
32
+ @ta.final
33
+ def n(self, o: CanName) -> Name:
34
+ return self.name(o)
@@ -0,0 +1,39 @@
1
+ import typing as ta
2
+
3
+ from ... import dataclasses as dc
4
+ from ... import lang
5
+ from .base import Node
6
+ from .idents import Ident
7
+ from .names import CanName
8
+ from .names import Name
9
+ from .names import NameBuilder
10
+
11
+
12
+ ##
13
+
14
+
15
+ class Relation(Node, lang.Abstract):
16
+ pass
17
+
18
+
19
+ class Table(Relation, lang.Final):
20
+ n: Name
21
+ a: Ident | None = dc.xfield(None, repr_fn=dc.opt_repr)
22
+
23
+
24
+ CanTable: ta.TypeAlias = Table | CanName
25
+ CanRelation: ta.TypeAlias = Relation | CanTable
26
+
27
+
28
+ class RelationBuilder(NameBuilder):
29
+ def table(self, n: CanTable) -> Table:
30
+ if isinstance(n, Table):
31
+ return n
32
+ else:
33
+ return Table(self.name(n))
34
+
35
+ def relation(self, o: CanRelation) -> Relation:
36
+ if isinstance(o, Relation):
37
+ return o
38
+ else:
39
+ return self.table(o)
@@ -0,0 +1,50 @@
1
+ import typing as ta
2
+
3
+ from ... import dataclasses as dc
4
+ from ... import lang
5
+ from .base import Node
6
+ from .exprs import CanExpr
7
+ from .exprs import Expr
8
+ from .exprs import ExprBuilder
9
+ from .idents import Ident
10
+ from .relations import CanRelation
11
+ from .relations import Relation
12
+ from .relations import RelationBuilder
13
+ from .stmts import Stmt
14
+
15
+
16
+ ##
17
+
18
+
19
+ class SelectItem(Node, lang.Final):
20
+ v: Expr
21
+ a: Ident | None = dc.xfield(None, repr_fn=dc.opt_repr)
22
+
23
+
24
+ class Select(Stmt, lang.Final):
25
+ its: ta.Sequence[SelectItem] = dc.xfield(coerce=tuple)
26
+ fr: Relation | None = dc.xfield(None, repr_fn=dc.opt_repr)
27
+ wh: Expr | None = dc.xfield(None, repr_fn=dc.opt_repr)
28
+
29
+
30
+ CanSelectItem: ta.TypeAlias = SelectItem | CanExpr
31
+
32
+
33
+ class SelectBuilder(ExprBuilder, RelationBuilder):
34
+ def select_item(self, o: CanSelectItem) -> SelectItem:
35
+ if isinstance(o, SelectItem):
36
+ return o
37
+ else:
38
+ return SelectItem(self.expr(o))
39
+
40
+ def select(
41
+ self,
42
+ its: ta.Sequence[CanSelectItem],
43
+ fr: CanRelation | None = None,
44
+ wh: CanExpr | None = None,
45
+ ) -> Select:
46
+ return Select(
47
+ [self.select_item(i) for i in its],
48
+ fr=self.relation(fr) if fr is not None else None,
49
+ wh=self.expr(wh) if wh is not None else None,
50
+ )
@@ -0,0 +1,29 @@
1
+ from .base import Builder
2
+ from .binary import BinaryBuilder
3
+ from .exprs import ExprBuilder
4
+ from .idents import IdentBuilder
5
+ from .multi import MultiBuilder
6
+ from .names import NameBuilder
7
+ from .relations import RelationBuilder
8
+ from .selects import SelectBuilder
9
+ from .stmts import StmtBuilder
10
+ from .unary import UnaryBuilder
11
+
12
+
13
+ class StdBuilder(
14
+ SelectBuilder,
15
+ StmtBuilder,
16
+
17
+ MultiBuilder,
18
+ BinaryBuilder,
19
+ UnaryBuilder,
20
+ ExprBuilder,
21
+
22
+ RelationBuilder,
23
+
24
+ NameBuilder,
25
+ IdentBuilder,
26
+
27
+ Builder,
28
+ ):
29
+ pass
@@ -0,0 +1,28 @@
1
+ import typing as ta
2
+
3
+ from ... import lang
4
+ from .base import Node
5
+ from .exprs import CanExpr
6
+ from .exprs import ExprBuilder
7
+
8
+
9
+ ##
10
+
11
+
12
+ class Stmt(Node, lang.Abstract):
13
+ pass
14
+
15
+
16
+ class ExprStmt(Stmt, lang.Final):
17
+ pass
18
+
19
+
20
+ CanStmt: ta.TypeAlias = Stmt | CanExpr
21
+
22
+
23
+ class StmtBuilder(ExprBuilder):
24
+ def stmt(self, o: CanStmt) -> Stmt:
25
+ if isinstance(o, Stmt):
26
+ return o
27
+ else:
28
+ return ExprStmt(self.expr(o))
@@ -0,0 +1,29 @@
1
+ from ... import lang
2
+ from .base import Node
3
+ from .exprs import CanExpr
4
+ from .exprs import Expr
5
+ from .exprs import ExprBuilder
6
+
7
+
8
+ ##
9
+
10
+
11
+ class UnaryOp(Node, lang.Final):
12
+ name: str
13
+
14
+
15
+ class UnaryOps(lang.Namespace):
16
+ NOT = UnaryOp('not')
17
+
18
+
19
+ class Unary(Expr, lang.Final):
20
+ op: UnaryOp
21
+ v: Expr
22
+
23
+
24
+ class UnaryBuilder(ExprBuilder):
25
+ def unary(self, op: UnaryOp, v: CanExpr) -> Unary:
26
+ return Unary(op, self.expr(v))
27
+
28
+ def not_(self, v: CanExpr) -> Unary:
29
+ return self.unary(UnaryOps.NOT, v)
@@ -0,0 +1,11 @@
1
+ from .tabledefs import ( # noqa
2
+ TableDef,
3
+ )
4
+
5
+
6
+ ##
7
+
8
+
9
+ from ...lang.imports import _register_conditional_import # noqa
10
+
11
+ _register_conditional_import('...marshal', '.marshal', __package__)
@@ -0,0 +1,26 @@
1
+ """
2
+ TODO:
3
+ - move to sql/alchemy/tabledefs.py
4
+ """
5
+ import typing as ta
6
+
7
+ import sqlalchemy as sa
8
+ import sqlalchemy.sql.schema
9
+
10
+ from .tabledefs import TableDef
11
+
12
+
13
+ def build_sa_table(
14
+ td: TableDef,
15
+ *,
16
+ metadata: sa.MetaData | None = None,
17
+ **kwargs: ta.Any,
18
+ ) -> sa.Table:
19
+ items: list[sa.sql.schema.SchemaItem] = []
20
+
21
+ return sa.Table(
22
+ td.name,
23
+ metadata if metadata is not None else sa.MetaData(),
24
+ *items,
25
+ **kwargs,
26
+ )
@@ -0,0 +1,22 @@
1
+ from ... import dataclasses as dc
2
+ from ... import lang
3
+
4
+
5
+ @dc.dataclass(frozen=True)
6
+ class Dtype(lang.Abstract, lang.Sealed):
7
+ pass
8
+
9
+
10
+ @dc.dataclass(frozen=True)
11
+ class Integer(Dtype, lang.Singleton):
12
+ pass
13
+
14
+
15
+ @dc.dataclass(frozen=True)
16
+ class String(Dtype, lang.Singleton):
17
+ pass
18
+
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class Datetime(Dtype, lang.Singleton):
22
+ pass
@@ -0,0 +1,88 @@
1
+ import typing as ta
2
+
3
+ from ... import check
4
+ from ... import collections as col
5
+ from ... import dataclasses as dc
6
+ from ... import lang
7
+ from .dtypes import Dtype
8
+
9
+
10
+ ##
11
+
12
+
13
+ class Element(lang.Abstract, lang.Sealed):
14
+ pass
15
+
16
+
17
+ ##
18
+
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class Column(Element, lang.Final):
22
+ name: str
23
+ type: Dtype
24
+ nullable: bool = dc.field(default=False, kw_only=True)
25
+ default: lang.Maybe[ta.Any] = dc.field(default=lang.empty(), kw_only=True)
26
+
27
+
28
+ @dc.dataclass(frozen=True)
29
+ class PrimaryKey(Element, lang.Final):
30
+ columns: ta.Sequence[str]
31
+
32
+
33
+ @dc.dataclass(frozen=True)
34
+ class Index(Element, lang.Final):
35
+ columns: ta.Sequence[str] = dc.xfield(coerce=col.seq)
36
+ name: str | None = None
37
+
38
+
39
+ ##
40
+
41
+
42
+ @dc.dataclass(frozen=True)
43
+ class IdIntegerPrimaryKey(Element, lang.Final):
44
+ pass
45
+
46
+
47
+ #
48
+
49
+
50
+ @dc.dataclass(frozen=True)
51
+ class CreatedAt(Element, lang.Final):
52
+ pass
53
+
54
+
55
+ @dc.dataclass(frozen=True)
56
+ class UpdatedAt(Element, lang.Final):
57
+ pass
58
+
59
+
60
+ @dc.dataclass(frozen=True)
61
+ class UpdatedAtTrigger(Element, lang.Final):
62
+ column: str
63
+
64
+
65
+ @dc.dataclass(frozen=True)
66
+ class CreatedAtUpdatedAt(Element, lang.Final):
67
+ pass
68
+
69
+
70
+ ##
71
+
72
+
73
+ @dc.dataclass(frozen=True)
74
+ class Elements(ta.Sequence[Element], lang.Final):
75
+ lst: ta.Sequence[Element] = dc.xfield(coerce=col.seq_of(check.of_isinstance(Element)))
76
+
77
+ def __iter__(self) -> ta.Iterator[Element]:
78
+ return iter(self.lst)
79
+
80
+ def __getitem__(self, index: ta.Any) -> Element: # type: ignore[override]
81
+ return self.lst[index]
82
+
83
+ def __len__(self) -> int:
84
+ return len(self.lst)
85
+
86
+ @lang.cached_property
87
+ def by_type(self) -> col.DynamicTypeMap[Element]:
88
+ return col.DynamicTypeMap(self.lst)
@@ -0,0 +1,49 @@
1
+ from ... import dataclasses as dc
2
+ from .dtypes import Datetime
3
+ from .dtypes import Integer
4
+ from .elements import Column
5
+ from .elements import CreatedAt
6
+ from .elements import CreatedAtUpdatedAt
7
+ from .elements import Element
8
+ from .elements import Elements
9
+ from .elements import IdIntegerPrimaryKey
10
+ from .elements import PrimaryKey
11
+ from .elements import UpdatedAt
12
+ from .elements import UpdatedAtTrigger
13
+ from .tabledefs import TableDef
14
+
15
+
16
+ def lower_table_elements(td: TableDef) -> TableDef:
17
+ todo: list[Element] = list(td.elements)[::-1]
18
+ out: list[Element] = []
19
+
20
+ while todo:
21
+ match (e := todo.pop()):
22
+ case Column() | PrimaryKey():
23
+ out.append(e)
24
+
25
+ case IdIntegerPrimaryKey():
26
+ out.extend([
27
+ Column('id', Integer()),
28
+ PrimaryKey(['id']),
29
+ ])
30
+
31
+ case CreatedAt():
32
+ out.append(Column('created_at', Datetime()))
33
+
34
+ case UpdatedAt():
35
+ out.extend([
36
+ Column('updated_at', Datetime()),
37
+ UpdatedAtTrigger('updated_at'),
38
+ ])
39
+
40
+ case CreatedAtUpdatedAt():
41
+ todo.extend([
42
+ CreatedAt(),
43
+ UpdatedAt(),
44
+ ][::-1])
45
+
46
+ case _:
47
+ raise TypeError(e)
48
+
49
+ return dc.replace(td, elements=Elements(out))
@@ -0,0 +1,19 @@
1
+ from ... import lang
2
+ from ... import marshal as msh
3
+ from .dtypes import Dtype
4
+ from .elements import Element
5
+
6
+
7
+ def _install_poly(cls: type) -> None:
8
+ p = msh.polymorphism_from_subclasses(cls, naming=msh.Naming.SNAKE)
9
+ msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.PolymorphismMarshalerFactory(p)]
10
+ msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(p)]
11
+
12
+
13
+ @lang.cached_function
14
+ def _install_standard_marshalling() -> None:
15
+ _install_poly(Dtype)
16
+ _install_poly(Element)
17
+
18
+
19
+ _install_standard_marshalling()
@@ -0,0 +1,52 @@
1
+ """
2
+ TODO:
3
+ - QualifiedName
4
+ - hybrid dataclass scheme
5
+ - sqlite without sqlalchemy
6
+
7
+ ==
8
+
9
+ @td.tableclass([
10
+ IdIntegerPrimaryKey(),
11
+ CreatedAtUpdatedAt(),
12
+ ])
13
+ @dc.dataclass(frozen=True)
14
+ class User(lang.Final):
15
+ id: int
16
+
17
+ created_at: datetime.datetime
18
+ updated_at: datetime.datetime
19
+
20
+ name: str
21
+
22
+ ==
23
+
24
+ @td.tableclass([
25
+ IdIntegerPrimaryKey(),
26
+ CreatedAtUpdatedAt(),
27
+ ])
28
+ @dc.dataclass(frozen=True)
29
+ class BaseTable(lang.Abstract):
30
+ id: int
31
+
32
+ created_at: datetime.datetime
33
+ updated_at: datetime.datetime
34
+
35
+ @td.tableclass('user')
36
+ @dc.dataclass(frozen=True)
37
+ class User(BaseTable, lang.Final):
38
+ name: str
39
+
40
+ """
41
+ from ... import dataclasses as dc
42
+ from ... import lang
43
+ from .elements import Elements
44
+
45
+
46
+ ##
47
+
48
+
49
+ @dc.dataclass(frozen=True)
50
+ class TableDef(lang.Final):
51
+ name: str
52
+ elements: Elements