python-plugins 1.0.2__py3-none-any.whl → 1.0.3__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 (33) hide show
  1. python_plugins/__about__.py +1 -1
  2. python_plugins/crypto/zip7mix.py +12 -2
  3. python_plugins/sqla/__init__.py +3 -0
  4. python_plugins/sqla/db.py +96 -0
  5. python_plugins/sqla/models/association_proxy.py +48 -0
  6. python_plugins/sqla/models/demo.py +114 -0
  7. python_plugins/sqla/models/message.py +19 -0
  8. python_plugins/sqla/models/model1.py +161 -0
  9. python_plugins/sqla/models/multpk.py +16 -0
  10. python_plugins/sqla/models/polymorphic.py +35 -0
  11. python_plugins/sqla/models/relations.py +74 -0
  12. python_plugins/sqla/models/tree_node.py +17 -0
  13. python_plugins/sqla/orm.py +40 -0
  14. python_plugins/sqla/utils/__init__.py +10 -0
  15. python_plugins/sqla/utils/attr.py +110 -0
  16. python_plugins/sqla/utils/expression.py +9 -0
  17. python_plugins/sqla/utils/instance.py +12 -0
  18. python_plugins/sqla/utils/model.py +31 -0
  19. python_plugins/sqla/utils/stmt.py +34 -0
  20. python_plugins/sqla/utils/update.py +23 -0
  21. {python_plugins-1.0.2.dist-info → python_plugins-1.0.3.dist-info}/METADATA +6 -12
  22. python_plugins-1.0.3.dist-info/RECORD +53 -0
  23. {python_plugins-1.0.2.dist-info → python_plugins-1.0.3.dist-info}/WHEEL +1 -1
  24. python_plugins/models/update.py +0 -33
  25. python_plugins-1.0.2.dist-info/RECORD +0 -36
  26. /python_plugins/{models → sqla}/mixins/__init__.py +0 -0
  27. /python_plugins/{models → sqla}/mixins/data_mixin.py +0 -0
  28. /python_plugins/{models → sqla}/mixins/primary_key_mixin.py +0 -0
  29. /python_plugins/{models → sqla}/mixins/timestamp_mixin.py +0 -0
  30. /python_plugins/{models → sqla}/mixins/token_minxin.py +0 -0
  31. /python_plugins/{models → sqla}/mixins/user_minxin.py +0 -0
  32. /python_plugins/{models → sqla/models}/__init__.py +0 -0
  33. {python_plugins-1.0.2.dist-info → python_plugins-1.0.3.dist-info}/licenses/LICENSE.rst +0 -0
@@ -1 +1 @@
1
- __version__ = "1.0.2"
1
+ __version__ = "1.0.3"
@@ -21,7 +21,7 @@ class Zip7Mix(MixByte):
21
21
  def compress(self, file_or_dir, archive_path=None, pwd=None, silent=True):
22
22
  """
23
23
  examples::
24
-
24
+
25
25
  compress("myfile.txt") # output to myfile.txt.7z
26
26
  compress("myfolder") # output to myfolder.7z
27
27
  compress("myfile.txt", "archive.7z", pwd="mypassword")
@@ -70,7 +70,7 @@ class Zip7Mix(MixByte):
70
70
  ):
71
71
  """
72
72
  Examples::
73
-
73
+
74
74
  uncompress("archive.7z") # output to folder archive_extracted
75
75
  uncompress("archive.7z", "output_folder") # output to output_folder
76
76
  uncompress("archive.7z", pwd="mypassword")
@@ -152,3 +152,13 @@ class Zip7Mix(MixByte):
152
152
  archive_path=archive_path, output_path=output_path, pwd=pwd
153
153
  )
154
154
  return result
