instructure-dap-client 2.3.0__tar.gz → 2.3.1__tar.gz

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 (174) hide show
  1. {instructure_dap_client-2.3.0/instructure_dap_client.egg-info → instructure_dap_client-2.3.1}/PKG-INFO +1 -1
  2. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/__init__.py +1 -1
  3. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/commands/command_group.py +17 -23
  4. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1/instructure_dap_client.egg-info}/PKG-INFO +1 -1
  5. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/__init__.py +1 -1
  6. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/data_types.py +71 -6
  7. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/data_types.py +7 -2
  8. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/LICENSE +0 -0
  9. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/MANIFEST.in +0 -0
  10. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/README.md +0 -0
  11. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/__main__.py +0 -0
  12. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/__init__.py +0 -0
  13. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/download_incremental.py +0 -0
  14. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/download_schema.py +0 -0
  15. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/download_snapshot.py +0 -0
  16. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/drop_db.py +0 -0
  17. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/init_db.py +0 -0
  18. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/list_db.py +0 -0
  19. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/list_tables.py +0 -0
  20. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/actions/sync_db.py +0 -0
  21. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/api.py +0 -0
  22. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/commands/__init__.py +0 -0
  23. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/commands/commands.py +0 -0
  24. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/commands/global_options.py +0 -0
  25. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/concurrency.py +0 -0
  26. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/dap_error.py +0 -0
  27. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/dap_types.py +0 -0
  28. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/integration/__init__.py +0 -0
  29. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/integration/base_connection.py +0 -0
  30. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/integration/connection.py +0 -0
  31. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/integration/database.py +0 -0
  32. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/integration/database_errors.py +0 -0
  33. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/log.py +0 -0
  34. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/networking.py +0 -0
  35. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/py.typed +0 -0
  36. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/__init__.py +0 -0
  37. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/canvas.py +0 -0
  38. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/canvas_logs.py +0 -0
  39. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/catalog.py +0 -0
  40. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/meta_schema.py +0 -0
  41. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/new_quizzes.py +0 -0
  42. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/record_validation.py +0 -0
  43. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql.py +0 -0
  44. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql_metatable_handler.py +0 -0
  45. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql_op.py +0 -0
  46. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql_op_drop.py +0 -0
  47. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql_op_init.py +0 -0
  48. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/replicator/sql_op_sync.py +0 -0
  49. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/retry_options.py +0 -0
  50. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/timestamp.py +0 -0
  51. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/tracking.py +0 -0
  52. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/ui.py +0 -0
  53. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/version_upgrade/__init__.py +0 -0
  54. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/version_upgrade/db_version_upgrader.py +0 -0
  55. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/version_upgrade/mssql_0_to_1.sql +0 -0
  56. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/version_upgrade/mysql_0_to_1.sql +0 -0
  57. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/dap/version_upgrade/postgresql_0_to_1.sql +0 -0
  58. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/SOURCES.txt +0 -0
  59. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/dependency_links.txt +0 -0
  60. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/entry_points.txt +0 -0
  61. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/requires.txt +0 -0
  62. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/top_level.txt +0 -0
  63. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/instructure_dap_client.egg-info/zip-safe +0 -0
  64. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pypi_index.md +0 -0
  65. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pyproject.toml +0 -0
  66. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/base.py +0 -0
  67. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/connection.py +0 -0
  68. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/data/__init__.py +0 -0
  69. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/data/exchange.py +0 -0
  70. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/data/generator.py +0 -0
  71. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/README.md +0 -0
  72. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/__init__.py +0 -0
  73. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/__init__.py +0 -0
  74. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/data_types.py +0 -0
  75. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/dependency.py +0 -0
  76. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/engine.py +0 -0
  77. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/generator.py +0 -0
  78. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/delta/object_types.py +0 -0
  79. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/README.md +0 -0
  80. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/__init__.py +0 -0
  81. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/connection.py +0 -0
  82. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/dependency.py +0 -0
  83. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/discovery.py +0 -0
  84. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/engine.py +0 -0
  85. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/generator.py +0 -0
  86. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/mutation.py +0 -0
  87. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mssql/object_types.py +0 -0
  88. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/__init__.py +0 -0
  89. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/connection.py +0 -0
  90. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/data_types.py +0 -0
  91. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/dependency.py +0 -0
  92. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/discovery.py +0 -0
  93. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/engine.py +0 -0
  94. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/generator.py +0 -0
  95. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/mutation.py +0 -0
  96. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/mysql/object_types.py +0 -0
  97. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/README.md +0 -0
  98. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/__init__.py +0 -0
  99. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/connection.py +0 -0
  100. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/data_types.py +0 -0
  101. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/dependency.py +0 -0
  102. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/discovery.py +0 -0
  103. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/engine.py +0 -0
  104. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/generator.py +0 -0
  105. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/mutation.py +0 -0
  106. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/oracle/object_types.py +0 -0
  107. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/__init__.py +0 -0
  108. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/connection.py +0 -0
  109. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/data_types.py +0 -0
  110. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/dependency.py +0 -0
  111. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/discovery.py +0 -0
  112. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/engine.py +0 -0
  113. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/generator.py +0 -0
  114. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/mutation.py +0 -0
  115. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/postgresql/object_types.py +0 -0
  116. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/__init__.py +0 -0
  117. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/connection.py +0 -0
  118. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/data_types.py +0 -0
  119. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/dependency.py +0 -0
  120. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/engine.py +0 -0
  121. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/redshift/generator.py +0 -0
  122. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/__init__.py +0 -0
  123. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/data_types.py +0 -0
  124. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/dependency.py +0 -0
  125. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/engine.py +0 -0
  126. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/generator.py +0 -0
  127. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/snowflake/object_types.py +0 -0
  128. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/test/__init__.py +0 -0
  129. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/test/dependency.py +0 -0
  130. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/__init__.py +0 -0
  131. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/connection.py +0 -0
  132. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/dependency.py +0 -0
  133. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/discovery.py +0 -0
  134. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/engine.py +0 -0
  135. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/dialect/trino/generator.py +0 -0
  136. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/factory.py +0 -0
  137. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/__init__.py +0 -0
  138. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/constraints.py +0 -0
  139. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/data_types.py +0 -0
  140. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/discovery.py +0 -0
  141. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/inspection.py +0 -0
  142. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/mutation.py +0 -0
  143. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/object_dict.py +0 -0
  144. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/object_types.py +0 -0
  145. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/py_to_sql.py +0 -0
  146. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/formation/sql_to_py.py +0 -0
  147. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/__init__.py +0 -0
  148. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/entity_types.py +0 -0
  149. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/id_types.py +0 -0
  150. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/key_types.py +0 -0
  151. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/model/properties.py +0 -0
  152. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/py.typed +0 -0
  153. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/python_types.py +0 -0
  154. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/resultset.py +0 -0
  155. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/util/__init__.py +0 -0
  156. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/util/dataclasses.py +0 -0
  157. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/util/dispatch.py +0 -0
  158. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/pysqlsync/util/typing.py +0 -0
  159. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/setup.cfg +0 -0
  160. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/__init__.py +0 -0
  161. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/auxiliary.py +0 -0
  162. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/classdef.py +0 -0
  163. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/core.py +0 -0
  164. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/deserializer.py +0 -0
  165. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/docstring.py +0 -0
  166. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/exception.py +0 -0
  167. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/inspection.py +0 -0
  168. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/mapping.py +0 -0
  169. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/name.py +0 -0
  170. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/py.typed +0 -0
  171. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/schema.py +0 -0
  172. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/serialization.py +0 -0
  173. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/serializer.py +0 -0
  174. {instructure_dap_client-2.3.0 → instructure_dap_client-2.3.1}/strong_typing/topological.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instructure-dap-client
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Data Access Platform client library
5
5
  Maintainer-email: "Instructure, Inc." <dapclient@instructure.com>
