GeoAlchemy2 0.15.2__tar.gz → 0.16.0__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 (137) hide show
  1. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/workflows/test_and_publish.yml +58 -25
  2. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.pre-commit-config.yaml +0 -2
  3. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/CHANGES.txt +7 -0
  4. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0/GeoAlchemy2.egg-info}/PKG-INFO +1 -1
  5. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/SOURCES.txt +5 -0
  6. {geoalchemy2-0.15.2/GeoAlchemy2.egg-info → geoalchemy2-0.16.0}/PKG-INFO +1 -1
  7. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/admin.rst +2 -2
  8. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/index.rst +1 -1
  9. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/mysql.py +74 -6
  10. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/__init__.py +4 -4
  11. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/__init__.py +1 -0
  12. geoalchemy2-0.16.0/geoalchemy2/types/dialects/mariadb.py +47 -0
  13. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/pyproject.toml +3 -0
  14. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/requirements.txt +1 -1
  15. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/Dockerfile +2 -2
  16. geoalchemy2-0.16.0/test_container/Dockerfile_mariadb +19 -0
  17. geoalchemy2-0.16.0/test_container/build_mariadb.sh +7 -0
  18. geoalchemy2-0.16.0/test_container/helpers/init_mariadb.sh +22 -0
  19. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/helpers/init_mysql.sh +2 -1
  20. geoalchemy2-0.16.0/test_container/run_mariadb.sh +12 -0
  21. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/conftest.py +85 -25
  22. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_orm_mapped_v2.py +1 -1
  23. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_summarystatsagg.py +1 -1
  24. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/schema_fixtures.py +1 -1
  25. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_alembic_migrations.py +1 -1
  26. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functional.py +85 -19
  27. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functional_mysql.py +19 -8
  28. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functional_postgresql.py +1 -1
  29. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_pickle.py +1 -1
  30. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tox.ini +7 -2
  31. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.codespellrc +0 -0
  32. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.coveragerc +0 -0
  33. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.flake8 +0 -0
  34. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  35. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  36. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  37. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/how_to_use.yaml +0 -0
  38. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/dependabot.yml +0 -0
  39. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.github/pull_request_template.md +0 -0
  40. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.gitignore +0 -0
  41. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/.readthedocs.yaml +0 -0
  42. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/COPYING.rst +0 -0
  43. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/dependency_links.txt +0 -0
  44. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/not-zip-safe +0 -0
  45. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/requires.txt +0 -0
  46. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/top_level.txt +0 -0
  47. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/GeoAlchemy2_dev.yml +0 -0
  48. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/MANIFEST.in +0 -0
  49. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/README.rst +0 -0
  50. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/RELEASE.rst +0 -0
  51. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/TEST.rst +0 -0
  52. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/Makefile +0 -0
  53. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_static/geoalchemy.png +0 -0
  54. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_static/geoalchemy.svg +0 -0
  55. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_static/geoalchemy_small.png +0 -0
  56. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_static/geoalchemy_small.svg +0 -0
  57. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_templates/sidebar-about.html +0 -0
  58. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_templates/sidebar-links.html +0 -0
  59. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_templates/sidebar-logo.html +0 -0
  60. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/LICENSE +0 -0
  61. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/README +0 -0
  62. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/flask/layout.html +0 -0
  63. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/flask/relations.html +0 -0
  64. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/flask/static/flasky.css_t +0 -0
  65. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/flask/static/small_flask.css +0 -0
  66. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/_themes/flask/theme.conf +0 -0
  67. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/alembic.rst +0 -0
  68. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/alembic_helpers.rst +0 -0
  69. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/changelog.rst +0 -0
  70. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/conf.py +0 -0
  71. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/core_tutorial.rst +0 -0
  72. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/elements.rst +0 -0
  73. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/make.bat +0 -0
  74. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/migrate.rst +0 -0
  75. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/orm_tutorial.rst +0 -0
  76. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/shape.rst +0 -0
  77. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/spatial_functions.rst +0 -0
  78. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/spatial_operators.rst +0 -0
  79. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/spatialite_tutorial.rst +0 -0
  80. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/doc/types.rst +0 -0
  81. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/generate_type_stubs.py +0 -0
  82. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/__init__.py +0 -0
  83. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/_functions.py +0 -0
  84. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/_functions_helpers.py +0 -0
  85. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/__init__.py +0 -0
  86. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/__init__.py +0 -0
  87. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/common.py +0 -0
  88. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/geopackage.py +0 -0
  89. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/postgresql.py +0 -0
  90. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/sqlite.py +0 -0
  91. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/alembic_helpers.py +0 -0
  92. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/comparator.py +0 -0
  93. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/elements.py +0 -0
  94. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/exc.py +0 -0
  95. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/functions.py +0 -0
  96. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/functions.pyi +0 -0
  97. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/py.typed +0 -0
  98. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/shape.py +0 -0
  99. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/common.py +0 -0
  100. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/geopackage.py +0 -0
  101. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/mysql.py +0 -0
  102. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/postgresql.py +0 -0
  103. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/sqlite.py +0 -0
  104. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/geoalchemy2/utils.py +0 -0
  105. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/requirements-doc.txt +0 -0
  106. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/requirements-mypy.txt +0 -0
  107. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/requirements-rtd.txt +0 -0
  108. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/setup.cfg +0 -0
  109. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/setup.py +0 -0
  110. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/.dockerignore +0 -0
  111. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/.gitignore +0 -0
  112. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/build.sh +0 -0
  113. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/helpers/entrypoint.sh +0 -0
  114. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/helpers/init_postgres.sh +0 -0
  115. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/helpers/install_requirements.sh +0 -0
  116. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/test_container/run.sh +0 -0
  117. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/__init__.py +0 -0
  118. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/alembic_config/alembic.ini +0 -0
  119. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/data/spatialite_ge_4.sqlite +0 -0
  120. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/data/spatialite_geopackage.gpkg +0 -0
  121. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/data/spatialite_lt_4.sqlite +0 -0
  122. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/README.rst +0 -0
  123. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/__init__.py +0 -0
  124. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_decipher_raster.py +0 -0
  125. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_disable_wrapping.py +0 -0
  126. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_insert_raster.py +0 -0
  127. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_length_at_insert.py +0 -0
  128. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_raster_transform.py +0 -0
  129. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_specific_compilation.py +0 -0
  130. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/gallery/test_type_decorator.py +0 -0
  131. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_comparator.py +0 -0
  132. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_elements.py +0 -0
  133. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functional_geopackage.py +0 -0
  134. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functional_sqlite.py +0 -0
  135. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_functions.py +0 -0
  136. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_shape.py +0 -0
  137. {geoalchemy2-0.15.2 → geoalchemy2-0.16.0}/tests/test_types.py +0 -0