155
+
156
+ def unpwd(self, archive_path):
157
+ file_size = op.getsize(archive_path)
158
+ with open(archive_path, "rb") as f:
159
+ if file_size > 1000:
160
+ f.seek(-1000, os.SEEK_END)
161
+ data = f.read()
162
+ parse_result = self.parse_tail_link_blocks(data)
163
+ pwd = parse_result["pwd"].decode("utf-8")
164
+ return pwd
@@ -0,0 +1,3 @@
1
+ from .db import Db
2
+
3
+ db = Db()
@@ -0,0 +1,96 @@
1
+ from flask import Flask
2
+ from flask import current_app
3
+ from flask import g
4
+ from sqlalchemy import create_engine
5
+ from sqlalchemy.orm import sessionmaker
6
+ from sqlalchemy.orm import scoped_session
7
+ from sqlalchemy.orm import DeclarativeBase
8
+
9
+
10
+ class Db:
11
+ Model = None
12
+ engine = None
13
+ session = None
14
+ Session = None
15
+
16
+ def __init__(self, app: Flask | None = None):
17
+ self.Model = self._make_declarative_base()
18
+ if app is not None:
19
+ self.init_app(app)
20
+
21
+ def _make_declarative_base(self):
22
+ class Base(DeclarativeBase):
23
+ pass
24
+
25
+ return Base
26
+
27
+ def init_session(self, url=None, echo=False):
28
+ """Initialize the database engine and session factory.
29
+ This method is used in non-Flask environments.
30
+ Examples:
31
+ db = Db()
32
+ db.init_session(url="sqlite:///mydb.sqlite", echo=True)
33
+ db.create_all()
34
+ with db.Session() as session:
35
+ # use the session here
36
+ session.add(some_object)
37
+ session.commit()
38
+ """
39
+ options = {"url": url or "sqlite:///:memory:"}
40
+ if echo:
41
+ options["echo"] = True
42
+ self.engine = create_engine(**options)
43
+ self.Session = sessionmaker(self.engine)
44
+
45
+ def init_app(self, app: Flask) -> None:
46
+ if "sqlalchemy" in app.extensions:
47
+ raise RuntimeError("A 'SQLAlchemy' instance has already been registered.")
48
+ app.extensions["sqlalchemy"] = self
49
+
50
+ # engine
51
+ engine_options = {
52
+ "url": app.config.get("SQLALCHEMY_DATABASE_URI", "sqlite:///:memory:")
53
+ }
54
+ if app.config.get("SQLALCHEMY_ECHO"):
55
+ engine_options["echo"] = True
56
+ self.engine = self._make_engine(engine_options)
57
+
58
+ # session
59
+ session_options = {"bind": self.engine}
60
+ self.session = self._make_scoped_session(session_options)
61
+ app.teardown_appcontext(self._remove_session)
62
+
63
+ # cli
64
+ app.shell_context_processor(self._add_models_to_shell)
65
+
66
+ def _make_engine(self, options: dict):
67
+ return create_engine(**options)
68
+
69
+ def _make_scoped_session(self, options):
70
+ session_factory = sessionmaker(**options)
71
+ return scoped_session(session_factory, scopefunc=self._get_app_g_id)
72
+
73
+ def _get_app_g_id(self) -> int:
74
+ return id(g._get_current_object())
75
+
76
+ def _remove_session(self, exception=None):
77
+ """Remove the current session at the end of the request."""
78
+ self.session.remove()
79
+
80
+ def _add_models_to_shell(self):
81
+ """Registered with :meth:`~flask.Flask.shell_context_processor`.
82
+ Adds the ``db`` instance and all model classes to ``flask shell``.
83
+ """
84
+ db = current_app.extensions["sqlalchemy"]
85
+ out = {m.class_.__name__: m.class_ for m in db.Model.registry.mappers}
86
+ out["db"] = db
87
+ return out
88
+
89
+ def create_all(self, **kwargs):
90
+ if "bind" not in kwargs:
91
+ kwargs["bind"] = self.engine
92
+ self.Model.metadata.create_all(**kwargs)
93
+
94
+ def reset_models(self):
95
+ self.Model.metadata.drop_all(self.engine)
96
+ self.Model.metadata.create_all(self.engine)
@@ -0,0 +1,48 @@
1
+ from typing import Final
2
+ from typing import List
3
+ from .. import db
4
+ from ..orm import Mapped
5
+ from ..orm import mapped_column
6
+ from ..orm import ForeignKey
7
+ from ..orm import relationship
8
+ from ..orm import Table
9
+ from ..orm import Column
10
+ from ..orm import Integer
11
+ from ..orm import String
12
+ from ..orm import association_proxy
13
+ from ..orm import AssociationProxy
14
+
15
+
16
+ class AssociationProxyChild(db.Model):
17
+ __tablename__ = "association_proxy_child"
18
+ id: Mapped[int] = mapped_column(primary_key=True)
19
+ name: Mapped[str] = mapped_column(String(64))
20
+
21
+
22
+ class AssociationProxyParent(db.Model):
23
+ __tablename__ = "association_proxy_parent"
24
+ id: Mapped[int] = mapped_column(primary_key=True)
25
+ name: Mapped[str] = mapped_column(String(64))
26
+ children: Mapped[List[AssociationProxyChild]] = relationship(
27
+ secondary=lambda: association_proxy_parent_child_table
28
+ )
29
+ # proxy the 'name' attribute from the 'children' relationship
30
+ childrennames: AssociationProxy[List[str]] = association_proxy("children", "name")
31
+
32
+
33
+ association_proxy_parent_child_table: Final[Table] = Table(
34
+ "association_proxy_parent_child",
35
+ db.Model.metadata,
36
+ Column(
37
+ "association_proxy_parent_id",
38
+ Integer,
39
+ ForeignKey("association_proxy_parent.id"),
40
+ primary_key=True,
41
+ ),
42
+ Column(
43
+ "association_proxy_child_id",
44
+ Integer,
45
+ ForeignKey("association_proxy_child.id"),
46
+ primary_key=True,
47
+ ),
48
+ )
@@ -0,0 +1,114 @@
1
+ from typing import Optional, List
2
+ from datetime import datetime
3
+ from datetime import date
4
+ from datetime import time
5
+ import enum
6
+
7
+ from .. import db
8
+ from ..orm import Integer
9
+ from ..orm import Boolean
10
+ from ..orm import String
11
+ from ..orm import Float
12
+ from ..orm import DateTime
13
+ from ..orm import Date
14
+ from ..orm import Time
15
+ from ..orm import LargeBinary
16
+ from ..orm import Enum
17
+ from ..orm import JSON
18
+ from ..orm import Mapped
19
+ from ..orm import mapped_column
20
+ from ..orm import relationship
21
+ from ..orm import composite
22
+ from ..orm import synonym
23
+ from ..orm import Table
24
+ from ..orm import Column
25
+ from ..orm import ForeignKey
26
+ from ..orm import hybrid_property
27
+ from ..orm import hybrid_method
28
+ from ..orm import association_proxy
29
+ from ..orm import AssociationProxy
30
+
31
+ # see https://docs.sqlalchemy.org/en/20/orm/extensions/associationproxy.html
32
+
33
+ class Point:
34
+ x: int
35
+ y: int
36
+
37
+
38
+ # Status = Literal["pending", "received", "completed"]
39
+ class Status(enum.Enum):
40
+ PENDING = "pending"
41
+ RECEIVED = "received"
42
+ COMPLETED = "completed"
43
+
44
+
45
+ class Demo(db.Model):
46
+ __tablename__ = "demo"
47
+
48
+ id: Mapped[int] = mapped_column(primary_key=True)
49
+ name: Mapped[str] = mapped_column(unique=True)
50
+ first_name: Mapped[str]
51
+ last_name: Mapped[str]
52
+ data: Mapped[dict] = mapped_column(JSON)
53
+ bool_field: Mapped[bool] = mapped_column(Boolean, nullable=True)
54
+ date_field: Mapped[date] = mapped_column(Date, nullable=True)
55
+ time_field: Mapped[time] = mapped_column(Time, nullable=True)
56
+ datetime_field: Mapped[datetime] = mapped_column(DateTime, nullable=True)
57
+ x: Mapped[int]
58
+ y: Mapped[int]
59
+ start: Mapped[int]
60
+ end: Mapped[int]
61
+ status: Mapped[Status]
62
+ created_at: Mapped[datetime] = mapped_column(default=datetime.now)
63
+ updated_at: Mapped[datetime] = mapped_column(
64
+ default=datetime.now, onupdate=datetime.now
65
+ )
66
+ point: Mapped[Point] = composite("x", "y")
67
+
68
+ syn_status = synonym("status")
69
+
70
+ @hybrid_property
71
+ def full_name(self) -> str:
72
+ return f"{self.first_name} {self.last_name}"
73
+
74
+ @hybrid_method
75
+ def contains(self, point: int) -> bool:
76
+ return (self.start <= point) & (point <= self.end)
77
+
78
+ tg: Mapped[List["Tag"]] = relationship(secondary=lambda: demo_tag_table)
79
+ # proxy the 'keyword' attribute from the 'kw' relationship
80
+ tags: AssociationProxy[List[str]] = association_proxy("tg", "tag")
81
+
82
+ addresses: Mapped[List["Address"]] = relationship(back_populates="demo")
83
+
84
+ def __init__(self, name: str):
85
+ self.name = name
86
+
87
+
88
+ class Address(db.Model):
89
+ __tablename__ = "address"
90
+ id: Mapped[int] = mapped_column(primary_key=True)
91
+ street: Mapped[str]
92
+ demo_id = mapped_column(ForeignKey("demo.id"))
93
+ demo: Mapped["Demo"] = relationship(back_populates="addresses")
94
+
95
+
96
+ class Tag(db.Model):
97
+ __tablename__ = "tag"
98
+
99
+ id: Mapped[int] = mapped_column(primary_key=True)
100
+ tag: Mapped[str]
101
+
102
+ def __init__(self, tag: str):
103
+ self.tag = tag
104
+
105
+ def __repr__(self) -> str:
106
+ return f"Tag({self.tag!r})"
107
+
108
+
109
+ demo_tag_table = Table(
110
+ "demo_tag",
111
+ db.Model.metadata,
112
+ Column("demo_id", ForeignKey("demo.id"), primary_key=True),
113
+ Column("tag_id", ForeignKey("tag.id"), primary_key=True),
114
+ )
@@ -0,0 +1,19 @@
1
+ import enum
2
+ from .. import db
3
+ from ..orm import Mapped
4
+ from ..orm import mapped_column
5
+
6
+
7
+ class MyCat(enum.Enum):
8
+ CAT1 = "Category A"
9
+ CAT2 = "Category B"
10
+
11
+
12
+ class Message(db.Model):
13
+ __table__tablename__ = "message"
14
+ id: Mapped[int] = mapped_column(primary_key=True)
15
+ text: Mapped[str]
16
+ sender: Mapped[str]
17
+ recipient: Mapped[str]
18
+ category:Mapped[MyCat] = mapped_column(default=MyCat.CAT1,nullable=False)
19
+
@@ -0,0 +1,161 @@
1
+ import enum
2
+ from datetime import datetime, date, time
3
+ from .. import db
4
+ from ..orm import Mapped
5
+ from ..orm import mapped_column
6
+ from ..orm import Enum
7
+ from ..orm import hybrid_property
8
+ from ..orm import cast
9
+
10
+
11
+ class EnumChoices(enum.Enum):
12
+ first = 1
13
+ second = 2
14
+
15
+
16
+ class Model1(db.Model):
17
+ id: Mapped[int] = mapped_column(primary_key=True)
18
+ test1:Mapped[str]
19
+ test2:Mapped[str]
20
+ test3:Mapped[str]
21
+ test4:Mapped[str]
22
+ bool_field: Mapped[bool]
23
+ date_field: Mapped[date]
24
+ time_field: Mapped[time]
25
+ datetime_field: Mapped[datetime]
26
+ email_field:Mapped[str]
27
+ enum_field: Mapped[str] = mapped_column(Enum("model1_v1", "model1_v2"), nullable=True)
28
+ enum_type_field = mapped_column(Enum(EnumChoices), nullable=True)
29
+ choice_field:Mapped[str]
30
+
31
+ def __init__(
32
+ self,
33
+ test1=None,
34
+ test2=None,
35
+ test3=None,
36
+ test4=None,
37
+ bool_field=False,
38
+ date_field=None,
39
+ time_field=None,
40
+ datetime_field=None,
41
+ choice_field=None,
42
+ enum_field=None,
43
+ enum_type_field=None,
44
+ ):
45
+ self.test1 = test1
46
+ self.test2 = test2
47
+ self.test3 = test3
48
+ self.test4 = test4
49
+ self.bool_field = bool_field
50
+ self.date_field = date_field
51
+ self.time_field = time_field
52
+ self.datetime_field = datetime_field
53
+ self.choice_field = choice_field
54
+ self.enum_field = enum_field
55
+ self.enum_type_field = enum_type_field
56
+
57
+ def __str__(self):
58
+ return str(self.test1)
59
+
60
+
61
+ class Model2(db.Model):
62
+ id: Mapped[int] = mapped_column(primary_key=True)
63
+ string_field:Mapped[str]
64
+ string_field_default = db.Column(db.Text, nullable=False, default="")
65
+ string_field_empty_default = db.Column(db.Text, nullable=False, default="")
66
+ int_field = db.Column(db.Integer)
67
+ bool_field = db.Column(db.Boolean)
68
+ enum_field = db.Column(db.Enum("model2_v1", "model2_v2"), nullable=True)
69
+ float_field = db.Column(db.Float)
70
+
71
+ # Relation
72
+ model1_id = db.Column(db.Integer, db.ForeignKey(Model1.id))
73
+ model1 = db.relationship(lambda: Model1, backref="model2")
74
+
75
+ def __init__(
76
+ self,
77
+ string_field=None,
78
+ int_field=None,
79
+ bool_field=None,
80
+ model1=None,
81
+ float_field=None,
82
+ string_field_default=None,
83
+ string_field_empty_default=None,
84
+ ):
85
+ self.string_field = string_field
86
+ self.int_field = int_field
87
+ self.bool_field = bool_field
88
+ self.model1 = model1
89
+ self.float_field = float_field
90
+ self.string_field_default = string_field_default
91
+ self.string_field_empty_default = string_field_empty_default
92
+
93
+
94
+ class Model3(db.Model):
95
+ def __init__(self, id=None, val1=None):
96
+ self.id = id
97
+ self.val1 = val1
98
+
99
+ id = db.Column(db.String(20), primary_key=True)
100
+ val1 = db.Column(db.String(20))
101
+
102
+
103
+ class ModelHybrid(db.Model):
104
+ id: Mapped[int] = mapped_column(primary_key=True)
105
+ name = db.Column(db.String)
106
+ width = db.Column(db.Integer)
107
+ height = db.Column(db.Integer)
108
+
109
+ firstname = db.Column(db.String)
110
+ lastname = db.Column(db.String)
111
+
112
+ @hybrid_property
113
+ def fullname(self):
114
+ return "{} {}".format(self.firstname, self.lastname)
115
+
116
+ @hybrid_property
117
+ def number_of_pixels(self):
118
+ return self.width * self.height
119
+
120
+ @hybrid_property
121
+ def number_of_pixels_str(self):
122
+ return str(self.number_of_pixels())
123
+
124
+ @number_of_pixels_str.expression
125
+ def number_of_pixels_str(cls):
126
+ return cast(cls.width * cls.height, db.String)
127
+
128
+
129
+ class ModelHybrid2(db.Model):
130
+ id: Mapped[int] = mapped_column(primary_key=True)
131
+ name = db.Column(db.String)
132
+ owner_id = db.Column(
133
+ db.Integer, db.ForeignKey("model_hybrid.id", ondelete="CASCADE")
134
+ )
135
+ owner = db.relationship("ModelHybrid", backref=db.backref("tiles"), uselist=False)
136
+
137
+
138
+ class ModelNoint(db.Model):
139
+ id: Mapped[str] = mapped_column(primary_key=True)
140
+ test = db.Column(db.String)
141
+
142
+
143
+ class ModelForm(db.Model):
144
+ id: Mapped[str] = mapped_column(primary_key=True)
145
+ int_field = db.Column(db.Integer)
146
+ datetime_field = db.Column(db.DateTime)
147
+ text_field = db.Column(db.UnicodeText)
148
+ excluded_column = db.Column(db.String)
149
+
150
+
151
+ class ModelChild(db.Model):
152
+ id: Mapped[str] = mapped_column(primary_key=True)
153
+ model_id = db.Column(db.Integer, db.ForeignKey(ModelForm.id))
154
+ model = db.relationship(ModelForm, backref="backref")
155
+ enum_field = db.Column(db.Enum("model1_v1", "model1_v2"), nullable=True)
156
+ choice_field = db.Column(db.String, nullable=True)
157
+
158
+
159
+
160
+
161
+
@@ -0,0 +1,16 @@
1
+ from .. import db
2
+ from ..orm import Mapped
3
+ from ..orm import mapped_column
4
+
5
+
6
+ class Singlepk(db.Model):
7
+ __tablename__ = "singlepk"
8
+ id: Mapped[int] = mapped_column(primary_key=True)
9
+ data: Mapped[str]
10
+
11
+
12
+ class Multpk(db.Model):
13
+ __tablename__ = "multpk"
14
+ id: Mapped[int] = mapped_column(primary_key=True)
15
+ id2: Mapped[int] = mapped_column(primary_key=True)
16
+ data: Mapped[str]
@@ -0,0 +1,35 @@
1
+ from typing import Optional
2
+ from .. import db
3
+ from ..orm import Mapped
4
+ from ..orm import mapped_column
5
+
6
+ # see https://docs.sqlalchemy.org/en/20/orm/inheritance.html#single-inheritance
7
+ # see https://docs.sqlalchemy.org/en/20/orm/queryguide/_single_inheritance.html
8
+
9
+ class Employee(db.Model):
10
+ __tablename__ = "employee"
11
+ id: Mapped[int] = mapped_column(primary_key=True)
12
+ name: Mapped[str]
13
+ type: Mapped[str]
14
+
15
+ def __repr__(self):
16
+ return f"{self.__class__.__name__}({self.name!r})"
17
+
18
+ __mapper_args__ = {
19
+ "polymorphic_identity": "employee",
20
+ "polymorphic_on": "type",
21
+ }
22
+
23
+
24
+ class Manager(Employee):
25
+ manager_name: Mapped[str] = mapped_column(nullable=True)
26
+ __mapper_args__ = {
27
+ "polymorphic_identity": "manager",
28
+ }
29
+
30
+
31
+ class Engineer(Employee):
32
+ engineer_info: Mapped[str] = mapped_column(nullable=True)
33
+ __mapper_args__ = {
34
+ "polymorphic_identity": "engineer",
35
+ }
@@ -0,0 +1,74 @@
1
+ from typing import List
2
+ from typing import Set
3
+ from .. import db
4
+ from ..orm import Mapped
5
+ from ..orm import mapped_column
6
+ from ..orm import ForeignKey
7
+ from ..orm import relationship
8
+ from ..orm import Table
9
+ from ..orm import Column
10
+ from ..orm import Integer
11
+
12
+
13
+ class OneToManyParent(db.Model):
14
+ __tablename__ = "one_to_many_parent"
15
+ id: Mapped[int] = mapped_column(primary_key=True)
16
+ children: Mapped[List["ManyToOneChild"]] = relationship()
17
+ children2: Mapped[List["ManyToOneChild2"]] = relationship(back_populates="parent2")
18
+ children3: Mapped[Set["ManyToOneChild3"]] = relationship(back_populates="parent3")
19
+
20
+
21
+ class ManyToOneChild(db.Model):
22
+ __tablename__ = "many_to_one_child1"
23
+ id: Mapped[int] = mapped_column(primary_key=True)
24
+ parent_id: Mapped[int] = mapped_column(ForeignKey("one_to_many_parent.id"))
25
+
26
+
27
+ class ManyToOneChild2(db.Model):
28
+ __tablename__ = "many_to_one_child2"
29
+ id: Mapped[int] = mapped_column(primary_key=True)
30
+ parent_id: Mapped[int] = mapped_column(ForeignKey("one_to_many_parent.id"))
31
+ parent2: Mapped["OneToManyParent"] = relationship(back_populates="children2")
32
+
33
+
34
+ class ManyToOneChild3(db.Model):
35
+ __tablename__ = "many_to_one_child3"
36
+ id: Mapped[int] = mapped_column(primary_key=True)
37
+ parent_id: Mapped[int] = mapped_column(ForeignKey("one_to_many_parent.id"))
38
+ parent3: Mapped["OneToManyParent"] = relationship(back_populates="children3")
39
+
40
+ class OneToOneParent(db.Model):
41
+ __tablename__ = "one_to_one_parent"
42
+ id: Mapped[int] = mapped_column(primary_key=True)
43
+ child: Mapped["OneToOneChild"] = relationship(back_populates="parent")
44
+
45
+
46
+ class OneToOneChild(db.Model):
47
+ __tablename__ = "one_to_one_child"
48
+ id: Mapped[int] = mapped_column(primary_key=True)
49
+ parent_id: Mapped[int] = mapped_column(ForeignKey("one_to_one_parent.id"))
50
+ parent: Mapped["OneToOneParent"] = relationship(back_populates="child")
51
+
52
+
53
+ association_table = Table(
54
+ "many_to_many_association",
55
+ db.Model.metadata,
56
+ Column("left_id", Integer, ForeignKey("many_to_many_left.id"), primary_key=True),
57
+ Column("right_id", Integer, ForeignKey("many_to_many_right.id"), primary_key=True),
58
+ )
59
+
60
+
61
+ class ManyToManyLeft(db.Model):
62
+ __tablename__ = "many_to_many_left"
63
+ id: Mapped[int] = mapped_column(primary_key=True)
64
+ rights: Mapped[List["ManyToManyRight"]] = relationship(
65
+ secondary=association_table, back_populates="lefts"
66
+ )
67
+
68
+
69
+ class ManyToManyRight(db.Model):
70
+ __tablename__ = "many_to_many_right"
71
+ id: Mapped[int] = mapped_column(primary_key=True)
72
+ lefts: Mapped[List["ManyToManyLeft"]] = relationship(
73
+ secondary=association_table, back_populates="rights"
74
+ )
@@ -0,0 +1,17 @@
1
+ from .. import db
2
+ from ..orm import ForeignKey
3
+ from ..orm import Mapped
4
+ from ..orm import mapped_column
5
+ from ..orm import relationship
6
+
7
+ # Adjacency List Relationships
8
+ # see https://docs.sqlalchemy.org/en/20/orm/self_referential.html
9
+
10
+
11
+ class TreeNode(db.Model):
12
+ __tablename__ = "tree_node"
13
+ id: Mapped[int] = mapped_column(primary_key=True)
14
+ parent_id = mapped_column(ForeignKey("tree_node.id"))
15
+ data: Mapped[str]
16
+ children = relationship("TreeNode", back_populates="parent")
17
+ parent = relationship("TreeNode", back_populates="children", remote_side=[id])
@@ -0,0 +1,40 @@
1
+ from sqlalchemy.types import Integer
2
+ from sqlalchemy.types import Boolean
3
+ from sqlalchemy.types import String
4
+ from sqlalchemy.types import TEXT
5
+ from sqlalchemy.types import Float
6
+ from sqlalchemy.types import DateTime
7
+ from sqlalchemy.types import Date
8
+ from sqlalchemy.types import Time
9
+ from sqlalchemy.types import LargeBinary
10
+ from sqlalchemy.types import JSON
11
+ from sqlalchemy.types import Enum
12
+
13
+ from sqlalchemy.sql import select
14
+ from sqlalchemy.sql import delete
15
+ from sqlalchemy.sql import func
16
+ from sqlalchemy.sql import cast
17
+ from sqlalchemy.sql import text
18
+ from sqlalchemy.sql import and_
19
+ from sqlalchemy.sql import or_
20
+ from sqlalchemy.sql import not_
21
+
22
+ from sqlalchemy import Column
23
+ from sqlalchemy import Table
24
+ from sqlalchemy import ForeignKey
25
+
26
+ from sqlalchemy.orm import Mapped
27
+ from sqlalchemy.orm import mapped_column
28
+ from sqlalchemy.orm import relationship
29
+ from sqlalchemy.orm import composite
30
+ from sqlalchemy.orm import synonym
31
+
32
+ from sqlalchemy.orm import joinedload
33
+ from sqlalchemy.orm import selectinload
34
+
35
+ from sqlalchemy.ext.associationproxy import association_proxy
36
+ from sqlalchemy.ext.associationproxy import AssociationProxy
37
+ from sqlalchemy.ext.hybrid import hybrid_property
38
+ from sqlalchemy.ext.hybrid import hybrid_method
39
+ from sqlalchemy.ext.mutable import MutableDict
40
+ from sqlalchemy.ext.mutable import MutableList
@@ -0,0 +1,10 @@
1
+ from .attr import is_column
2
+ from .attr import is_relationship
3
+ from .attr import is_hybrid
4
+ from .attr import is_association_proxy
5
+ from .attr import get_field_with_path
6
+ from .expression import parse_like_term
7
+ from .stmt import select_pk_values
8
+ from .stmt import clear
9
+ from .stmt import delete_by_pk_ids
10
+
@@ -0,0 +1,110 @@
1
+ from typing import Tuple, List
2
+ from sqlalchemy.orm import ColumnProperty
3
+ from sqlalchemy.orm import RelationshipProperty
4
+ from sqlalchemy.orm.attributes import InstrumentedAttribute
5
+ from sqlalchemy.ext.hybrid import hybrid_property
6
+ from sqlalchemy.ext.associationproxy import AssociationProxy
7
+
8
+ def is_instrumented_attribute(attr):
9
+ return isinstance(attr, InstrumentedAttribute)
10
+
11
+
12
+ def is_column(attr):
13
+ return hasattr(attr, "property") and isinstance(attr.property, ColumnProperty)
14
+
15
+
16
+ def is_relationship(attr):
17
+ return hasattr(attr, "property") and isinstance(attr.property, RelationshipProperty)
18
+
19
+
20
+ def is_hybrid(attr):
21
+ return isinstance(attr, hybrid_property)
22
+
23
+ def is_association_proxy(attr):
24
+ return isinstance(attr, AssociationProxy)
25
+
26
+
27
+ def get_field_with_path(
28
+ model, path: str
29
+ ) -> Tuple[InstrumentedAttribute, List[InstrumentedAttribute]]:
30
+ """
31
+ Resolve a dot-separated field path (e.g., 'profile.contact.email')
32
+ starting from `model`, handling AssociationProxy and relationships.
33
+
34
+ Returns:
35
+ (final_attr, join_path)
36
+ - final_attr: The terminal InstrumentedAttribute (e.g., Contact.email)
37
+ - join_path: List of relationship attributes for explicit joins
38
+ (e.g., [User.profile, Profile.contact])
39
+ """
40
+ print(model, path)
41
+ parts = path.split(".")
42
+ current_model = model
43
+ current_attr = None
44
+ join_path: List[InstrumentedAttribute] = []
45
+
46
+ for i, part in enumerate(parts):
47
+ attr = getattr(current_model, part)
48
+ # Case 1: Column (must be last)
49
+ if hasattr(attr, "property") and isinstance(attr.property, ColumnProperty):
50
+ if i != len(parts) - 1:
51
+ raise ValueError(
52
+ f"Column '{part}' cannot be followed by further path segments."
53
+ )
54
+ current_attr = attr
55
+ break
56
+ # Case 2: Relationship
57
+ elif is_relationship(attr):
58
+ if i == len(parts) - 1:
59
+ raise ValueError(
60
+ f"Cannot sort/filter on relationship '{path}' directly. "
61
+ "Specify a column (e.g., '{path}.id')."
62
+ )
63
+ join_path.append(attr)
64
+ current_model = attr.property.mapper.class_
65
+ # Case 3: AssociationProxy
66
+ elif isinstance(attr, AssociationProxy):
67
+ # Step into the underlying relationship
68
+ local_rel_name = attr.local_attr # str, e.g., 'profile'
69
+ local_rel = getattr(current_model, local_rel_name)
70
+
71
+ if not is_relationship(local_rel):
72
+ raise ValueError(
73
+ f"AssociationProxy '{part}' is not backed by a relationship "
74
+ f"(got {type(local_rel.property).__name__})."
75
+ )
76
+
77
+ join_path.append(local_rel)
78
+ target_model = local_rel.property.mapper.class_
79
+
80
+ # Get the remote attribute (should be InstrumentedAttribute in SA 2.0)
81
+ remote_attr = attr.remote_attr
82
+
83
+ # If there are more parts after this proxy, recurse
84
+ if i < len(parts) - 1:
85
+ remaining = ".".join(parts[i + 1 :])
86
+ final_attr, extra_joins = get_field_with_path(target_model, remaining)
87
+ join_path.extend(extra_joins)
88
+ return final_attr, join_path
89
+
90
+ # This is the last part — ensure remote_attr is usable
91
+ if isinstance(remote_attr, str):
92
+ # Fallback for older versions (not needed in SA 2.0+, but safe)
93
+ remote_attr = getattr(target_model, remote_attr)
94
+
95
+ if not hasattr(remote_attr, "property"):
96
+ raise ValueError(
97
+ f"Remote attribute {remote_attr} is not a mapped ORM attribute."
98
+ )
99
+
100
+ current_attr = remote_attr
101
+ break
102
+ else:
103
+ raise ValueError(
104
+ f"Unsupported attribute type for '{model}':'{part}': {type(attr)}"
105
+ )
106
+
107
+ if current_attr is None:
108
+ raise RuntimeError("Failed to resolve path — no terminal attribute found.")
109
+
110
+ return current_attr, join_path
@@ -0,0 +1,9 @@
1
+ def parse_like_term(term):
2
+ if term.startswith("^"):
3
+ stmt = "%s%%" % term[1:]
4
+ elif term.startswith("="):
5
+ stmt = term[1:]
6
+ else:
7
+ stmt = "%%%s%%" % term
8
+
9
+ return stmt
@@ -0,0 +1,12 @@
1
+ from sqlalchemy import inspect
2
+
3
+
4
+ def get_identity(instance):
5
+ """
6
+ Return primary key values from an instance.
7
+ """
8
+ identity = inspect(instance).identity
9
+ if len(identity) == 1:
10
+ return identity[0]
11
+ else:
12
+ return identity
@@ -0,0 +1,31 @@
1
+ from sqlalchemy import inspect
2
+
3
+
4
+ def get_model_mapper(model):
5
+ """
6
+ Return the mapper for a given model
7
+ """
8
+ return inspect(model)
9
+
10
+
11
+ def get_primary_key(model):
12
+ """
13
+ Return primary key name from a model. If the primary key consists of multiple columns,
14
+ return the corresponding tuple
15
+ """
16
+ mapper = inspect(model)
17
+ pks = [col.name for col in mapper.primary_key]
18
+ if len(pks) == 1:
19
+ return pks[0]
20
+ elif len(pks) > 1:
21
+ return tuple(pks)
22
+ else:
23
+ return None
24
+
25
+
26
+ def get_model_tables(model):
27
+ """
28
+ Return a set of table names that the model is mapped to
29
+ """
30
+ mapper = inspect(model)
31
+ return mapper.tables
@@ -0,0 +1,34 @@
1
+ from sqlalchemy import inspect
2
+ from sqlalchemy import select
3
+ from sqlalchemy import delete
4
+ from sqlalchemy import tuple_
5
+
6
+
7
+ def select_pk_values(model):
8
+ """
9
+ Return a select statement that selects all primary key values from a model
10
+ """
11
+ mapper = inspect(model)
12
+ stmt = select(*mapper.primary_key)
13
+ return stmt
14
+
15
+ def clear(model):
16
+ """
17
+ Return a delete statement that deletes all rows of the model
18
+ """
19
+ stmt = delete(model)
20
+ return stmt
21
+
22
+ def delete_by_pk_ids(model, ids: list):
23
+ """
24
+ Return a delete statement that deletes all rows with primary key in ids
25
+ """
26
+ mapper = inspect(model)
27
+ primary_key = mapper.primary_key
28
+ if len(primary_key) == 1:
29
+ pk_col = primary_key[0]
30
+ stmt = delete(model).where(pk_col.in_(ids))
31
+ else:
32
+ stmt = delete(model).where(tuple_(*primary_key).in_(ids))
33
+ return stmt
34
+
@@ -0,0 +1,23 @@
1
+ def update_obj(session, Model, obj, data: dict):
2
+ """insert or update object
3
+
4
+ :param session: sqlalchemy session
5
+ :param Model: object Model
6
+ :param obj: object of Model
7
+ :param data: data dict
8
+ """
9
+
10
+ if obj is None:
11
+ new_obj = Model()
12
+ for k in data:
13
+ if hasattr(new_obj, k):
14
+ setattr(new_obj, k, data.get(k))
15
+ session.add(new_obj)
16
+ session.commit()
17
+ print(f"{new_obj} inserted")
18
+ else:
19
+ for k in data:
20
+ if hasattr(obj, k):
21
+ setattr(obj, k, data.get(k))
22
+ session.commit()
23
+ print(f"{obj} updated")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-plugins
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: A collection of Python functions and classes.
5
5
  Project-URL: Documentation, https://python-plugins.readthedocs.io