6
6
  License-Expression: MIT
@@ -6,7 +6,7 @@ to data collected across various educational products in bulk with high fidelity
6
6
  a canonical data model.
7
7
  """
8
8
 
9
- __version__ = "2.3.0"
9
+ __version__ = "2.3.1"
10
10
  __copyright__ = "Copyright 2022-2026, Instructure, Inc."
11
11
  __license__ = "MIT"
12
12
  __maintainer__ = "Instructure, Inc."
@@ -1,3 +1,4 @@
1
+ import textwrap
1
2
  from typing import Optional
2
3
  import asyncclick as click
3
4
 
@@ -24,45 +25,38 @@ class CustomGroup(click.Group):
24
25
 
25
26
  url1 = "https://developerdocs.instructure.com/services/dap/dap-cli-readme/dap-cli-reference"
26
27
  url2 = "https://developerdocs.instructure.com/services/dap/query-api"
27
- self._write_text_with_non_wrapped_parts(
28
+ self._write_text_without_breaking_urls(
28
29
  formatter,
29
30
  f"For more information and examples, check the reference at {url1} "
30
31
  f"and the OpenAPI specification for DAP API at {url2}.",
31
- non_wrapped_parts=[url1, url2],
32
32
  )
33
33
 
34
34
  def list_commands(self, ctx: click.Context) -> list[str]:
35
35
  # This overrides the default alphabetical ordering of commands with the order in which they were added
36
36
  return list(self.commands.keys())
37
37
 
38
- def _write_text_with_non_wrapped_parts(
38
+ def _write_text_without_breaking_urls(
39
39
  self,
40
40
  formatter: click.HelpFormatter,
41
41
  text: str,
42
- non_wrapped_parts: list[str] = [],
43
42
  ) -> None:
44
43
  """
