import datetime import warnings from typing import List, Union from sqlalchemy import event from sqlalchemy.sql import Join from sqlalchemy.orm.session import object_session from dbsync import core from dbsync.models import Operation, Version, SQLClass, call_after_tracking_fn, call_before_tracking_fn, SkipOperation from dbsync.logs import get_logger from dbsync.createlogger import create_logger from logging import DEBUG logger = create_logger("dbsync.server.tracking") logger.level = DEBUG if core.mode == 'client': warnings.warn("don't import both server and client") core.mode = 'server' def make_listener(command: str): """Builds a listener for the given command (i, u, d).""" @core.session_committing def listener(mapper, connection, target, session=None) -> None: logger.info(f"tracking {target}") if getattr(core.SessionClass.object_session(target), core.INTERNAL_SESSION_ATTR, False): logger.debug(f"internal session object not tracked: {target}")
from dbsync.client.wsclient import SyncClient from dbsync.core import with_transaction_async from dbsync.createlogger import create_logger from dbsync.messages.push import PushMessage from dbsync.models import Node, Operation, Version from dbsync.server.wsserver import SyncServer from dbsync.socketclient import GenericWSClient from dbsync.socketserver import Connection from tests.models_websockets import SERVER_URL, addstuff, changestuff, A, B, datapath, deletestuff from .models_websockets import PORT from .server_setup import sync_server, server_session, server_db from .client_setup import sync_client, client_session, sync_client_registered, client_db, create_sync_client_registered, \ create_client_session logger = create_logger("dbsync.tests") @SyncServer.handler("/counter") async def counter(conn: Connection): n = int(await conn.socket.recv()) for i in range(n): await conn.socket.send(str(i)) @SyncServer.handler("/fuckup") async def fuckup(conn: Connection): """ provoke an exception """
from dbsync.messages.push import PushMessage from dbsync.models import OperationError, Version, Operation, attr, SQLClass, call_after_tracking_fn from dbsync.server import before_push, after_push from dbsync.server.conflicts import find_unique_conflicts from dbsync.server.handlers import PullRejected from dbsync.socketserver import GenericWSServer, Connection import sqlalchemy as sa from sqlalchemy.engine import Engine from dbsync.createlogger import create_logger from sqlalchemy.orm import sessionmaker, make_transient from dbsync.utils import get_pk, properties_dict import logging logger = create_logger("dbsync-server") class SyncServerConnection(Connection): ... async def send_field_payload(connection: Connection, msg: Dict[str, Any]): from ..models import get_model_extensions_for_obj session = connection.server.Session() logger.debug(f"send_field_payload:{msg}") # breakpoint() module = importlib.import_module(msg['package_name']) klass = getattr(module, msg['class_name']) pkname = msg['id_field'] obj = session.query(klass).filter(
from typing import List, Dict, Any, Optional from dbsync.createlogger import create_logger from dbsync.dialects import GUID from sqlalchemy import types from dbsync.utils import (properties_dict, object_from_dict, get_pk, parent_objects, query_model) from dbsync.lang import * from dbsync.core import (MAX_SQL_VARIABLES, session_closing, synched_models, pushed_models) from dbsync.models import Node, Operation, SQLClass from dbsync.messages.base import MessageQuery, BaseMessage from dbsync.messages.codecs import encode, encode_dict, decode, decode_dict logger = create_logger("messages.push") class PushMessage(BaseMessage): """ A push message. A push message contains the latest version information, the node information, and the list of unversioned operations and the required objects for those to be performed. The message can be instantiated from a raw data dictionary or can be made empty and filled later with the ``add_unversioned_operations`` method, in which case the node attribute and the latest version identifier should be assigned explicitly as well. The method ``set_node`` is required to be used
from dbsync.models import Operation from dbsync import dialects from dbsync.messages.pull import PullMessage, PullRequestMessage from dbsync.client.compression import compress, compressed_operations from dbsync.client.conflicts import ( get_related_tables, get_fks, find_direct_conflicts, find_dependency_conflicts, find_reversed_dependency_conflicts, find_insert_conflicts, find_unique_conflicts) from dbsync.client.net import post_request logger = create_logger("client/pull") # Utilities specific to the merge def max_local(model, session): """ Returns the maximum value for the primary key of the given model in the local database. """ if model is None: raise ValueError("null model given to max_local query") return dialects.max_local(model, session) def max_remote(model, container): """ Returns the maximum value for the primary key of the given model
.. __: http://essay.utwente.nl/61767/1/Master_thesis_Jan-Henk_Gerritsen.pdf """ from sqlalchemy import or_ from sqlalchemy.orm import undefer from sqlalchemy.schema import UniqueConstraint from sqlalchemy.sql import Join from dbsync.lang import * from dbsync.utils import get_pk, class_mapper, query_model, column_properties, entity_name from dbsync.core import synched_models, null_model from dbsync.models import Operation from dbsync.createlogger import create_logger logger = create_logger("dbsync.client.conflicts") def get_related_tables(sa_class): """ Returns a list of related SA tables dependent on the given SA model by foreign key. """ mapper = class_mapper(sa_class) models = iter(list(synched_models.models.keys())) return [ table for table in ( class_mapper(model).mapped_table for model in models
from dbsync.messages.pull import PullRequestMessage, PullMessage from dbsync.messages.push import PushMessage from dbsync.messages.register import RegisterMessage from dbsync.models import Node, get_model_extensions_for_obj, Version, Operation from dbsync.socketclient import GenericWSClient from sqlalchemy.engine import Engine from sqlalchemy.orm import sessionmaker from dbsync.wscommon import SerializationError wscommon.register_exception(PushRejected) wscommon.register_exception(PullSuggested) from logging import DEBUG import logging logger = create_logger("wsclient") logger.level = DEBUG @dataclass class SyncClient(GenericWSClient): engine: Optional[Engine] = None Session: Optional[sessionmaker] = None id: int = -1 elapsed_rounds = 0 def __post_init__(self): if not self.Session: self.engine = core.get_engine() self.Session = lambda: core.SessionClass(
from dbsync.createlogger import create_logger from dbsync.models import Operation, SQLClass, add_field_extension, ExtensionField, extend_model, SkipOperation from dbsync.server.wsserver import SyncServer from sqlalchemy import Column, Integer, String, ForeignKey, create_engine from sqlalchemy.orm import relationship, sessionmaker, Session from sqlalchemy.ext.declarative import declarative_base from dbsync.dialects import GUID from dbsync.utils import generate_secret import dbsync from dbsync import client, models, core, server server_db = "./test_server.db" server_uri_postgres = 'postgresql:///synctest' logger = create_logger("models_websockets") def client_db(pid=None): if pid is None: pid = os.getpid() return f"./test_client_{pid}.db" PORT = 7081 SERVER_URL = f"ws://localhost:{PORT}/" Base = declarative_base() def datapath(fname="", mode=None, pid=""):