6
6
  Project-URL: Source, https://github.com/ojso/python-plugins
@@ -38,17 +38,11 @@ Classifier: Programming Language :: Python :: 3.10
38
38
  Classifier: Programming Language :: Python :: 3.11
39
39
  Classifier: Topic :: Software Development :: Build Tools
40
40
  Requires-Python: >=3.10
41
- Requires-Dist: cryptography>=44.0
42
- Provides-Extra: jwt
43
- Requires-Dist: pyjwt; extra == 'jwt'
44
- Provides-Extra: pillow
45
- Requires-Dist: pillow; extra == 'pillow'
46
- Provides-Extra: qrcode
47
- Requires-Dist: qrcode; extra == 'qrcode'
48
- Provides-Extra: requests
49
- Requires-Dist: requests; extra == 'requests'
50
- Provides-Extra: sqlalchemy
51
- Requires-Dist: sqlalchemy; extra == 'sqlalchemy'
41
+ Requires-Dist: cryptography>=46.0
42
+ Requires-Dist: flask>=3.1
43
+ Requires-Dist: requests>=2.32
44
+ Requires-Dist: sqlalchemy>=2.0
45
+ Requires-Dist: wtforms>=3.2
52
46
  Description-Content-Type: text/x-rst
53
47
 
54
48
  python-plugins
