python-plugins 1.0.2__py3-none-any.whl → 1.0.4__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 (30) hide show
  1. python_plugins/__about__.py +1 -1
  2. python_plugins/crypto/zip7mix.py +12 -2
  3. python_plugins/examples/sphinx_google_style.py +311 -0
  4. python_plugins/examples/sphinx_numpy_style.py +351 -0
  5. python_plugins/ospath/walk.py +31 -0
  6. python_plugins/sqla/__init__.py +3 -0
  7. python_plugins/sqla/db.py +97 -0
  8. python_plugins/sqla/orm.py +40 -0
  9. python_plugins/sqla/utils/__init__.py +10 -0
  10. python_plugins/sqla/utils/attr.py +85 -0
  11. python_plugins/sqla/utils/expression.py +9 -0
  12. python_plugins/sqla/utils/instance.py +12 -0
  13. python_plugins/sqla/utils/model.py +31 -0
  14. python_plugins/sqla/utils/paginate.py +74 -0
  15. python_plugins/sqla/utils/stmt.py +34 -0
  16. python_plugins/sqla/utils/update.py +23 -0
  17. {python_plugins-1.0.2.dist-info → python_plugins-1.0.4.dist-info}/METADATA +6 -12
  18. python_plugins-1.0.4.dist-info/RECORD +48 -0
  19. {python_plugins-1.0.2.dist-info → python_plugins-1.0.4.dist-info}/WHEEL +1 -1
  20. python_plugins/models/update.py +0 -33
  21. python_plugins/ospath/walk_remove.py +0 -19
  22. python_plugins-1.0.2.dist-info/RECORD +0 -36
  23. /python_plugins/{models → examples}/__init__.py +0 -0
  24. /python_plugins/{models → sqla}/mixins/__init__.py +0 -0
  25. /python_plugins/{models → sqla}/mixins/data_mixin.py +0 -0
  26. /python_plugins/{models → sqla}/mixins/primary_key_mixin.py +0 -0
  27. /python_plugins/{models → sqla}/mixins/timestamp_mixin.py +0 -0
  28. /python_plugins/{models → sqla}/mixins/token_minxin.py +0 -0
  29. /python_plugins/{models → sqla}/mixins/user_minxin.py +0 -0
  30. {python_plugins-1.0.2.dist-info → python_plugins-1.0.4.dist-info}/licenses/LICENSE.rst +0 -0