45
- Writes text into the formatter, replacing non-wrapped parts with placeholders
46
- to prevent them from being wrapped by the formatter. Then it replaces the placeholders
47
- back with the original parts after the text has been written to the formatter.
44
+ Writes text into the formatter like ``HelpFormatter.write_text``, but never
45
+ splits a URL (or any other single "word") across lines: a word wider than the
46
+ available width overflows the target width instead of being cut apart.
48
47
  """
49
48
 
50
- placeholders: dict[str, str] = {}
51
-
52
- for i in range(len(non_wrapped_parts)):
53
- part = non_wrapped_parts[i]
54
- placeholder = part.replace("-", "_").replace(" ", "_")
55
- placeholders[part] = placeholder
56
-
57
- for part, placeholder in placeholders.items():
58
- text = text.replace(part, placeholder)
59
-
60
- formatter.write_text(text)
61
-
62
- for part, placeholder in placeholders.items():
63
- formatter.buffer = [
64
- line.replace(placeholder, part) for line in formatter.buffer
65
- ]
49
+ indent = " " * formatter.current_indent
50
+ wrapper = textwrap.TextWrapper(
51
+ width=formatter.width,
52
+ initial_indent=indent,
53
+ subsequent_indent=indent,
54
+ replace_whitespace=False,
55
+ break_long_words=False,
56
+ break_on_hyphens=False,
57
+ )
58
+ formatter.write(wrapper.fill(text))
59
+ formatter.write("\n")
66
60
 
67
61
 
68
62
  @click.group(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: instructure-dap-client
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Data Access Platform client library
5
5
  Maintainer-email: "Instructure, Inc." <dapclient@instructure.com>
6
6
  License-Expression: MIT
@@ -9,7 +9,7 @@ Copyright 2023-2026, Levente Hunyadi; 2026 Instructure, Inc.
9
9
  :see: https://github.com/instructure-internal/pysqlsync
10
10
  """
11
11
 
12
- __version__ = "1.0.1"
12
+ __version__ = "1.0.2"
13
13
  __author__ = "Instructure, Inc."
14
14
  __copyright__ = "Copyright 2023-2026, Levente Hunyadi; 2026 Instructure, Inc."
15
15
  __license__ = "MIT"