@@ -0,0 +1,53 @@
1
+ python_plugins/__about__.py,sha256=2plzdEEb24FLjE2I2XyBBcJEPYWHccNL4SgtLC_6erg,22
2
+ python_plugins/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
+ python_plugins/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_plugins/crypto/aes_cipher.py,sha256=7lTvA01h3Z56riv7sB7CrZRh_OO66m21wVTVizU9PYg,1946
5
+ python_plugins/crypto/mixbyte.py,sha256=5re7W0-UuOjnnWW9HK50t6akLAbOtPmz9SQ3nq5w3hk,6649
6
+ python_plugins/crypto/pbkdf_fernet.py,sha256=8CGU4ddco6369NaoXodMKz_h8JMetHrZmMVt30XAICM,2049
7
+ python_plugins/crypto/simple_fernet.py,sha256=Yg5OXiXNcbyQ4EC31c58Vn00pbloGjJpscfbxn2L7YQ,1759
8
+ python_plugins/crypto/tarmix.py,sha256=DmTV-vNLTokUQJWn2H4QUSzfFjMQVrX2MiMpMd_BL0g,4874
9
+ python_plugins/crypto/txtfile_cipher.py,sha256=-mTkvQgtNYLUvrQLKTnepBBdkf-T0w-DnMfZ5wnbklU,4852
10
+ python_plugins/crypto/zip7mix.py,sha256=tQMmX_6ax99LXNfY8HBbu9EXSwQSgGOF3EwWEcrtdUo,5272
11
+ python_plugins/email/__init__.py,sha256=HubZT2h3m5WEjic3NZ0H7gYp-9tUgZaDkAE9O-Tm7hM,26
12
+ python_plugins/email/smtp.py,sha256=CY1fWxdBDqqGZ22R8yqEvFZvMeEsMnqTb4h5IZ8WAVU,1641
13
+ python_plugins/examples/datetime.py,sha256=bmC9d1W7XKA1ED9XO9reUiUyfQcM_BqGoGyOF21RW9A,282
14
+ python_plugins/examples/hashes.py,sha256=uSF3ohZRD7b2VAIvjjpTWC0SlY7QsFhsFZUejINrRGU,640
15
+ python_plugins/examples/higher_order_functions.py,sha256=vTfT3OEfuKkIW7UMD3JtreVDMeRbXHbjlz3G-j-J4x4,4574
16
+ python_plugins/examples/postgresql_dump.py,sha256=zN5aLYLxpon2y9_5gKizRjlrRUlkAO-dG-BuKpJ4F3U,1030
17
+ python_plugins/examples/pretty.py,sha256=igN4uq67AADcPOiy_h3_M-oEwgc1i3gJScbKtkf6d-k,211
18
+ python_plugins/examples/random_string.py,sha256=U7B-bAa4zEpewkd4_8KIPZ0XsPdbGlJ_FEj0FnTGdms,2210
19
+ python_plugins/examples/run_jwt.py,sha256=ZwjUXg5PKeophiXqwSaMlHrhwVKhHTsRb68HtkRLX8k,1485
20
+ python_plugins/examples/run_process.py,sha256=I_wjCqzWI6d39ebL-YArQ8LiXFQ3bwEoCnxJTZK1Zbc,780
21
+ python_plugins/examples/xml2dict.py,sha256=RUxqDt6NKzwbuodTxKVoiR4dP-vNbmL77dztLx_9UzY,164
22
+ python_plugins/examples/tkinter/calculate.py,sha256=M1b-w7-pVe-7FS3erBJxgFNfmm4lzP3zlK41glyhWx8,1142
23
+ python_plugins/ospath/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ python_plugins/ospath/walk_remove.py,sha256=rnDHr1wGSxufo2YV9_EXeVNEAnT4LGjG7-5dOI2gWY0,494
25
+ python_plugins/sqla/__init__.py,sha256=dJyZS1js_pdpAgLnsqfRFPQBFeZ8PdssdPfTzgie5c8,30
26
+ python_plugins/sqla/db.py,sha256=fA601WJ3QiUyXAQGwS72wa9S1b973T-HK1ZsE6OL0c0,3179
27
+ python_plugins/sqla/orm.py,sha256=7h0oY4TGfdrvAFKedVbKdWTvWHq_Sc-ycd2VvWiZJyo,1331
28
+ python_plugins/sqla/mixins/__init__.py,sha256=l4dJVgUFI7aISA7X-CcVBOp19rXBgqyyhHwtuQnSgR0,241
29
+ python_plugins/sqla/mixins/data_mixin.py,sha256=HCc1uvF6_O4yjK38uWAsqysEedLWgc7wtds3NjQTMZ8,366
30
+ python_plugins/sqla/mixins/primary_key_mixin.py,sha256=QUO-7ZmYtAMMi7ReRQDYV0uwQCnU9dvl6g6GHitYtlA,154
31
+ python_plugins/sqla/mixins/timestamp_mixin.py,sha256=u9rIu0IrzdCRRbnMk4IN4nTlNNiVPB8yPnTcHjQC1KU,547
32
+ python_plugins/sqla/mixins/token_minxin.py,sha256=SxNftZXS-hCwqxov7whF_tBtlayuoi3LUPtu-ofMmdg,276
33
+ python_plugins/sqla/mixins/user_minxin.py,sha256=D-N45bunicBuuwKs--s_tyDxxLC3mkxV9Tva8JAhsko,579
34
+ python_plugins/sqla/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ python_plugins/sqla/models/association_proxy.py,sha256=a3_ffi4gyXMuDV9NtlCo2POoBxwFCKCA2fSJlfft1Ow,1454
36
+ python_plugins/sqla/models/demo.py,sha256=UbibjsBvm542Gyx8t8qf8Izqs47K88v9BN0Pc2RPAJc,3218
37
+ python_plugins/sqla/models/message.py,sha256=NDxcN8mWnWFTTunf5dz-Tb5FmHv8HHzppsZ8IVHmpAw,435
38
+ python_plugins/sqla/models/model1.py,sha256=NxOsygCCt9q1hpt2QmGsuCs6yl1Kn5tv5HGuhHaPCRQ,4596
39
+ python_plugins/sqla/models/multpk.py,sha256=pexTSm7CzXpf0pD_ECfHraM0QlZcMAYf9Qv_KPijvUA,396
40
+ python_plugins/sqla/models/polymorphic.py,sha256=-nwEoKkAZL97mnykisZ1VkntyeqNLmfEbd7tXxAYnuY,938
41
+ python_plugins/sqla/models/relations.py,sha256=zjbZrhW9pv8Tpnu6zApdO-rhwjbFF3Vv1r_xp5DCKWc,2669
42
+ python_plugins/sqla/models/tree_node.py,sha256=VGGdIGhfDe_0BUp3UpxEjexMSirwezOUXGv-fKiBXvk,575
43
+ python_plugins/sqla/utils/__init__.py,sha256=lq6KaQfwmnobgas87D26ijnaCfDau3H7ZkmozBYWzk0,302
44
+ python_plugins/sqla/utils/attr.py,sha256=IdWj17GXKk4tk-dQROWZh7ZyPPlO4--YaoeZp0EWgUQ,4119
45
+ python_plugins/sqla/utils/expression.py,sha256=_9P59Elc3jqdXFiXxkrRY9gsaUSum-chNMPbiqQcC58,202
46
+ python_plugins/sqla/utils/instance.py,sha256=EbcI3pQhsRj-mPW9ZHs0yQ4zMGVMHw-HtmmXHY15kK0,255
47
+ python_plugins/sqla/utils/model.py,sha256=R9ObqEMDOaYKLv8pcoDHoV7m4mxWHgEDiZ74NokMMjA,678
48
+ python_plugins/sqla/utils/stmt.py,sha256=3GzzEvi0RmvE3q-zBweol9LmsEQ0UPkn9G6P0epNwWw,876
49
+ python_plugins/sqla/utils/update.py,sha256=jsTgivwzIeFSpbpFwb48_pTUNT-KM6TYnGv3wKH98HM,631
50
+ python_plugins-1.0.3.dist-info/METADATA,sha256=1ImRtLGKGW7nNd06mtiLso56_D3ZxVPBy4soald9ghs,2624
51
+ python_plugins-1.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
52
+ python_plugins-1.0.3.dist-info/licenses/LICENSE.rst,sha256=X5eLIsAn1yAKd88LWTYkXUe0PmVK_Z5SD7_5NheGR-s,1104
53
+ python_plugins-1.0.3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,33 +0,0 @@
1
- def update_obj(db, old_obj, new_data: dict, NewClass, force=None):
2
- """insert or update object
3
-
4
- :param db: sqlalchemy db
5
- :param old_obj: old object
6
- :param new_data: new dict
7
- :param NewClass: object class
8
- :param force: update= update old object with new attribute
9
- """
10
- # 1. old is not exist
11
- if old_obj is None:
12
- new_obj = NewClass()
13
- for k in new_data:
14
- if hasattr(new_obj, k):
15
- setattr(new_obj, k, new_data.get(k))
16
- db.session.add(new_obj)
17
- db.session.commit()
18
- print(f"{new_obj} inserted")
19
- return
20
-
21
- # 2. old is exist
22
- match force:
23
- case None:
24
- print(f"{old_obj} exists")
25
- case "update":
26
- # update old
27
- for k in new_data:
28
- if hasattr(old_obj, k):
29
- setattr(old_obj, k, new_data.get(k))
30
- db.session.commit()
31
- print(f"{old_obj} updated")
32
- case _:
33
- raise Exception
@@ -1,36 +0,0 @@
1
- python_plugins/__about__.py,sha256=Y3LSfRioSl2xch70pq_ULlvyECXyEtN3krVaWeGyaxk,22
2
- python_plugins/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
- python_plugins/crypto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_plugins/crypto/aes_cipher.py,sha256=7lTvA01h3Z56riv7sB7CrZRh_OO66m21wVTVizU9PYg,1946
5
- python_plugins/crypto/mixbyte.py,sha256=5re7W0-UuOjnnWW9HK50t6akLAbOtPmz9SQ3nq5w3hk,6649
6
- python_plugins/crypto/pbkdf_fernet.py,sha256=8CGU4ddco6369NaoXodMKz_h8JMetHrZmMVt30XAICM,2049
7
- python_plugins/crypto/simple_fernet.py,sha256=Yg5OXiXNcbyQ4EC31c58Vn00pbloGjJpscfbxn2L7YQ,1759
8
- python_plugins/crypto/tarmix.py,sha256=DmTV-vNLTokUQJWn2H4QUSzfFjMQVrX2MiMpMd_BL0g,4874
9
- python_plugins/crypto/txtfile_cipher.py,sha256=-mTkvQgtNYLUvrQLKTnepBBdkf-T0w-DnMfZ5wnbklU,4852
10
- python_plugins/crypto/zip7mix.py,sha256=x5_N3k6Wr-71Z3cqmPIWqVmzikR7O65xeSr-A42w_Y0,4933
11
- python_plugins/email/__init__.py,sha256=HubZT2h3m5WEjic3NZ0H7gYp-9tUgZaDkAE9O-Tm7hM,26
12
- python_plugins/email/smtp.py,sha256=CY1fWxdBDqqGZ22R8yqEvFZvMeEsMnqTb4h5IZ8WAVU,1641
13
- python_plugins/examples/datetime.py,sha256=bmC9d1W7XKA1ED9XO9reUiUyfQcM_BqGoGyOF21RW9A,282
14
- python_plugins/examples/hashes.py,sha256=uSF3ohZRD7b2VAIvjjpTWC0SlY7QsFhsFZUejINrRGU,640
15
- python_plugins/examples/higher_order_functions.py,sha256=vTfT3OEfuKkIW7UMD3JtreVDMeRbXHbjlz3G-j-J4x4,4574
16
- python_plugins/examples/postgresql_dump.py,sha256=zN5aLYLxpon2y9_5gKizRjlrRUlkAO-dG-BuKpJ4F3U,1030
17
- python_plugins/examples/pretty.py,sha256=igN4uq67AADcPOiy_h3_M-oEwgc1i3gJScbKtkf6d-k,211
18
- python_plugins/examples/random_string.py,sha256=U7B-bAa4zEpewkd4_8KIPZ0XsPdbGlJ_FEj0FnTGdms,2210
19
- python_plugins/examples/run_jwt.py,sha256=ZwjUXg5PKeophiXqwSaMlHrhwVKhHTsRb68HtkRLX8k,1485
20
- python_plugins/examples/run_process.py,sha256=I_wjCqzWI6d39ebL-YArQ8LiXFQ3bwEoCnxJTZK1Zbc,780
21
- python_plugins/examples/xml2dict.py,sha256=RUxqDt6NKzwbuodTxKVoiR4dP-vNbmL77dztLx_9UzY,164
22
- python_plugins/examples/tkinter/calculate.py,sha256=M1b-w7-pVe-7FS3erBJxgFNfmm4lzP3zlK41glyhWx8,1142
23
- python_plugins/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- python_plugins/models/update.py,sha256=cIwhR0iKkB7cVx7km_oA9ya97MSkJlLPb8pZWaEePmE,991
25
- python_plugins/models/mixins/__init__.py,sha256=l4dJVgUFI7aISA7X-CcVBOp19rXBgqyyhHwtuQnSgR0,241
26
- python_plugins/models/mixins/data_mixin.py,sha256=HCc1uvF6_O4yjK38uWAsqysEedLWgc7wtds3NjQTMZ8,366
27
- python_plugins/models/mixins/primary_key_mixin.py,sha256=QUO-7ZmYtAMMi7ReRQDYV0uwQCnU9dvl6g6GHitYtlA,154
28
- python_plugins/models/mixins/timestamp_mixin.py,sha256=u9rIu0IrzdCRRbnMk4IN4nTlNNiVPB8yPnTcHjQC1KU,547
29
- python_plugins/models/mixins/token_minxin.py,sha256=SxNftZXS-hCwqxov7whF_tBtlayuoi3LUPtu-ofMmdg,276
30
- python_plugins/models/mixins/user_minxin.py,sha256=D-N45bunicBuuwKs--s_tyDxxLC3mkxV9Tva8JAhsko,579
31
- python_plugins/ospath/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- python_plugins/ospath/walk_remove.py,sha256=rnDHr1wGSxufo2YV9_EXeVNEAnT4LGjG7-5dOI2gWY0,494
33
- python_plugins-1.0.2.dist-info/METADATA,sha256=KusHRGLBBQ9p_y9Ttu9q9Y1p_8WM_kBuPc1bSP8QgQk,2840
34
- python_plugins-1.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- python_plugins-1.0.2.dist-info/licenses/LICENSE.rst,sha256=X5eLIsAn1yAKd88LWTYkXUe0PmVK_Z5SD7_5NheGR-s,1104
36
- python_plugins-1.0.2.dist-info/RECORD,,
File without changes
File without changes
File without changes
File without changes
File without changes