@@ -0,0 +1,31 @@
1
+ import os
2
+ import shutil
3
+
4
+
5
+ def remove(dir, dirname):
6
+ for root, dirs, files in os.walk(dir):
7
+ if "venv" in root or "git" in root:
8
+ continue
9
+ for dir in dirs:
10
+ if dir == dirname:
11
+ rm_path = os.path.join(root, dir)
12
+ print(f"Removing {rm_path}")
13
+ shutil.rmtree(rm_path)
14
+
15
+
16
+ def remove_pycache(dir="."):
17
+ remove(dir, "__pycache__")
18
+
19
+
20
+ def remove_ipynb_checkpoints(dir="."):
21
+ remove(dir, ".ipynb_checkpoints")
22
+
23
+
24
+ def find_empty_dirs(dir="."):
25
+ for root, dirs, files in os.walk(dir):
26
+ if "venv" in root or "git" in root:
27
+ continue
28
+ for dir in dirs:
29
+ dir_path = os.path.join(root, dir)
30
+ if not os.listdir(dir_path):
31
+ print(f"Empty dir: {dir_path}")
@@ -0,0 +1,3 @@
1
+ from .db import Db
2
+
3
+ db = Db()
@@ -0,0 +1,97 @@
1
+ from flask import Flask
2
+ from flask import current_app
3
+ from flask import has_request_context
4
+ from flask import g
5
+ from sqlalchemy import create_engine
6
+ from sqlalchemy.orm import sessionmaker
7
+ from sqlalchemy.orm import scoped_session
8
+ from sqlalchemy.orm import DeclarativeBase
9
+
10
+
11
+ class Db:
12
+ Model = None
13
+ engine = None
14
+ session = None
15
+ Session = None
16
+
17
+ def __init__(self, app: Flask | None = None):
18
+ self.Model = self._make_declarative_base()
19
+ if app is not None:
20
+ self.init_app(app)
21
+
22
+ def _make_declarative_base(self):
23
+ class Base(DeclarativeBase):
24
+ pass
25
+
26
+ return Base
27
+
28
+ def init_session(self, url=None, echo=False):
29
+ """Initialize the database engine and session factory.
30
+ This method is used in non-Flask environments.
31
+ Examples:
32
+ db = Db()
33
+ db.init_session(url="sqlite:///mydb.sqlite", echo=True)
34
+ db.create_all()
35
+ with db.Session() as session:
36
+ # use the session here
37
+ session.add(some_object)
38
+ session.commit()
39
+ """
40
+ options = {"url": url or "sqlite:///:memory:"}
41
+ if echo:
42
+ options["echo"] = True
43
+ self.engine = create_engine(**options)
44
+ self.Session = sessionmaker(self.engine)
45
+
46
+ def init_app(self, app: Flask) -> None:
47
+ if "sqlalchemy" in app.extensions:
48
+ raise RuntimeError("A 'SQLAlchemy' instance has already been registered.")
49
+ app.extensions["sqlalchemy"] = self
50
+
51
+ # engine
52
+ engine_options = {
53
+ "url": app.config.get("SQLALCHEMY_DATABASE_URI", "sqlite:///:memory:")
54
+ }
55
+ if app.config.get("SQLALCHEMY_ECHO"):
56
+ engine_options["echo"] = True
57
+ self.engine = self._make_engine(engine_options)
58
+
59
+ # session
60
+ session_options = {"bind": self.engine}
61
+ self.session = self._make_scoped_session(session_options)
62
+ app.teardown_appcontext(self._remove_session)
63
+
64
+ # cli
65
+ app.shell_context_processor(self._add_models_to_shell)
66
+
67
+ def _make_engine(self, options: dict):
68
+ return create_engine(**options)
69
+
70
+ def _make_scoped_session(self, options):
71
+ session_factory = sessionmaker(**options)
72
+ return scoped_session(session_factory, scopefunc=self._get_scope_id)
73
+
74
+ def _get_scope_id(self) -> int:
75
+ return id(g._get_current_object())
76
+
77
+ def _remove_session(self, exception=None):
78
+ """Remove the current session at the end of the request."""
79
+ self.session.remove()
80
+
81
+ def _add_models_to_shell(self):
82
+ """Registered with :meth:`~flask.Flask.shell_context_processor`.
83
+ Adds the ``db`` instance and all model classes to ``flask shell``.
84
+ """
85
+ db = current_app.extensions["sqlalchemy"]
86
+ out = {m.class_.__name__: m.class_ for m in db.Model.registry.mappers}
87
+ out["db"] = db
88
+ return out
89
+
90
+ def create_all(self, **kwargs):
91
+ if "bind" not in kwargs:
92
+ kwargs["bind"] = self.engine
93
+ self.Model.metadata.create_all(**kwargs)
94
+
95
+ def reset_models(self):
96
+ self.Model.metadata.drop_all(self.engine)
97
+ self.Model.metadata.create_all(self.engine)
@@ -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_property
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,85 @@
1
+ from typing import Tuple, List
2
+ from sqlalchemy import inspect
3
+ from sqlalchemy.orm import ColumnProperty
4
+ from sqlalchemy.orm import RelationshipProperty
5
+ from sqlalchemy.orm.attributes import InstrumentedAttribute
6
+ from sqlalchemy.ext.hybrid import hybrid_property
7
+ from sqlalchemy.ext.associationproxy import AssociationProxy
8
+
9
+
10
+ def is_instrumented_attribute(attr):
11
+ return isinstance(attr, InstrumentedAttribute)
12
+
13
+
14
+ def is_column(attr):
15
+ return hasattr(attr, "property") and isinstance(attr.property, ColumnProperty)
16
+
17
+
18
+ def is_relationship(attr):
19
+ return hasattr(attr, "property") and isinstance(attr.property, RelationshipProperty)
20
+
21
+
22
+ def is_hybrid_property(model, attr_name):
23
+ mapper = inspect(model)
24
+ descriptor = mapper.all_orm_descriptors.get(attr_name)
25
+ return isinstance(descriptor, hybrid_property)
26
+
27
+
28
+ def is_association_proxy(model, attr_name):
29
+ mapper = inspect(model)
30
+ descriptor = mapper.all_orm_descriptors.get(attr_name)
31
+ return isinstance(descriptor, AssociationProxy)
32
+
33
+
34
+ def get_field_with_path(
35
+ model, name: str
36
+ ) -> Tuple[InstrumentedAttribute, List[InstrumentedAttribute]]:
37
+ """
38
+ Resolve a dot-separated field path (e.g., 'profile.contact.email')
39
+ starting from `model`, handling columns and relationships.
40
+
41
+ Returns:
42
+ (final_attr, join_path)
43
+ - final_attr: The terminal InstrumentedAttribute (e.g., Contact.email)
44
+ - join_path: List of relationship attributes for explicit joins (e.g., [User.profile, Profile.contact])
45
+ """
46
+ final_attr = None
47
+ join_path: List[InstrumentedAttribute] = []
48
+
49
+ parts = name.split(".")
50
+ current_model = model
51
+ for i, part in enumerate(parts):
52
+ attr = getattr(current_model, part)
53
+ # Case 1: Column (must be last)
54
+ if is_column(attr):
55
+ if i != len(parts) - 1:
56
+ raise ValueError(
57
+ f"Column '{part}' cannot be followed by further path segments."
58
+ )
59
+ final_attr = attr
60
+ break
61
+ # Case 2: Relationship
62
+ elif is_relationship(attr):
63
+ join_path.append(attr)
64
+ current_model = attr.property.mapper.class_
65
+ # Case 3: AssociationProxy
66
+ elif is_association_proxy(current_model, part):
67
+ if i != len(parts) - 1:
68
+ raise ValueError(
69
+ f"AssociationProxy '{part}' cannot be followed by further path segments."
70
+ )
71
+ # Step into the underlying relationship
72
+ local_rel = attr.local_attr
73
+ join_path.append(local_rel)
74
+ remote_attr = attr.remote_attr
75
+ final_attr = remote_attr
76
+ break
77
+ else:
78
+ raise ValueError(
79
+ f"Unsupported attribute type for '{model}':'{part}': {type(attr)}"
80
+ )
81
+
82
+ if final_attr is None:
83
+ raise RuntimeError("Failed to resolve path — no terminal attribute found.")
84
+
85
+ return final_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,74 @@
1
+ from math import ceil
2
+ from typing import Any, Optional, Generic, TypeVar, Iterator
3
+ from sqlalchemy.sql import Select
4
+ from sqlalchemy.sql import select,func
5
+ from sqlalchemy.orm import Session
6
+
7
+ T = TypeVar("T")
8
+
9
+ class Pagination(Generic[T]):
10
+ def __init__(
11
+ self,
12
+ items: list[T],
13
+ total: int,
14
+ page: int,
15
+ per_page: int,
16
+ ):
17
+ self.items = items
18
+ self.total = total
19
+ self.page = page
20
+ self.per_page = per_page
21
+ self.pages = ceil(total / per_page) if per_page > 0 else 0
22
+ self.has_prev = page > 1
23
+ self.has_next = page < self.pages
24
+ self.prev_num = page - 1 if self.has_prev else None
25
+ self.next_num = page + 1 if self.has_next else None
26
+
27
+ def iter_pages(self) -> Iterator[int]:
28
+ """Iterate over page numbers for pagination controls."""
29
+ return iter(range(1, self.pages + 1))
30
+
31
+ def __repr__(self):
32
+ return f"<Pagination page={self.page} of {self.pages}>"
33
+
34
+ def paginate(
35
+ session: Session,
36
+ stmt: Select,
37
+ *,
38
+ page: int = 1,
39
+ per_page: int = 20,
40
+ ) -> Pagination:
41
+ """
42
+ Paginate a SQLAlchemy 2.0 select statement.
43
+
44
+ Args:
45
+ session: SQLAlchemy Session instance
46
+ stmt: A SQLAlchemy Select statement (e.g., select(User))
47
+ page: Current page number (1-indexed)
48
+ per_page: Number of items per page
49
+
50
+ Returns:
51
+ Pagination object with .items, .total, .has_next, etc.
52
+ """
53
+
54
+ # Count total rows
55
+ count_stmt = select(func.count()).select_from(stmt.subquery())
56
+ total = session.execute(count_stmt).scalar_one()
57
+
58
+ if total == 0:
59
+ return Pagination(items=[], total=0, page=page, per_page=per_page)
60
+
61
+ if page < 1:
62
+ # raise ValueError("Page must be >= 1")
63
+ page = 1
64
+
65
+ pages = ceil(total / per_page)
66
+ if page > pages:
67
+ # raise ValueError(f"Page {page} is out of range (total pages: {pages})")
68
+ page = pages
69
+
70
+ # Apply limit/offset
71
+ paginated_stmt = stmt.offset((page - 1) * per_page).limit(per_page)
72
+ items = session.execute(paginated_stmt).scalars().all()
73
+
74
+ return Pagination(items=items, total=total, page=page, per_page=per_page)
@@ -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.4
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,48 @@
1
+ python_plugins/__about__.py,sha256=acuR_XSJzp4OrQ5T8-Ac5gYe48mUwObuwjRmisFmZ7k,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/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ python_plugins/examples/datetime.py,sha256=bmC9d1W7XKA1ED9XO9reUiUyfQcM_BqGoGyOF21RW9A,282
15
+ python_plugins/examples/hashes.py,sha256=uSF3ohZRD7b2VAIvjjpTWC0SlY7QsFhsFZUejINrRGU,640
16
+ python_plugins/examples/higher_order_functions.py,sha256=vTfT3OEfuKkIW7UMD3JtreVDMeRbXHbjlz3G-j-J4x4,4574
17
+ python_plugins/examples/postgresql_dump.py,sha256=zN5aLYLxpon2y9_5gKizRjlrRUlkAO-dG-BuKpJ4F3U,1030
18
+ python_plugins/examples/pretty.py,sha256=igN4uq67AADcPOiy_h3_M-oEwgc1i3gJScbKtkf6d-k,211
19
+ python_plugins/examples/random_string.py,sha256=U7B-bAa4zEpewkd4_8KIPZ0XsPdbGlJ_FEj0FnTGdms,2210
20
+ python_plugins/examples/run_jwt.py,sha256=ZwjUXg5PKeophiXqwSaMlHrhwVKhHTsRb68HtkRLX8k,1485
21
+ python_plugins/examples/run_process.py,sha256=I_wjCqzWI6d39ebL-YArQ8LiXFQ3bwEoCnxJTZK1Zbc,780
22
+ python_plugins/examples/sphinx_google_style.py,sha256=TJuxBqXG3OtZHmlbLlCRD07ADs1QImOhZu33HksSgKM,9688
23
+ python_plugins/examples/sphinx_numpy_style.py,sha256=jhtOp7fiQcbtj-dUufloPQlV4vAKwlAlRgw8r6rxVgw,9735
24
+ python_plugins/examples/xml2dict.py,sha256=RUxqDt6NKzwbuodTxKVoiR4dP-vNbmL77dztLx_9UzY,164
25
+ python_plugins/examples/tkinter/calculate.py,sha256=M1b-w7-pVe-7FS3erBJxgFNfmm4lzP3zlK41glyhWx8,1142
26
+ python_plugins/ospath/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ python_plugins/ospath/walk.py,sha256=zj8616KtK4bduJyuyw2b7bg6udV_-ssEAGPLJblhPlM,792
28
+ python_plugins/sqla/__init__.py,sha256=dJyZS1js_pdpAgLnsqfRFPQBFeZ8PdssdPfTzgie5c8,30
29
+ python_plugins/sqla/db.py,sha256=rW0x7U0d3oqhZSL2GbxTEtyy83neGogt5VUNTnJadnA,3217
30
+ python_plugins/sqla/orm.py,sha256=7h0oY4TGfdrvAFKedVbKdWTvWHq_Sc-ycd2VvWiZJyo,1331
31
+ python_plugins/sqla/mixins/__init__.py,sha256=l4dJVgUFI7aISA7X-CcVBOp19rXBgqyyhHwtuQnSgR0,241
32
+ python_plugins/sqla/mixins/data_mixin.py,sha256=HCc1uvF6_O4yjK38uWAsqysEedLWgc7wtds3NjQTMZ8,366
33
+ python_plugins/sqla/mixins/primary_key_mixin.py,sha256=QUO-7ZmYtAMMi7ReRQDYV0uwQCnU9dvl6g6GHitYtlA,154
34
+ python_plugins/sqla/mixins/timestamp_mixin.py,sha256=u9rIu0IrzdCRRbnMk4IN4nTlNNiVPB8yPnTcHjQC1KU,547
35
+ python_plugins/sqla/mixins/token_minxin.py,sha256=SxNftZXS-hCwqxov7whF_tBtlayuoi3LUPtu-ofMmdg,276
36
+ python_plugins/sqla/mixins/user_minxin.py,sha256=D-N45bunicBuuwKs--s_tyDxxLC3mkxV9Tva8JAhsko,579
37
+ python_plugins/sqla/utils/__init__.py,sha256=sHrgAp1TJ3k02gbhMIf2or9IzI7in1P70PqqhFNhBUY,311
38
+ python_plugins/sqla/utils/attr.py,sha256=R6ehESBt3G-ukfczmqoKb9BiWdS0AC9uz2y0OZgzjQE,2947
39
+ python_plugins/sqla/utils/expression.py,sha256=_9P59Elc3jqdXFiXxkrRY9gsaUSum-chNMPbiqQcC58,202
40
+ python_plugins/sqla/utils/instance.py,sha256=EbcI3pQhsRj-mPW9ZHs0yQ4zMGVMHw-HtmmXHY15kK0,255
41
+ python_plugins/sqla/utils/model.py,sha256=R9ObqEMDOaYKLv8pcoDHoV7m4mxWHgEDiZ74NokMMjA,678
42
+ python_plugins/sqla/utils/paginate.py,sha256=Fqqb3N6HAdSD4OXvu62XgmIQp1eUAY0ODS4e3e_gtWQ,2186
43
+ python_plugins/sqla/utils/stmt.py,sha256=3GzzEvi0RmvE3q-zBweol9LmsEQ0UPkn9G6P0epNwWw,876
44
+ python_plugins/sqla/utils/update.py,sha256=jsTgivwzIeFSpbpFwb48_pTUNT-KM6TYnGv3wKH98HM,631
45
+ python_plugins-1.0.4.dist-info/METADATA,sha256=Cxs-TUoFEfTwbCNeYCtWxiH08_xQZVER8zz8g-5PH_c,2624
46
+ python_plugins-1.0.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
47
+ python_plugins-1.0.4.dist-info/licenses/LICENSE.rst,sha256=X5eLIsAn1yAKd88LWTYkXUe0PmVK_Z5SD7_5NheGR-s,1104
48
+ python_plugins-1.0.4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.29.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,19 +0,0 @@
1
- import os
2
- import shutil
3
-
4
- def remove(dir,rm_dir_name):
5
- for root, dirs, files in os.walk(dir):
6
- if "venv" in root or "git" in root:
7
- continue
8
- for dir in dirs:
9
- if dir == rm_dir_name:
10
- rm_path = os.path.join(root, dir)
11
- print(f"Removing {rm_path}")
12
- shutil.rmtree(rm_path)
13
-
14
- def remove_pycache(dir="."):
15
- remove(dir,"__pycache__")
16
-
17
- def remove_ipynb_checkpoints(dir="."):
18
- remove(dir,".ipynb_checkpoints")
19
-
@@ -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