about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py')
-rw-r--r--.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py185
1 files changed, 185 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py b/.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py
new file mode 100644
index 00000000..b7032b65
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sqlalchemy/ext/serializer.py
@@ -0,0 +1,185 @@
+# ext/serializer.py
+# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
+# <see AUTHORS file>
+#
+# This module is part of SQLAlchemy and is released under
+# the MIT License: https://www.opensource.org/licenses/mit-license.php
+# mypy: ignore-errors
+
+"""Serializer/Deserializer objects for usage with SQLAlchemy query structures,
+allowing "contextual" deserialization.
+
+.. legacy::
+
+    The serializer extension is **legacy** and should not be used for
+    new development.
+
+Any SQLAlchemy query structure, either based on sqlalchemy.sql.*
+or sqlalchemy.orm.* can be used.  The mappers, Tables, Columns, Session
+etc. which are referenced by the structure are not persisted in serialized
+form, but are instead re-associated with the query structure
+when it is deserialized.
+
+.. warning:: The serializer extension uses pickle to serialize and
+   deserialize objects, so the same security consideration mentioned
+   in the `python documentation
+   <https://docs.python.org/3/library/pickle.html>`_ apply.
+
+Usage is nearly the same as that of the standard Python pickle module::
+
+    from sqlalchemy.ext.serializer import loads, dumps
+
+    metadata = MetaData(bind=some_engine)
+    Session = scoped_session(sessionmaker())
+
+    # ... define mappers
+
+    query = (
+        Session.query(MyClass)
+        .filter(MyClass.somedata == "foo")
+        .order_by(MyClass.sortkey)
+    )
+
+    # pickle the query
+    serialized = dumps(query)
+
+    # unpickle.  Pass in metadata + scoped_session
+    query2 = loads(serialized, metadata, Session)
+
+    print(query2.all())
+
+Similar restrictions as when using raw pickle apply; mapped classes must be
+themselves be pickleable, meaning they are importable from a module-level
+namespace.
+
+The serializer module is only appropriate for query structures.  It is not
+needed for:
+
+* instances of user-defined classes.   These contain no references to engines,
+  sessions or expression constructs in the typical case and can be serialized
+  directly.
+
+* Table metadata that is to be loaded entirely from the serialized structure
+  (i.e. is not already declared in the application).   Regular
+  pickle.loads()/dumps() can be used to fully dump any ``MetaData`` object,
+  typically one which was reflected from an existing database at some previous
+  point in time.  The serializer module is specifically for the opposite case,
+  where the Table metadata is already present in memory.
+
+"""
+
+from io import BytesIO
+import pickle
+import re
+
+from .. import Column
+from .. import Table
+from ..engine import Engine
+from ..orm import class_mapper
+from ..orm.interfaces import MapperProperty
+from ..orm.mapper import Mapper
+from ..orm.session import Session
+from ..util import b64decode
+from ..util import b64encode
+
+
+__all__ = ["Serializer", "Deserializer", "dumps", "loads"]
+
+
+class Serializer(pickle.Pickler):
+
+    def persistent_id(self, obj):
+        # print "serializing:", repr(obj)
+        if isinstance(obj, Mapper) and not obj.non_primary:
+            id_ = "mapper:" + b64encode(pickle.dumps(obj.class_))
+        elif isinstance(obj, MapperProperty) and not obj.parent.non_primary:
+            id_ = (
+                "mapperprop:"
+                + b64encode(pickle.dumps(obj.parent.class_))
+                + ":"
+                + obj.key
+            )
+        elif isinstance(obj, Table):
+            if "parententity" in obj._annotations:
+                id_ = "mapper_selectable:" + b64encode(
+                    pickle.dumps(obj._annotations["parententity"].class_)
+                )
+            else:
+                id_ = f"table:{obj.key}"
+        elif isinstance(obj, Column) and isinstance(obj.table, Table):
+            id_ = f"column:{obj.table.key}:{obj.key}"
+        elif isinstance(obj, Session):
+            id_ = "session:"
+        elif isinstance(obj, Engine):
+            id_ = "engine:"
+        else:
+            return None
+        return id_
+
+
+our_ids = re.compile(
+    r"(mapperprop|mapper|mapper_selectable|table|column|"
+    r"session|attribute|engine):(.*)"
+)
+
+
+class Deserializer(pickle.Unpickler):
+
+    def __init__(self, file, metadata=None, scoped_session=None, engine=None):
+        super().__init__(file)
+        self.metadata = metadata
+        self.scoped_session = scoped_session
+        self.engine = engine
+
+    def get_engine(self):
+        if self.engine:
+            return self.engine
+        elif self.scoped_session and self.scoped_session().bind:
+            return self.scoped_session().bind
+        else:
+            return None
+
+    def persistent_load(self, id_):
+        m = our_ids.match(str(id_))
+        if not m:
+            return None
+        else:
+            type_, args = m.group(1, 2)
+            if type_ == "attribute":
+                key, clsarg = args.split(":")
+                cls = pickle.loads(b64decode(clsarg))
+                return getattr(cls, key)
+            elif type_ == "mapper":
+                cls = pickle.loads(b64decode(args))
+                return class_mapper(cls)
+            elif type_ == "mapper_selectable":
+                cls = pickle.loads(b64decode(args))
+                return class_mapper(cls).__clause_element__()
+            elif type_ == "mapperprop":
+                mapper, keyname = args.split(":")
+                cls = pickle.loads(b64decode(mapper))
+                return class_mapper(cls).attrs[keyname]
+            elif type_ == "table":
+                return self.metadata.tables[args]
+            elif type_ == "column":
+                table, colname = args.split(":")
+                return self.metadata.tables[table].c[colname]
+            elif type_ == "session":
+                return self.scoped_session()
+            elif type_ == "engine":
+                return self.get_engine()
+            else:
+                raise Exception("Unknown token: %s" % type_)
+
+
+def dumps(obj, protocol=pickle.HIGHEST_PROTOCOL):
+    buf = BytesIO()
+    pickler = Serializer(buf, protocol)
+    pickler.dump(obj)
+    return buf.getvalue()
+
+
+def loads(data, metadata=None, scoped_session=None, engine=None):
+    buf = BytesIO(data)
+    unpickler = Deserializer(buf, metadata, scoped_session, engine)
+    return unpickler.load()