instructure-pysqlsync 0.8.5.dev0__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 (102) hide show
  1. instructure_pysqlsync-0.8.5.dev0.dist-info/METADATA +244 -0
  2. instructure_pysqlsync-0.8.5.dev0.dist-info/RECORD +102 -0
  3. instructure_pysqlsync-0.8.5.dev0.dist-info/WHEEL +5 -0
  4. instructure_pysqlsync-0.8.5.dev0.dist-info/licenses/LICENSE +21 -0
  5. instructure_pysqlsync-0.8.5.dev0.dist-info/top_level.txt +1 -0
  6. instructure_pysqlsync-0.8.5.dev0.dist-info/zip-safe +1 -0
  7. pysqlsync/__init__.py +15 -0
  8. pysqlsync/base.py +1386 -0
  9. pysqlsync/connection.py +101 -0
  10. pysqlsync/data/__init__.py +0 -0
  11. pysqlsync/data/exchange.py +184 -0
  12. pysqlsync/data/generator.py +305 -0
  13. pysqlsync/dialect/README.md +35 -0
  14. pysqlsync/dialect/__init__.py +0 -0
  15. pysqlsync/dialect/delta/__init__.py +0 -0
  16. pysqlsync/dialect/delta/data_types.py +51 -0
  17. pysqlsync/dialect/delta/dependency.py +7 -0
  18. pysqlsync/dialect/delta/engine.py +18 -0
  19. pysqlsync/dialect/delta/generator.py +74 -0
  20. pysqlsync/dialect/delta/object_types.py +87 -0
  21. pysqlsync/dialect/mssql/README.md +23 -0
  22. pysqlsync/dialect/mssql/__init__.py +0 -0
  23. pysqlsync/dialect/mssql/connection.py +146 -0
  24. pysqlsync/dialect/mssql/data_types.py +113 -0
  25. pysqlsync/dialect/mssql/dependency.py +9 -0
  26. pysqlsync/dialect/mssql/discovery.py +99 -0
  27. pysqlsync/dialect/mssql/engine.py +20 -0
  28. pysqlsync/dialect/mssql/generator.py +88 -0
  29. pysqlsync/dialect/mssql/mutation.py +46 -0
  30. pysqlsync/dialect/mssql/object_types.py +135 -0
  31. pysqlsync/dialect/mysql/__init__.py +0 -0
  32. pysqlsync/dialect/mysql/connection.py +126 -0
  33. pysqlsync/dialect/mysql/data_types.py +40 -0
  34. pysqlsync/dialect/mysql/dependency.py +10 -0
  35. pysqlsync/dialect/mysql/discovery.py +145 -0
  36. pysqlsync/dialect/mysql/engine.py +20 -0
  37. pysqlsync/dialect/mysql/generator.py +140 -0
  38. pysqlsync/dialect/mysql/mutation.py +65 -0
  39. pysqlsync/dialect/mysql/object_types.py +75 -0
  40. pysqlsync/dialect/oracle/README.md +22 -0
  41. pysqlsync/dialect/oracle/__init__.py +0 -0
  42. pysqlsync/dialect/oracle/connection.py +141 -0
  43. pysqlsync/dialect/oracle/data_types.py +104 -0
  44. pysqlsync/dialect/oracle/dependency.py +9 -0
  45. pysqlsync/dialect/oracle/discovery.py +231 -0
  46. pysqlsync/dialect/oracle/engine.py +20 -0
  47. pysqlsync/dialect/oracle/generator.py +93 -0
  48. pysqlsync/dialect/oracle/mutation.py +37 -0
  49. pysqlsync/dialect/oracle/object_types.py +59 -0
  50. pysqlsync/dialect/postgresql/__init__.py +0 -0
  51. pysqlsync/dialect/postgresql/connection.py +133 -0
  52. pysqlsync/dialect/postgresql/data_types.py +6 -0
  53. pysqlsync/dialect/postgresql/dependency.py +9 -0
  54. pysqlsync/dialect/postgresql/discovery.py +392 -0
  55. pysqlsync/dialect/postgresql/engine.py +20 -0
  56. pysqlsync/dialect/postgresql/generator.py +99 -0
  57. pysqlsync/dialect/postgresql/mutation.py +82 -0
  58. pysqlsync/dialect/postgresql/object_types.py +99 -0
  59. pysqlsync/dialect/redshift/__init__.py +0 -0
  60. pysqlsync/dialect/redshift/connection.py +156 -0
  61. pysqlsync/dialect/redshift/data_types.py +10 -0
  62. pysqlsync/dialect/redshift/dependency.py +9 -0
  63. pysqlsync/dialect/redshift/engine.py +20 -0
  64. pysqlsync/dialect/redshift/generator.py +82 -0
  65. pysqlsync/dialect/snowflake/__init__.py +0 -0
  66. pysqlsync/dialect/snowflake/data_types.py +18 -0
  67. pysqlsync/dialect/snowflake/dependency.py +9 -0
  68. pysqlsync/dialect/snowflake/engine.py +18 -0
  69. pysqlsync/dialect/snowflake/generator.py +64 -0
  70. pysqlsync/dialect/snowflake/object_types.py +84 -0
  71. pysqlsync/dialect/test/__init__.py +0 -0
  72. pysqlsync/dialect/test/dependency.py +10 -0
  73. pysqlsync/dialect/trino/__init__.py +0 -0
  74. pysqlsync/dialect/trino/connection.py +86 -0
  75. pysqlsync/dialect/trino/dependency.py +9 -0
  76. pysqlsync/dialect/trino/discovery.py +21 -0
  77. pysqlsync/dialect/trino/engine.py +20 -0
  78. pysqlsync/dialect/trino/generator.py +31 -0
  79. pysqlsync/factory.py +169 -0
  80. pysqlsync/formation/__init__.py +0 -0
  81. pysqlsync/formation/constraints.py +78 -0
  82. pysqlsync/formation/data_types.py +192 -0
  83. pysqlsync/formation/discovery.py +390 -0
  84. pysqlsync/formation/inspection.py +179 -0
  85. pysqlsync/formation/mutation.py +320 -0
  86. pysqlsync/formation/object_dict.py +79 -0
  87. pysqlsync/formation/object_types.py +872 -0
  88. pysqlsync/formation/py_to_sql.py +1134 -0
  89. pysqlsync/formation/sql_to_py.py +194 -0
  90. pysqlsync/model/__init__.py +0 -0
  91. pysqlsync/model/data_types.py +397 -0
  92. pysqlsync/model/entity_types.py +68 -0
  93. pysqlsync/model/id_types.py +193 -0
  94. pysqlsync/model/key_types.py +38 -0
  95. pysqlsync/model/properties.py +234 -0
  96. pysqlsync/py.typed +0 -0
  97. pysqlsync/python_types.py +192 -0
  98. pysqlsync/resultset.py +106 -0
  99. pysqlsync/util/__init__.py +0 -0
  100. pysqlsync/util/dataclasses.py +80 -0
  101. pysqlsync/util/dispatch.py +28 -0
  102. pysqlsync/util/typing.py +13 -0
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: instructure-pysqlsync
3
+ Version: 0.8.5.dev0
4
+ Summary: Synchronize schema and large volumes of data
5
+ Author-email: "Instructure, Inc." <dapclient@instructure.com>
6
+ Maintainer-email: "Instructure, Inc." <dapclient@instructure.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/instructure-internal/pysqlsync
9
+ Project-URL: Source, https://github.com/instructure-internal/pysqlsync
10
+ Keywords: synchronization,sql-schema,sql-query,sql-insert,database-clients
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Topic :: Database :: Database Engines/Servers
23
+ Classifier: Topic :: Software Development :: Code Generators
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: json_strong_typing>=0.4.2
30
+ Requires-Dist: certifi>=2025.11.12; python_version < "3.10"
31
+ Requires-Dist: truststore>=0.10; python_version >= "3.10"
32
+ Requires-Dist: typing_extensions>=4.15; python_version < "3.12"
33
+ Provides-Extra: tsv
34
+ Requires-Dist: tsv2py>=0.7; extra == "tsv"
35
+ Provides-Extra: postgresql
36
+ Requires-Dist: asyncpg>=0.30; extra == "postgresql"
37
+ Provides-Extra: oracle
38
+ Requires-Dist: oracledb>=3.4; extra == "oracle"
39
+ Provides-Extra: mysql
40
+ Requires-Dist: aiomysql>=0.3; extra == "mysql"
41
+ Requires-Dist: PyMySQL[rsa]>=1.1; extra == "mysql"
42
+ Provides-Extra: mssql
43
+ Requires-Dist: pyodbc>=5.3; extra == "mssql"
44
+ Provides-Extra: snowflake
45
+ Requires-Dist: snowflake-connector-python>=3.18; extra == "snowflake"
46
+ Provides-Extra: trino
47
+ Requires-Dist: aiotrino>=0.3; extra == "trino"
48
+ Dynamic: license-file
49
+
50
+ # pysqlsync: Synchronize schema and large volumes of data over SQL
51
+
52
+ *pysqlsync* helps you synchronize your target database or data warehouse with a data source, making efficient use of Python language elements and database drivers (client libraries). The library package employs Python data-classes (decorated with `@dataclass`) to define database tables and generate `CREATE`, `DROP`, `INSERT`, `MERGE` and `DELETE` SQL statements. Commands against the database driver are executed with the asynchronous paradigm (`async` and `await`). This can result in an order of magnitude speed increase over traditional methods such as SQLAlchemy when data is inserted or upserted (merged) into, or deleted from a table.
53
+
54
+ ## Use cases
55
+
56
+ * Formation. Create an initializer SQL script (e.g. ANSI, PostgreSQL or MySQL) from a set of Python `@dataclass` definitions.
57
+ * Discovery. Create a traversable Python object hierarchy (e.g. `Namespace`, `Table`, `Column` and `Constraint` objects) from a database catalog (using `information_schema` or `pg_catalog`).
58
+ * Schema synchronization. Emit SQL statements to mutate the database schema from a source state to a desired target state using `CREATE`, `DROP` and `ALTER`.
59
+ * Data import. Efficiently insert data from a list of objects or tuples of simple types into a database table using `INSERT`, `MERGE` and `DELETE` with multiple arguments, and lists of tuples or collections of objects as input.
60
+
61
+ ## Quick start
62
+
63
+ First, define the table structure with a standard Python data-class (including dependent data types):
64
+
65
+ <!-- Example 1 -->
66
+ ```python
67
+ class WorkflowState(enum.Enum):
68
+ active = "active"
69
+ inactive = "inactive"
70
+ deleted = "deleted"
71
+
72
+
73
+ @dataclasses.dataclass
74
+ class UserTable:
75
+ id: PrimaryKey[int]
76
+ updated_at: datetime
77
+ workflow_state: WorkflowState
78
+ uuid: uuid.UUID
79
+ name: str
80
+ short_name: Annotated[str, MaxLength(255)]
81
+ homepage_url: Optional[str] = None
82
+ ```
83
+
84
+ The data-class can be defined statically in code, or generated dynamically from input (with `dataclasses.make_dataclass`). Fields can be required or nullable (represented in Python as `None`). All basic data types are supported, including integers (of various widths), floating-point numbers, strings (of fixed or variable length), timestamps (`datetime.datetime` in Python), UUIDs (`uuid.UUID` in Python), enumerations (represented in Python as `enum.Enum`), etc. `list[...]` is supported as a collection type, and composite types (data-classes without a primary key) are also permitted.
85
+
86
+ Next, instantiate a database engine, open a connection, create the database structure (with a `CREATE TABLE` statement), and populate the database with initial data (with SQL `INSERT` or `COPY`):
87
+
88
+ <!-- Example 2 -->
89
+ ```python
90
+ engine = get_dialect("postgresql")
91
+ parameters = ConnectionParameters(
92
+ host="localhost",
93
+ port=5432,
94
+ username="user.name",
95
+ password=None,
96
+ database="database.name",
97
+ )
98
+ options = GeneratorOptions(
99
+ enum_mode=EnumMode.RELATION, namespaces={tables: "example"}
100
+ )
101
+
102
+ data = [
103
+ UserTable(
104
+ id=1,
105
+ updated_at=datetime.now(),
106
+ workflow_state=WorkflowState.active,
107
+ uuid=uuid.uuid4(),
108
+ name="Laura Twenty-Four",
109
+ short_name="Laura",
110
+ )
111
+ ]
112
+ async with engine.create_connection(parameters, options) as conn:
113
+ await conn.create_objects([UserTable])
114
+ await conn.insert_data(UserTable, data)
115
+ ```
116
+
117
+ Let's assume the database structure changes. With the help of an `Explorer` instance, discover the objects in the database, and create/drop objects to match the state as captured in the specified Python module:
118
+
119
+ <!-- Example 3 -->
120
+ ```python
121
+ async with engine.create_connection(parameters, options) as conn:
122
+ await engine.create_explorer(conn).synchronize(module=tables)
123
+ ```
124
+
125
+ Finally, keep the target database content synchronized with data from the source (with the equivalent of SQL `MERGE`):
126
+
127
+ <!-- Example 4 -->
128
+ ```python
129
+ data = [
130
+ UserTable(
131
+ id=2,
132
+ updated_at=datetime.now(),
133
+ workflow_state=WorkflowState.active,
134
+ uuid=uuid.uuid4(),
135
+ name="Zeta Twelve",
136
+ short_name="Zeta",
137
+ )
138
+ ]
139
+ async with engine.create_connection(parameters, options) as conn:
140
+ await engine.create_explorer(conn).synchronize(module=tables)
141
+ await conn.upsert_data(UserTable, data)
142
+ ```
143
+
144
+ In order to boost efficiency, you can insert (or update) data directly from a list of tuples:
145
+
146
+ <!-- Example 5 -->
147
+ ```python
148
+ field_names = ["id", "uuid", "name", "short_name", "workflow_state", "updated_at"]
149
+ field_types = [int, uuid.UUID, str, str, str, datetime]
150
+ rows = [
151
+ (1, uuid.uuid4(), "Laura Twenty-Four", "Laura", "active", datetime.now()),
152
+ (2, uuid.uuid4(), "Zeta Twelve", "Zeta", "inactive", datetime.now()),
153
+ ]
154
+ async with engine.create_connection(parameters, options) as conn:
155
+ await engine.create_explorer(conn).synchronize(module=tables)
156
+ table = conn.get_table(UserTable)
157
+ await conn.upsert_rows(
158
+ table,
159
+ field_names=tuple(field_names),
160
+ field_types=tuple(field_types),
161
+ records=rows,
162
+ )
163
+ ```
164
+
165
+ ## Structure and data synchronization
166
+
167
+ *pysqlsync* supports two modes of operation: structure synchronization and data synchronization.
168
+
169
+ When performing *structure synchronization*, *pysqlsync* morphs a database source state into a desired target state. The source state is typically obtained with reflection (e.g. extracting metadata from `information_schema` or `pg_catalog`). The target state is defined as a set of Python data-classes either statically or dynamically (e.g. based on a [JSON Schema](https://json-schema.org/)). Comparing source and target state, *pysqlsync* creates a transformation script (predominantly ANSI SQL with vendor-specific extensions such as comments), and runs the script against an asynchronous client such as `asyncpg` or `aiomysql`. This script creates new schemas, structure and enumeration types, tables, columns, constraints, etc. whenever the target state contains items that the source state lacks, and drops database objects when the opposite is true. When there are matching objects (based on qualified name), the object is mutated (e.g. the data type of a column is changed).
170
+
171
+ Once database structure has been morphed into the desired state, *data synchronization* helps keep a local database state in sync with a remote database state. *pysqlsync* implements insert and upsert functions to handle lists of tuples of data. Each tuple corresponds to a table row, and each tuple member is a column entry. Data in each column may have to be transformed to be suitable for the database dialect, e.g. MySQL would have to transform a `UUID` into a `BINARY(16)`, represented in Python as `bytes` because it has no `uuid` type. These transformation functions are derived in advance such that there is minimum CPU load to process a record (one of possibly billions). Loading data from network/disk to memory may use an efficient parser implementation such as tsv2py, which significantly speeds up parse time for composite types such as `datetime` or `UUID` with the help of SIMD CPU instructions.
172
+
173
+ ## Formation
174
+
175
+ Formation is the process of generating a series of SQL statements from a collection of Python data-class definitions. Several formation modes are supported.
176
+
177
+ ### Enumerations
178
+
179
+ `EnumMode` determines how Python enumeration types (subclasses of `enum.Enum`) are converted into database object types. Possible options for the target of an enumeration type are:
180
+
181
+ * a SQL `ENUM` type created with `CREATE TYPE ... AS ENUM ( ... )` (PostgreSQL), or
182
+ * an inline SQL `ENUM` definition, e.g. `ENUM('a', 'b', 'c')` (MySQL and Oracle), or
183
+ * a SQL data type corresponding to the enumeration value type, and a `CHECK` constraint on the column to block invalid values, or
184
+ * a foreign/primary key relation (reference constraint), coupled with a lookup table, in which the lookup table consists of an identity column acting as the primary key and a unique column storing the enumeration values.
185
+
186
+ Extensible enumerations (declared with `E | str` or `E | str | None` where `E` is a subclasses of `enum.Enum`) are always expanded into a relation (i.e. separate table) regardless of `EnumMode`.
187
+
188
+ ### Data-classes
189
+
190
+ `StructMode` determines how to convert composite types that are not mapped into SQL tables. A data-class type may be converted into
191
+
192
+ * a composite SQL type with `CREATE TYPE ... AS ( ... )` (PostgreSQL), or
193
+ * the SQL `json` type (PostgreSQL), or
194
+ * a text type, e.g. `varchar`, which holds the data as serialized JSON.
195
+
196
+ ### Lists
197
+
198
+ `ArrayMode` determines how to treat sequence types, such as Python lists, i.e. whether to represent them as
199
+
200
+ * a SQL `array` type (PostgreSQL), or
201
+ * a JSON array stored in a column with the SQL data type `json` (PostgreSQL), or
202
+ * a serialized JSON string stored in a text column type, e.g. `varchar`.
203
+
204
+ ### Modules
205
+
206
+ `GeneratorOptions` allows you to pass a mapping between module types and SQL schema identifiers. Objects in each Python module would be transformed into SQL objects in the corresponding SQL schema (namespace).
207
+
208
+ ## Database standard and engine support
209
+
210
+ * PostgreSQL (with [asyncpg](https://magicstack.github.io/asyncpg/))
211
+ * Microsoft SQL Server (with [pyodbc](https://github.com/mkleehammer/pyodbc/wiki), requires [ODBC Driver 18](https://learn.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server) or later)
212
+ * Oracle (with [oracledb](https://python-oracledb.readthedocs.io/))
213
+ * MySQL (with [aiomysql](https://aiomysql.readthedocs.io/))
214
+
215
+ When calling `str()` on Python objects such as `Table`, `Column` or `Constraint`, the library returns an ANSI-compliant representation.
216
+
217
+ ## Python classes for database objects
218
+
219
+ *pysqlsync* features several Python classes that correspond to database objects:
220
+
221
+ * `Catalog` captures a database state of possibly several namespaces.
222
+ * `Namespace` corresponds to a database schema in engines that feature schemas (e.g. PostgreSQL).
223
+ * `Table` represents a database table with a primary key, several columns and constraints.
224
+ * `Column` objects declare data type and nullability, and a possibly hold a default value.
225
+ * `StructType` and `StructMember` represent composite types in engines that support them (e.g. PostgreSQL).
226
+ * `EnumType` captures enumeration types for engines that represent them as their own type (e.g. PostgreSQL).
227
+
228
+ The collection of database objects represents a current structure, which may morph into a target structure. Some of the objects may be vendor-specific, e.g. MySQL has its own `MySQLColumn` type and PostgreSQL has its own `PostgreSQLTable` type.
229
+
230
+ All objects are identified either with a local ID (e.g. namespaces and columns) or a qualified ID (e.g. tables). When the database engine lacks namespace support, qualified IDs map to a prefix, e.g. `canvas.accounts` (table `accounts` in namespace `canvas`) becomes `canvas__accounts` (a table with no namespace).
231
+
232
+ ## Dialects
233
+
234
+ pysqlsync comes with several database dialects shipped with the library. However, it is possible to create and register new dialects that behave the same way as built-in dialects. In terms of capabilities, there are no differences between built-in and user-defined dialects.
235
+
236
+ If you are about to write integration for a new database dialect, it is recommended that you take one of the existing dialects (e.g. PostgreSQL, Microsoft SQL Server, Oracle or MySQL), and use it as a template. For more information, explore the folder `pysqlsync/dialect`.
237
+
238
+ ## Upstream
239
+
240
+ This is an internal fork of [hunyadi/pysqlsync](https://github.com/hunyadi/pysqlsync). To track upstream changes, add the original repository as a remote:
241
+
242
+ ```sh
243
+ git remote add hunyadi git@github.com:hunyadi/pysqlsync.git
244
+ ```
@@ -0,0 +1,102 @@
1
+ instructure_pysqlsync-0.8.5.dev0.dist-info/licenses/LICENSE,sha256=xSBMIQHJdUgGKSlJVCOFBtPAhszPF6ALKw-57ap98dg,1101
2
+ pysqlsync/__init__.py,sha256=rpfC54e7Urif20RCNZkMJ8nTYz2IsMSLVmWWKrJyUW8,531
3
+ pysqlsync/base.py,sha256=5wrM7oL_AOjAHmxsbo0yDZMmT-6JWBnltU30C6us1rU,51669
4
+ pysqlsync/connection.py,sha256=kl_JSHGJBnEr9E-7IW6lXQaA3XyRBlE0-NWBBaXGlPU,3559
5
+ pysqlsync/factory.py,sha256=E20P7pXuuzcXsf_ZOumnL-Z-FSRraD8GnQLzRCeE8L0,5752
6
+ pysqlsync/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ pysqlsync/python_types.py,sha256=WTKqyR6YW4XaKdNHBAdDUMjWcqLaP-ImoPD9hIUkBWQ,6378
8
+ pysqlsync/resultset.py,sha256=GWhrbkgxX4EMmLMBddijziKW5BXX51ONj_QW3TlQrCQ,3623
9
+ pysqlsync/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pysqlsync/data/exchange.py,sha256=kdk48CwIxTjbL_ZPLs4-fj8Shs9VUNGRB08pb6HimT8,5838
11
+ pysqlsync/data/generator.py,sha256=Fn_B7rVlbaYHyiuJeWiQ548EDW2Kes9xJLjMLt5AIAU,10880
12
+ pysqlsync/dialect/README.md,sha256=3eI3Dzz6A_TJgxJOzEmsdf-WrDsezZZf7TrjSK-wYD8,5085
13
+ pysqlsync/dialect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ pysqlsync/dialect/delta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ pysqlsync/dialect/delta/data_types.py,sha256=w9_T3F-UgeXxGJC37EGFaMvVLLs45FgMq9bsFJ3vZk4,999
16
+ pysqlsync/dialect/delta/dependency.py,sha256=RRFd0-afoU-0e2QclMA-n_KxjkujWW1xS2XPjr2rbbw,195
17
+ pysqlsync/dialect/delta/engine.py,sha256=jeETbyhKzqlAazepJGGFhmfFzK29tLSdBqQJa8BIOMs,487
18
+ pysqlsync/dialect/delta/generator.py,sha256=34E4MMD-flXz6R2GojuvUqJjrN5PapvjKuseRXTMT3E,2469
19
+ pysqlsync/dialect/delta/object_types.py,sha256=jrZVYgHWpHNhGyXK85e4AEtR3zR0b_2emC2NHDPSQZE,2585
20
+ pysqlsync/dialect/mssql/README.md,sha256=xGJSdV_K4m8F6SWnyCQw2QPvUUEyzJrQ1G5nshs8wMw,789
21
+ pysqlsync/dialect/mssql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ pysqlsync/dialect/mssql/connection.py,sha256=7tKlD6EoUaqurFreaNuqrJ09lBYyNlmEh3zBP56Fs74,5213
23
+ pysqlsync/dialect/mssql/data_types.py,sha256=ADFzn49IR82h_46CjF9yCg-MU6y5N0ZZCdRXtn8FVnQ,3522
24
+ pysqlsync/dialect/mssql/dependency.py,sha256=wBzhjUWTYvbC4gKdSdCe_8ePf1ds3SYwdryFK4DXJPY,258
25
+ pysqlsync/dialect/mssql/discovery.py,sha256=hFcGp01RNAbFxIzLZPhaDyLkHc9w2KKepWkJjfgiOo8,4293
26
+ pysqlsync/dialect/mssql/engine.py,sha256=Zcz8Bd3XO3oMhhm6i8D6AGCjHQWohh96vlMKrJKEQ1k,552
27
+ pysqlsync/dialect/mssql/generator.py,sha256=2SajU-FhuvJ8Gs_ehk5_XL13V6OfcMmEvNQb081qyrU,3370
28
+ pysqlsync/dialect/mssql/mutation.py,sha256=nJU2uRxw0zsUt5PIXVPIhB9zvu-QJgv9R4x8v8VQpXY,1815
29
+ pysqlsync/dialect/mssql/object_types.py,sha256=Oio7WIS2GtzyeGWUwIMzSzZ6mM0RBviBM_TT2hwPVyg,4035
30
+ pysqlsync/dialect/mysql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ pysqlsync/dialect/mysql/connection.py,sha256=7gnlglpjD8BaCS6pbM_3dbXzis1hKNkxz_OWrsix8Ao,4542
32
+ pysqlsync/dialect/mysql/data_types.py,sha256=FNToqK2jeBK5_5RATe8c79v2uvOhBTgdMN50Srx4-gk,1269
33
+ pysqlsync/dialect/mysql/dependency.py,sha256=OygsSx_shXpU7T2rNi9MVlEe-sCP5wuMtEC_V4_BdLM,317
34
+ pysqlsync/dialect/mysql/discovery.py,sha256=52VhOgEN8XhaheZfgvDk8xfuuIpe21XWs2pGFLdsPuU,6441
35
+ pysqlsync/dialect/mysql/engine.py,sha256=U6giltZzISuYQ1sMbWOaRcZUhFWH3z_qEGF00mL3rLc,552
36
+ pysqlsync/dialect/mysql/generator.py,sha256=d6jPfFjJo7DYP8GR5ph5Gwa2MIA6WrSN3StPyLDWmhg,6067
37
+ pysqlsync/dialect/mysql/mutation.py,sha256=9LMFkFf7uFsQ0Yb3yaMuXZZGpj7FXcVjTIN51LwamDY,2947
38
+ pysqlsync/dialect/mysql/object_types.py,sha256=A016_OzwwgBxNYEC-yH31ecTdAY39dK7TI45iJSgmZc,2604
39
+ pysqlsync/dialect/oracle/README.md,sha256=O_AFq4bvKm_C6PRsgdlphvtzVYCA2Fh-cc1kzMnBfnM,627
40
+ pysqlsync/dialect/oracle/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ pysqlsync/dialect/oracle/connection.py,sha256=VijCFOzxvH7-GhxP3thGOCbzr2TbMO9-Y6Uh38KaeOI,4780
42
+ pysqlsync/dialect/oracle/data_types.py,sha256=0xzyCkIOOdk5zVTfJSTYM40TcceVVZ9VJH6aN8k1GbY,3399
43
+ pysqlsync/dialect/oracle/dependency.py,sha256=tfCfWJLkB1qKNBlXiDN4Qfx8Q8Cd6XuPgMhLRFWE1Nc,246
44
+ pysqlsync/dialect/oracle/discovery.py,sha256=05Ko1FaQZ30Z4hn-kT4EzVxinqslqSrAdUjUacJVb5U,8554
45
+ pysqlsync/dialect/oracle/engine.py,sha256=PI3C1Fjbl7bZ83GBilt0G0zwJdoEUkwSDH1fjTiWI10,560
46
+ pysqlsync/dialect/oracle/generator.py,sha256=08QaFOOxKRf767nDBBK5qj8haWfzToIN5gZUnTRjFmg,4105
47
+ pysqlsync/dialect/oracle/mutation.py,sha256=dlFfCsUzVupcbBItqZE1GTQjH3P91HiU6p6YU3fFoc4,1380
48
+ pysqlsync/dialect/oracle/object_types.py,sha256=f83xzT6VXjLcWHxHclUQE2NxLBNmBxEWsbXiJ0ybGoY,1864
49
+ pysqlsync/dialect/postgresql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ pysqlsync/dialect/postgresql/connection.py,sha256=kbie90eWiumsFj-xkA7jGDZci6pJJeVEE41RDV6BU38,5000
51
+ pysqlsync/dialect/postgresql/data_types.py,sha256=6xOCIuKEaVO2pOLF1fa7hz3KfI9bR3xia4Db695V1EE,145
52
+ pysqlsync/dialect/postgresql/dependency.py,sha256=dWnPZBvAW5J-5KNRCvX0yomz9Yf2g7Z0cY3ZRGVmhJk,249
53
+ pysqlsync/dialect/postgresql/discovery.py,sha256=qdhFJkP_bMLSfIpzbunf2RFrkdMMmqXWcZ89dqmmeBc,15925
54
+ pysqlsync/dialect/postgresql/engine.py,sha256=51q2rqXc9N_AiD6C7f1RgorGXEI-r7N7X97a32o0Bt4,592
55
+ pysqlsync/dialect/postgresql/generator.py,sha256=ayVEMGhs7ANRIjExggVFeBLKXjywzhzr02f_MPYBIzE,4114
56
+ pysqlsync/dialect/postgresql/mutation.py,sha256=MRR3l8Is00CzyUsCNj2LgydoYvigb9DZMaEjk5-ort8,3821
57
+ pysqlsync/dialect/postgresql/object_types.py,sha256=Cs77Yymp21GuncIfRwCDbxzgkbkM5mUP__c-nw_jKk4,2871
58
+ pysqlsync/dialect/redshift/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
+ pysqlsync/dialect/redshift/connection.py,sha256=WXe7_lkr-V_yQwNgp5hLDwJ_FZzTWK2aup3wgmHzY2k,5547
60
+ pysqlsync/dialect/redshift/data_types.py,sha256=rXVPJv_7GgXx322baz0Ar_UktqSFpJPHBa10blDgoIk,303
61
+ pysqlsync/dialect/redshift/dependency.py,sha256=Kwbs95W67Zo0y3yFVazsQ3lPNOO8cWipKBTJQqRy2mM,262
62
+ pysqlsync/dialect/redshift/engine.py,sha256=WFRG0vgLGNYyWt_blXcVyWsaqpw2vNoB4tRzuNN76xo,592
63
+ pysqlsync/dialect/redshift/generator.py,sha256=X521WminSm-bcQj_LQ8qAbY0pSJnTpKgEqgbhdSVZ54,3044
64
+ pysqlsync/dialect/snowflake/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ pysqlsync/dialect/snowflake/data_types.py,sha256=GZbiEvz11S5ihIZ9Dk-mu1RlN5lZQUbY_K77uMNWjgU,449
66
+ pysqlsync/dialect/snowflake/dependency.py,sha256=SnWrzpztNYSyc4tS8eAIDLzor9BpsYshXir9aQBDMfo,250
67
+ pysqlsync/dialect/snowflake/engine.py,sha256=fiw7ln17C-js4zmgbkRefG2vkT-yJXbH3KR0zM0B-bM,503
68
+ pysqlsync/dialect/snowflake/generator.py,sha256=aKUAGE4ER0-w2rYN7YBpcULV9JjVsk8pAsjwgemRFJc,2188
69
+ pysqlsync/dialect/snowflake/object_types.py,sha256=OYsLqpwCOH1ZP-kHxUwCJWptS8KtPQHFYukOwopB0Xg,2589
70
+ pysqlsync/dialect/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
+ pysqlsync/dialect/test/dependency.py,sha256=avIdCXuaLjvMUdVKqH3LWM-NLT_X6MQBOn1MmExaXAQ,333
72
+ pysqlsync/dialect/trino/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
+ pysqlsync/dialect/trino/connection.py,sha256=C6GnIqHdL0tduELDz6JJQXtT1ulTATTFyjYnsHJHB8I,2679
74
+ pysqlsync/dialect/trino/dependency.py,sha256=a2SpMwtbjWcvKVQagJSN8qNQtqnzYLPjlPrM-JX__Vw,269
75
+ pysqlsync/dialect/trino/discovery.py,sha256=yAq4hV3j2WdFYWxbq2eKPsLz7pc9aaLC1ZE4DjOVi5E,698
76
+ pysqlsync/dialect/trino/engine.py,sha256=KHWbeoywcSfTRs9ZrdAWPDiaexzO5mYoACOwIJParAw,552
77
+ pysqlsync/dialect/trino/generator.py,sha256=qPYQ7yp8C97eXQAvMf9co8FGucdqRmxAlKu0_ZjwO5E,1147
78
+ pysqlsync/formation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
+ pysqlsync/formation/constraints.py,sha256=QweHKFZjSFdz1CkzyfuoD1c2iI4l3wTV4I3RZVpBd_g,2422
80
+ pysqlsync/formation/data_types.py,sha256=c_6UeeKrJPcGfeHSEnySzgoBqbt4aDMD2iL-h9VoZug,7416
81
+ pysqlsync/formation/discovery.py,sha256=Ln9m4EVfqyeDE37gwjJ-4sHRESRZ8ONPqfug6em_l4U,16328
82
+ pysqlsync/formation/inspection.py,sha256=EWVZ_WvHAfc8LbDboMwkXyJssGkAdPhMkOiyx4QcSsQ,5571
83
+ pysqlsync/formation/mutation.py,sha256=arnWK6p2M2eUnK2NCe5-n6f51BfVPgds2oio9kJ62nk,13349
84
+ pysqlsync/formation/object_dict.py,sha256=Tw53-avo-H6XZJErxp524-2LgYacQP748fEJPeLJJtM,2564
85
+ pysqlsync/formation/object_types.py,sha256=ZKCxFZGT1f0ia7wTQgNcF0Nd60Dj6RVtJk_ek0mOuF4,27821
86
+ pysqlsync/formation/py_to_sql.py,sha256=CAkkvfneao1FXWViocl8qWSL1E7rjQywRDFVRVQD2jk,46883
87
+ pysqlsync/formation/sql_to_py.py,sha256=Mgf8sr_WSR8rgRbiH_vI4ipqg9uvI_8GOJDnBDuaQ0M,6908
88
+ pysqlsync/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
+ pysqlsync/model/data_types.py,sha256=eSnBBsmUoGT3o3tprnl4l9mbf4Vij5wFTrqwYqIl_yc,11100
90
+ pysqlsync/model/entity_types.py,sha256=nF5ML-LYECwB2B6xCPR1WHGkea1tE6ENThUtLxjuoxs,2207
91
+ pysqlsync/model/id_types.py,sha256=LNSu0CLuR2dSQTvurldoePi7rQGqpKm5sDe2VlpJlMc,4357
92
+ pysqlsync/model/key_types.py,sha256=SdUTwh5iiofEU_PYXMpBYLR2Iz1DKb9p-WV7l7kxMxI,739
93
+ pysqlsync/model/properties.py,sha256=eGb3Y3nT7dxD_z70FF6Moq4Y1TUTF4x09725elFhQkY,7486
94
+ pysqlsync/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
95
+ pysqlsync/util/dataclasses.py,sha256=1AHp3eKa9LIf-CI7eyerQMm0ztqRaHytgSAcTC3dcf8,2773
96
+ pysqlsync/util/dispatch.py,sha256=17pL9-HubzPQvGmlT_wP49kXsWWE5zei2SfxoOpLLZk,902
97
+ pysqlsync/util/typing.py,sha256=SjILp7FG733KxddoJjAuUvc8YgimH2lEA6-YL-pZUws,478
98
+ instructure_pysqlsync-0.8.5.dev0.dist-info/METADATA,sha256=dM0fGzwEhNVdfsxaNGQmTPBhLxLKka9fMyU4zBGWeNU,13855
99
+ instructure_pysqlsync-0.8.5.dev0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
100
+ instructure_pysqlsync-0.8.5.dev0.dist-info/top_level.txt,sha256=w9A2WRkEAcGaTDp05I6BtMr8RfOW2MxKB4eGxes4TIQ,10
101
+ instructure_pysqlsync-0.8.5.dev0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
102
+ instructure_pysqlsync-0.8.5.dev0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023-2025 Levente Hunyadi; 2026 Instructure, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ pysqlsync
pysqlsync/__init__.py ADDED
@@ -0,0 +1,15 @@
1
+ """
2
+ pysqlsync: Synchronize schema and large volumes of data.
3
+
4
+ This library helps you synchronize your target database or data warehouse with a data source, making efficient use
5
+ of Python language elements and database drivers (client libraries).
6
+
7
+ :see: https://github.com/instructure-internal/pysqlsync
8
+ """
9
+
10
+ __version__ = "0.8.5.dev0"
11
+ __author__ = "Instructure, Inc."
12
+ __copyright__ = "Copyright 2023-2025, Levente Hunyadi; 2026 Instructure, Inc."
13
+ __license__ = "MIT"
14
+ __maintainer__ = "Instructure, Inc."
15
+ __status__ = "Development"