@@ -7,9 +7,11 @@ Copyright 2023-2026, Levente Hunyadi; 2026 Instructure, Inc.
7
7
  """
8
8
 
9
9
  import enum
10
+ from dataclasses import dataclass
10
11
  from typing import Any, Optional
11
12
 
12
13
  import pyodbc
14
+ from strong_typing.auxiliary import MaxLength
13
15
 
14
16
  from pysqlsync.model.data_types import (
15
17
  SqlBooleanType,
@@ -40,29 +42,70 @@ class MSSQLBooleanType(SqlBooleanType):
40
42
  return "1" if value else "0"
41
43
 
42
44
 
45
+ # `varchar(n)` holds n bytes; `nvarchar(n)` holds n UTF-16 code units. Beyond
46
+ # these maxima only the `(max)` form is valid.
47
+ MAX_VARCHAR_SIZE = 8000
48
+ MAX_NVARCHAR_SIZE = 4000
49
+
50
+ # Under a UTF-8 collation `varchar(n)` budgets n *bytes*, but the `MaxLength`
51
+ # annotation it is derived from counts *characters*. A character encodes to at
52
+ # most 4 bytes in UTF-8, so a limit declared in characters is scaled to
53
+ # guarantee any input fits. Without this a 255-character value holding one
54
+ # 3-byte character overflows `varchar(255)` and SQL Server rejects the insert
55
+ # with "String or binary data would be truncated".
56
+ MAX_UTF8_BYTES_PER_CHARACTER = 4
57
+
58
+
43
59
  class MSSQLEncoding(enum.Enum):
44
60
  UTF8 = "utf-8"
45
61
  UTF16 = "utf-16"
46
62
 
47
63
 
64
+ @dataclass
48
65
  class MSSQLVariableCharacterType(SqlVariableCharacterType):
66
+ # A dataclass field, not a plain attribute: the generated `__eq__` is what
67
+ # schema synchronization compares to decide whether a column needs an
68
+ # `ALTER`. Were `encoding` excluded, `varchar(n)` and `nvarchar(n)` would
69
+ # compare equal and a type change would silently never be migrated.
49
70
  encoding: Optional[MSSQLEncoding] = None
50
71
 
51
72
  def __init__(self, limit: Optional[int] = None, encoding: Optional[MSSQLEncoding] = None) -> None:
52
73
  super().__init__(limit)
53
74
  self.encoding = encoding
54
75
 
55
- def __str__(self) -> str:
76
+ def _max_size(self) -> int:
77
+ "Returns the widest fixed-width size this column's type family accepts."
78
+
56
79
  if self.encoding is MSSQLEncoding.UTF16:
57
- char_type = "nvarchar"
80
+ return MAX_NVARCHAR_SIZE
58
81
  else:
59
- char_type = "varchar"
82
+ return MAX_VARCHAR_SIZE
60
83
 
61
- if self.limit is not None and self.limit > 0 and self.limit != 2147483647:
84
+ def __str__(self) -> str:
85
+ char_type = "nvarchar" if self.encoding is MSSQLEncoding.UTF16 else "varchar"
86
+
87
+ if self.limit is not None and self.limit > 0 and self.limit <= self._max_size() and self.limit != 2147483647:
62
88
  return f"{char_type}({self.limit})"
63
89
  else:
64
90
  return f"{char_type}(max)"
65
91
 
92
+ def parse_meta(self, meta: Any) -> None:
93
+ if isinstance(meta, MaxLength):
94
+ # `MaxLength` counts characters. `varchar(n)` budgets n *bytes*, so a
95
+ # character limit is scaled to a byte limit; `nvarchar(n)` already
96
+ # counts UTF-16 code units, the same unit `MaxLength` counts in, so no
97
+ # scaling applies there.
98
+ scale = MAX_UTF8_BYTES_PER_CHARACTER if self.encoding is not MSSQLEncoding.UTF16 else 1
99
+ budget = meta.value * scale
100
+ # A budget past the fixed-width maximum is held as `None`, the same
101
+ # value discovery reports for a `(max)` column, so that a generated
102
+ # type and the one read back from the database compare equal.
103
+ # Keeping the overflowed count instead would make schema
104
+ # synchronization emit a redundant `ALTER` on every run.
105
+ self.limit = budget if budget <= self._max_size() else None
106
+ else:
107
+ super().parse_meta(meta)
108
+
66
109
 
67
110
  class MSSQLDateTimeType(SqlTimestampType):
68
111
  def __init__(self) -> None:
@@ -72,6 +115,28 @@ class MSSQLDateTimeType(SqlTimestampType):
72
115
  return "datetime2"
73
116
 
74
117
 
118
+ # Character parameters bind as the wide ODBC types, whose declared size is in
119
+ # UTF-16 code units and so cannot exceed the `nvarchar` maximum — half what a
120
+ # `varchar` column may declare. A wider declaration describes a fixed-width
121
+ # Unicode type that does not exist, and ODBC Driver 18 rejects the descriptor
122
+ # with HY104 "Invalid precision value". Report such a column as unbounded: the
123
+ # driver then binds it as a LOB, which carries any length without error.
124
+ MAX_WIDE_COLUMN_SIZE = MAX_NVARCHAR_SIZE
125
+
126
+
127
+ def _wide_column_size(limit: Optional[int]) -> int:
128
+ """
129
+ Returns the column size to declare for a wide (Unicode) character parameter.
130
+
131
+ :param limit: The column's declared character limit, or `None` if unbounded.
132
+ :returns: The limit if it fits a fixed-width wide type, or 0 to bind as a LOB.
133
+ """
134
+
135
+ if not limit or limit > MAX_WIDE_COLUMN_SIZE:
136
+ return 0
137
+ return limit
138
+
139
+
75
140
  def sql_to_odbc_type(data_type: SqlDataType) -> tuple[int, int, int]:
76
141
  """