@@ -54,28 +54,53 @@ jobs:
54
54
  --health-interval 10s
55
55
  --health-timeout 5s
56
56
  --health-retries 5
57
+ mysql:
58
+ image: mysql:latest
59
+ ports:
60
+ - 3307:3306
61
+ env:
62
+ MYSQL_USER: gis
63
+ MYSQL_PASSWORD: gis
64
+ MYSQL_DATABASE: gis
65
+ MYSQL_ROOT_PASSWORD: gis
66
+ # Set health checks to wait until MySQL has started
67
+ options: >-
68
+ --health-cmd="mysqladmin ping"
69
+ --health-interval=10s
70
+ --health-timeout=5s
71
+ --health-retries=3
72
+ mariadb:
73
+ image: mariadb:latest
74
+ ports:
75
+ - 3308:3306
76
+ env:
77
+ MARIADB_USER: gis
78
+ MARIADB_PASSWORD: gis
79
+ MARIADB_DATABASE: gis
80
+ MARIADB_ROOT_PASSWORD: gis
81
+ # Set health checks to wait until MariaDB has started
82
+ options: >-
83
+ --health-cmd="healthcheck.sh --connect --innodb_initialized"
84
+ --health-interval=10s
85
+ --health-timeout=5s
86
+ --health-retries=3
87
+
57
88
 
58
89
  steps:
59
90
 
60
91
  # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
61
92
  - uses: actions/checkout@v4
62
93
 
63
- # Setup Conda for Python and Pypy
64
- - name: Install Conda environment with Micromamba
65
- uses: mamba-org/setup-micromamba@v1
94
+ # Setup Python
95
+ - name: Set up Python ${{ matrix.python-version }}
96
+ uses: actions/setup-python@v5
66
97
  with:
67
- environment-name: test_${{ matrix.python-version.flag }}
68
- cache-environment: true
69
- create-args: >-
70
- ${{ matrix.python-version.pkg_name }}
71
- libgdal
72
- libspatialite==5.0.1
73
- pyproj
74
- condarc: |
75
- channels:
76
- - conda-forge
77
- - defaults
78
- channel_priority: strict
98
+ python-version: ${{ matrix.python-version.flag }}
99
+
100
+ # Install MariaDB
101
+ - name: Install MariaDB and SpatiaLite
102
+ run: |
103
+ sudo apt-get install -y mariadb-server mariadb-client libsqlite3-mod-spatialite libgdal-dev gdal-bin rasterio
79
104
 
80
105
  # Config PostgreSQL
81
106
  - name: Configure PostgreSQL
@@ -95,13 +120,17 @@ jobs:
95
120
  # Drop PostGIS Topology extension to "gis" database
96
121
  psql -h localhost -p 5432 -U gis -d gis -c 'DROP EXTENSION IF EXISTS postgis_topology;'
97
122
 
98
- # Setup MySQL
99
- - name: Set up MySQL
123
+ # Check MySQL
124
+ - name: Check MySQL
125
+ run: |
126
+ mysql --user=gis --password=gis --host=127.0.0.1 -P 3307 -e "SELECT VERSION();"
127
+ mysql --user=root --password=gis --host=127.0.0.1 -P 3307 -e "GRANT ALL PRIVILEGES ON *.* TO 'gis'@'%' WITH GRANT OPTION;"
128
+
129
+ # Check MariaDB
130
+ - name: Check MariaDB
100
131
  run: |
101
- sudo systemctl start mysql
102
- sudo mysql --user=root --password=root --host=127.0.0.1 -e "CREATE USER 'gis'@'%' IDENTIFIED BY 'gis';"
103
- sudo mysql --user=root --password=root --host=127.0.0.1 -e "GRANT ALL PRIVILEGES ON *.* TO 'gis'@'%' WITH GRANT OPTION;"
104
- mysql --user=gis --password=gis -e "CREATE DATABASE gis;"
132
+ mysql --user=gis --password=gis --host=127.0.0.1 -P 3308 -e "SELECT VERSION();"
133
+ mysql --user=root --password=gis --host=127.0.0.1 -P 3308 -e "GRANT ALL PRIVILEGES ON *.* TO 'gis'@'%' WITH GRANT OPTION;"
105
134
 
106
135
  # Check python version
107
136
  - name: Display Python version
@@ -114,16 +143,20 @@ jobs:
114
143
  - name: Install dependencies
115
144
  run: |
116
145
  python -m pip install --upgrade pip setuptools
117
- pip install tox-gh-actions
146
+ python -m pip install tox-gh-actions
118
147
 
119
148
  # Run the test suite
120
149
  - name: Run the tests
121
150
  env:
122
- SPATIALITE_LIBRARY_PATH: /home/runner/micromamba/envs/test_${{ matrix.python-version.flag }}/lib/mod_spatialite.so
123
- PROJ_LIB: /home/runner/micromamba/envs/test_${{ matrix.python-version.flag }}/share/proj
151
+ SPATIALITE_LIBRARY_PATH: /usr/lib/x86_64-linux-gnu/mod_spatialite.so
124
152
  COVERAGE_FILE: .coverage
125
- PYTEST_MYSQL_DB_URL: mysql://gis:gis@127.0.0.1/gis
153
+ PYTEST_MYSQL_DB_URL: mysql://gis:gis@127.0.0.1:3307/gis
154
+ PYTEST_MARIADB_DB_URL: mariadb://gis:gis@127.0.0.1:3308/gis
126
155
  run: |
156
+ export PYTEST_ADDOPTS='--require-all-dialects'
157
+ if [[ ${{ matrix.python-version.flag }} == 'pypy3.8' ]]; then
158
+ export PYTEST_ADDOPTS=${PYTEST_ADDOPTS}' --ignore=tests/gallery/test_insert_raster.py'
159
+ fi;
127
160
  # Run the unit test suite with SQLAlchemy=1.4.* and then with the latest version of SQLAlchemy
128
161
  tox -vv
129
162
 
@@ -1,5 +1,3 @@
1
- default_language_version:
2
- python: python3.8
3
1
  repos:
4
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
5
3
  rev: v4.6.0
@@ -1,6 +1,13 @@
1
1
  GeoAlchemy 2 Changelog