77
142
  Returns the ODBC data type associated with the SQL data type.
@@ -116,9 +181,9 @@ def sql_to_odbc_type(data_type: SqlDataType) -> tuple[int, int, int]:
116
181
  # the narrow `SQL_CHAR`/`SQL_VARCHAR` makes `fast_executemany` miscount
117
182
  # the buffer width, observed to silently corrupt non-Latin text. SQL
118
183
  # Server converts UTF-16 to the column's UTF-8 storage on insert.
119
- return pyodbc.SQL_WCHAR, data_type.limit or 0, 0
184
+ return pyodbc.SQL_WCHAR, _wide_column_size(data_type.limit), 0
120
185
  elif isinstance(data_type, SqlVariableCharacterType):
121
- return pyodbc.SQL_WVARCHAR, data_type.limit or 0, 0
186
+ return pyodbc.SQL_WVARCHAR, _wide_column_size(data_type.limit), 0
122
187
  elif isinstance(data_type, SqlFixedBinaryType):
123
188
  return pyodbc.SQL_BINARY, data_type.storage or 0, 0
124
189
  elif isinstance(data_type, SqlVariableBinaryType):
@@ -6,6 +6,7 @@ Copyright 2023-2026, Levente Hunyadi; 2026 Instructure, Inc.
6
6
  :see: https://github.com/instructure-internal/pysqlsync
7
7
  """
8
8
 
9
+ import copy
9
10
  import datetime
10
11
  import decimal
11
12
  from dataclasses import dataclass
@@ -387,10 +388,14 @@ def _compatible_type(left: SqlDataType, right: SqlDataType) -> SqlDataType:
387
388
  if isinstance(right, SqlFixedCharacterType):
388
389
  return type(left)(limit=max_or_none(left.limit, right.limit))
389
390
  elif isinstance(right, SqlVariableCharacterType):
390
- return type(right)(limit=max_or_none(left.limit, right.limit))
391
+ merged = copy.copy(right)
392
+ merged.limit = max_or_none(left.limit, right.limit)
393
+ return merged
391
394
  elif isinstance(left, SqlVariableCharacterType):
392
395
  if isinstance(right, (SqlFixedCharacterType, SqlVariableCharacterType)):
393
- return type(left)(limit=max_or_none(left.limit, right.limit))
396
+ merged = copy.copy(left)
397
+ merged.limit = max_or_none(left.limit, right.limit)
398
+ return merged
394
399
 
395
400
  # binary types
396
401
  if isinstance(left, SqlFixedBinaryType):