2
2
  ======================
3
3
 
4
+ 0.16.0
5
+ ------
6
+
7
+ * Test: Add test in test_functional.py for custom Geometry that uses WKT elements @adrien-berchet (#525)
8
+ * Add option to ensure all dialects are properly tested in CI @adrien-berchet (#526)
9
+ * Improve MariaDB support @adrien-berchet (#524)
10
+
4
11
  0.15.2
5
12
  ------
6
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: GeoAlchemy2
3
- Version: 0.15.2
3
+ Version: 0.16.0
4
4
  Summary: Using SQLAlchemy with Spatial Databases
5
5
  Home-page: https://geoalchemy-2.readthedocs.io/en/stable/
6
6
  Author: Eric Lemoine
@@ -86,15 +86,20 @@ geoalchemy2/types/__init__.py
86
86
  geoalchemy2/types/dialects/__init__.py
87
87
  geoalchemy2/types/dialects/common.py
88
88
  geoalchemy2/types/dialects/geopackage.py
89
+ geoalchemy2/types/dialects/mariadb.py
89
90
  geoalchemy2/types/dialects/mysql.py
90
91
  geoalchemy2/types/dialects/postgresql.py
91
92
  geoalchemy2/types/dialects/sqlite.py
92
93
  test_container/.dockerignore
93
94
  test_container/.gitignore
94
95
  test_container/Dockerfile
96
+ test_container/Dockerfile_mariadb
95
97
  test_container/build.sh
98
+ test_container/build_mariadb.sh
96
99
  test_container/run.sh
100
+ test_container/run_mariadb.sh
97
101
  test_container/helpers/entrypoint.sh
102
+ test_container/helpers/init_mariadb.sh
98
103
  test_container/helpers/init_mysql.sh
99
104
  test_container/helpers/init_postgres.sh
100
105
  test_container/helpers/install_requirements.sh
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: GeoAlchemy2
3
- Version: 0.15.2
3
+ Version: 0.16.0
4
4
  Summary: Using SQLAlchemy with Spatial Databases
5
5
  Home-page: https://geoalchemy-2.readthedocs.io/en/stable/
6
6
  Author: Eric Lemoine
@@ -25,8 +25,8 @@ PostgreSQL-specific objects
25
25
  :private-members:
26
26
  :show-inheritance:
27
27
 
28
- MySQL-specific objects
29
- ---------------------------
28
+ MySQL/MariadDB-specific objects
29
+ -------------------------------
30
30
 
31
31
  .. automodule:: geoalchemy2.admin.dialects.mysql
32
32
  :members:
@@ -17,7 +17,7 @@ GeoAlchemy 2 also supports the following dialects:
17
17
  * `GeoPackage <http://www.geopackage.org/spec/>`_
18
18
 
19
19
  Note that using GeoAlchemy 2 with these dialects may require some specific configuration on the
20
- application side.
20
+ application side. It also may not be optimal for performance.
21
21
 
22
22
  GeoAlchemy 2 aims to be simpler than its predecessor, `GeoAlchemy
23
23
  <https://pypi.python.org/pypi/GeoAlchemy>`_. Simpler to use, and simpler
@@ -8,6 +8,9 @@ from geoalchemy2 import functions
8
8
  from geoalchemy2.admin.dialects.common import _check_spatial_type
9
9
  from geoalchemy2.admin.dialects.common import _spatial_idx_name
10
10
  from geoalchemy2.admin.dialects.common import setup_create_drop
11
+ from geoalchemy2.elements import WKBElement
12
+ from geoalchemy2.elements import WKTElement
13
+ from geoalchemy2.shape import to_shape
11
14
  from geoalchemy2.types import Geography
12
15
  from geoalchemy2.types import Geometry
13
16
 
@@ -31,11 +34,16 @@ def reflect_geometry_column(inspector, table, column_info):
31
34
  column_name = column_info.get("name")
32
35
  schema = table.schema or inspector.default_schema_name
33
36
 
37
+ if inspector.dialect.name == "mariadb":
38
+ select_srid = "-1, "
39
+ else:
40
+ select_srid = "SRS_ID, "
41
+
34
42
  # Check geometry type, SRID and if the column is nullable
35
- geometry_type_query = """SELECT DATA_TYPE, SRS_ID, IS_NULLABLE
43
+ geometry_type_query = """SELECT DATA_TYPE, {}IS_NULLABLE
36
44
  FROM INFORMATION_SCHEMA.COLUMNS
37
45
  WHERE TABLE_NAME = '{}' and COLUMN_NAME = '{}'""".format(
38
- table.name, column_name
46
+ select_srid, table.name, column_name
39
47
  )
40
48
  if schema is not None:
41
49
  geometry_type_query += """ and table_schema = '{}'""".format(schema)
@@ -176,25 +184,85 @@ def _compile_GeomFromWKB_MySql(element, compiler, **kw):
176
184
  return "{}({})".format(element.identifier, compiled)
177
185
 
178
186
 
187
+ def _compile_GeomFromText_MariaDB(element, compiler, **kw):
188
+ element.identifier = "ST_GeomFromText"
189
+ compiled = compiler.process(element.clauses, **kw)
190
+ try:
191
+ clauses = list(element.clauses)
192
+ data_element = WKTElement(clauses[0].value)
193
+ srid = max(0, data_element.srid)
194
+ if srid <= 0:
195
+ srid = max(0, element.type.srid)
196
+ if len(clauses) > 1 and srid > 0:
197
+ clauses[1].value = srid
198
+ except Exception:
199
+ srid = max(0, element.type.srid)
200
+
201
+ if srid > 0:
202
+ res = "{}({}, {})".format(element.identifier, compiled, srid)
203
+ else:
204
+ res = "{}({})".format(element.identifier, compiled)
205
+ return res
206
+
207
+
208
+ def _compile_GeomFromWKB_MariaDB(element, compiler, **kw):
209
+ element.identifier = "ST_GeomFromText"
210
+
211
+ try:
212
+ clauses = list(element.clauses)
213
+ data_element = WKBElement(clauses[0].value)
214
+ srid = max(0, data_element.srid)
215
+ if srid <= 0:
216
+ srid = max(0, element.type.srid)
217
+ clauses[0].value = to_shape(data_element).wkt.encode("utf-8")
218
+ if len(clauses) > 1 and srid > 0:
219
+ clauses[1].value = srid
220
+ except Exception:
221
+ srid = max(0, element.type.srid)
222
+ compiled = compiler.process(element.clauses, **kw)
223
+
224
+ if srid > 0:
225
+ res = "{}({}, {})".format(element.identifier, compiled, srid)
226
+ else:
227
+ res = "{}({})".format(element.identifier, compiled)
228
+ return res
229
+
230
+
179
231
  @compiles(functions.ST_GeomFromText, "mysql") # type: ignore
180
- @compiles(functions.ST_GeomFromText, "mariadb") # type: ignore
181
232
  def _MySQL_ST_GeomFromText(element, compiler, **kw):
182
233
  return _compile_GeomFromText_MySql(element, compiler, **kw)
183
234
 
184
235
 
185
236
  @compiles(functions.ST_GeomFromEWKT, "mysql") # type: ignore
186
- @compiles(functions.ST_GeomFromEWKT, "mariadb") # type: ignore
187
237
  def _MySQL_ST_GeomFromEWKT(element, compiler, **kw):
188
238
  return _compile_GeomFromText_MySql(element, compiler, **kw)
189
239
 
190
240
 
241
+ @compiles(functions.ST_GeomFromText, "mariadb") # type: ignore
242
+ def _MariaDB_ST_GeomFromText(element, compiler, **kw):
243
+ return _compile_GeomFromText_MariaDB(element, compiler, **kw)
244
+
245
+
246
+ @compiles(functions.ST_GeomFromEWKT, "mariadb") # type: ignore
247
+ def _MariaDB_ST_GeomFromEWKT(element, compiler, **kw):
248
+ return _compile_GeomFromText_MariaDB(element, compiler, **kw)
249
+
250
+
191
251
  @compiles(functions.ST_GeomFromWKB, "mysql") # type: ignore
192
- @compiles(functions.ST_GeomFromWKB, "mariadb") # type: ignore
193
252
  def _MySQL_ST_GeomFromWKB(element, compiler, **kw):
194
253
  return _compile_GeomFromWKB_MySql(element, compiler, **kw)
195
254
 
196
255
 
197
256
  @compiles(functions.ST_GeomFromEWKB, "mysql") # type: ignore
198
- @compiles(functions.ST_GeomFromEWKB, "mariadb") # type: ignore
199
257
  def _MySQL_ST_GeomFromEWKB(element, compiler, **kw):
200
258
  return _compile_GeomFromWKB_MySql(element, compiler, **kw)
259
+
260
+
261
+ @compiles(functions.ST_GeomFromWKB, "mariadb") # type: ignore
262
+ def _MariaDB_ST_GeomFromWKB(element, compiler, **kw):
263
+ return _compile_GeomFromWKB_MariaDB(element, compiler, **kw)
264
+
265
+
266
+ @compiles(functions.ST_GeomFromEWKB, "mariadb") # type: ignore
267
+ def _MariaDB_ST_GeomFromEWKB(element, compiler, **kw):
268
+ return _compile_GeomFromWKB_MariaDB(element, compiler, **kw)
@@ -40,7 +40,7 @@ def select_dialect(dialect_name):
40
40
  known_dialects = {
41
41
  "geopackage": dialects.geopackage,
42
42
  "mysql": dialects.mysql,
43
- "mariadb": dialects.mysql,
43
+ "mariadb": dialects.mariadb,
44
44
  "postgresql": dialects.postgresql,
45
45
  "sqlite": dialects.sqlite,
46
46
  }
@@ -198,9 +198,9 @@ class _GISType(UserDefinedType):
198
198
  return geometry_type, srid
199
199
 
200
200
 
201
- @compiles(_GISType, "mariadb")
202
201
  @compiles(_GISType, "mysql")
203
- def get_col_spec(self, *args, **kwargs):
202
+ @compiles(_GISType, "mariadb")
203
+ def get_col_spec_mysql(self, compiler, *args, **kwargs):
204
204
  if self.geometry_type is not None:
205
205
  spec = "%s" % self.geometry_type
206
206
  else:
@@ -208,7 +208,7 @@ def get_col_spec(self, *args, **kwargs):
208
208
 
209
209
  if not self.nullable or self.spatial_index:
210
210
  spec += " NOT NULL"
211
- if self.srid > 0:
211
+ if self.srid > 0 and compiler.dialect.name != "mariadb":
212
212
  spec += " SRID %d" % self.srid
213
213
  return spec
214
214
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  from geoalchemy2.types.dialects import common # noqa
4
4
  from geoalchemy2.types.dialects import geopackage # noqa
5
+ from geoalchemy2.types.dialects import mariadb # noqa
5
6
  from geoalchemy2.types.dialects import mysql # noqa
6
7
  from geoalchemy2.types.dialects import postgresql # noqa
7
8
  from geoalchemy2.types.dialects import sqlite # noqa
@@ -0,0 +1,47 @@
1
+ """This module defines specific functions for MySQL dialect."""
2
+
3
+ from geoalchemy2.elements import WKBElement
4
+ from geoalchemy2.elements import WKTElement
5
+ from geoalchemy2.elements import _SpatialElement
6
+ from geoalchemy2.exc import ArgumentError
7
+ from geoalchemy2.shape import to_shape
8
+
9
+
10
+ def bind_processor_process(spatial_type, bindvalue):
11
+ if isinstance(bindvalue, str):
12
+ wkt_match = WKTElement._REMOVE_SRID.match(bindvalue)
13
+ srid = wkt_match.group(2)
14
+ try:
15
+ if srid is not None:
16
+ srid = int(srid)
17
+ except (ValueError, TypeError): # pragma: no cover
18
+ raise ArgumentError(
19
+ f"The SRID ({srid}) of the supplied value can not be casted to integer"
20
+ )
21
+
22
+ if srid is not None and srid != spatial_type.srid:
23
+ raise ArgumentError(
24
+ f"The SRID ({srid}) of the supplied value is different "
25
+ f"from the one of the column ({spatial_type.srid})"
26
+ )
27
+ return wkt_match.group(3)
28
+
29
+ if (
30
+ isinstance(bindvalue, _SpatialElement)
31
+ and bindvalue.srid != -1
32
+ and bindvalue.srid != spatial_type.srid
33
+ ):
34
+ raise ArgumentError(
35
+ f"The SRID ({bindvalue.srid}) of the supplied value is different "
36
+ f"from the one of the column ({spatial_type.srid})"
37
+ )
38
+
39
+ if isinstance(bindvalue, WKTElement):
40
+ bindvalue = bindvalue.as_wkt()
41
+ if bindvalue.srid <= 0:
42
+ bindvalue.srid = spatial_type.srid
43
+ return bindvalue
44
+ elif isinstance(bindvalue, WKBElement):
45
+ # With MariaDB we use Shapely to convert the WKBElement to an EWKT string
46
+ return to_shape(bindvalue).wkt
47
+ return bindvalue
@@ -5,6 +5,9 @@ requires = [
5
5
  "wheel",
6
6
  "setuptools_scm[toml]>=3.4",
7
7
  ]
8
+ build-backend = "setuptools.build_meta"
9
+
10
+ [tool.setuptools_scm]
8
11
 
9
12
  # BLACK
10
13
  [tool.black]
@@ -6,4 +6,4 @@ pytest
6
6
  pytest-cov
7
7
  pytest-html
8
8
  pytest-mypy
9
- rasterio
9
+ rasterio;implementation_name!='pypy'
@@ -4,8 +4,8 @@ COPY ./helpers/install_requirements.sh /
4
4
  RUN /install_requirements.sh
5
5
 
6
6
  COPY ./helpers/init_postgres.sh /
7
- env PGDATA="/var/lib/postgresql/data"
8
- env POSTGRES_PATH="/usr/lib/postgresql/16"
7
+ ENV PGDATA="/var/lib/postgresql/data"
8
+ ENV POSTGRES_PATH="/usr/lib/postgresql/16"
9
9
  RUN su postgres -c /init_postgres.sh
10
10
 
11
11
  ENV SPATIALITE_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/mod_spatialite.so"
@@ -0,0 +1,19 @@
1
+ FROM ubuntu:22.04
2
+
3
+ COPY ./helpers/install_requirements.sh /
4
+ RUN /install_requirements.sh
5
+
6
+ RUN apt-get update; apt-get install -y mariadb-server mariadb-client; rm -rf /var/lib/apt/lists/*;
7
+
8
+ COPY ./helpers/init_postgres.sh /
9
+ ENV PGDATA="/var/lib/postgresql/data"
10
+ ENV POSTGRES_PATH="/usr/lib/postgresql/16"
11
+ RUN su postgres -c /init_postgres.sh
12
+
13
+ ENV SPATIALITE_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/mod_spatialite.so"
14
+
15
+ COPY ./helpers/init_mariadb.sh /
16
+ RUN /init_mariadb.sh
17
+
18
+ COPY ./helpers/entrypoint.sh /
19
+ ENTRYPOINT ["/entrypoint.sh"]
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
5
+
6
+ cd "${SCRIPT_DIR}"
7
+ docker build -f Dockerfile_mariadb -t geoalchemy2-mariadb .
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ if [ $(whoami) != "root" ]; then
5
+ echo "must run as the root user"
6
+ exit 1
7
+ fi
8
+
9
+ echo "Starting mysql server"
10
+ /etc/init.d/mariadb start
11
+
12
+ echo "Waiting for mysql to start"
13
+ while ! mysqladmin ping -h 127.0.0.1 --silent; do
14
+ sleep 0.2
15
+ done
16
+
17
+ echo "Create the 'gis' role"
18
+ mariadb -e "CREATE USER 'gis'@'%' IDENTIFIED BY 'gis';"
19
+ mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'gis'@'%' WITH GRANT OPTION;"
20
+
21
+ echo "Create the 'gis' database"
22
+ mariadb -u gis --password=gis -e "CREATE DATABASE gis;"
@@ -6,9 +6,10 @@ if [ $(whoami) != "root" ]; then
6
6
  exit 1
7
7
  fi
8
8
 
9
+ echo "Starting mysql server"
9
10
  /etc/init.d/mysql start
10
11
 
11
- echo "waiting for mysql to start"
12
+ echo "Waiting for mysql to start"
12
13
  while ! mysqladmin ping -h 127.0.0.1 --silent; do
13
14
  sleep 0.2
14
15
  done
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bash
2
+
3
+ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
4
+
5
+ ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
+
7
+ mkdir -p "${SCRIPT_DIR}/output"
8
+
9
+ docker run --rm -it \
10
+ --mount type=bind,source="${ROOT}",target=/geoalchemy2_read_only,ro \
11
+ --mount type=bind,source="${SCRIPT_DIR}/output",target=/output \
12
+ geoalchemy2-mariadb