GeoAlchemy2 0.15.1__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.
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/workflows/test_and_publish.yml +58 -25
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.pre-commit-config.yaml +4 -6
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/CHANGES.txt +12 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0/GeoAlchemy2.egg-info}/PKG-INFO +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/SOURCES.txt +5 -0
- {geoalchemy2-0.15.1/GeoAlchemy2.egg-info → geoalchemy2-0.16.0}/PKG-INFO +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/admin.rst +2 -2
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/index.rst +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/mysql.py +74 -6
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/elements.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/__init__.py +4 -4
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/__init__.py +1 -0
- geoalchemy2-0.16.0/geoalchemy2/types/dialects/mariadb.py +47 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/sqlite.py +5 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/pyproject.toml +3 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/requirements.txt +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/Dockerfile +2 -2
- geoalchemy2-0.16.0/test_container/Dockerfile_mariadb +19 -0
- geoalchemy2-0.16.0/test_container/build_mariadb.sh +7 -0
- geoalchemy2-0.16.0/test_container/helpers/init_mariadb.sh +22 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/helpers/init_mysql.sh +2 -1
- geoalchemy2-0.16.0/test_container/run_mariadb.sh +12 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/__init__.py +4 -5
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/conftest.py +85 -25
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_orm_mapped_v2.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_summarystatsagg.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/schema_fixtures.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_alembic_migrations.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functional.py +107 -15
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functional_mysql.py +19 -8
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functional_postgresql.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functional_sqlite.py +48 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_pickle.py +1 -1
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tox.ini +7 -2
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.codespellrc +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.coveragerc +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.flake8 +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/ISSUE_TEMPLATE/how_to_use.yaml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/dependabot.yml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.github/pull_request_template.md +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.gitignore +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/.readthedocs.yaml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/COPYING.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/dependency_links.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/not-zip-safe +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/requires.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2.egg-info/top_level.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/GeoAlchemy2_dev.yml +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/MANIFEST.in +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/README.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/RELEASE.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/TEST.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/Makefile +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_static/geoalchemy.png +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_static/geoalchemy.svg +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_static/geoalchemy_small.png +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_static/geoalchemy_small.svg +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_templates/sidebar-about.html +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_templates/sidebar-links.html +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_templates/sidebar-logo.html +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/LICENSE +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/README +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/flask/layout.html +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/flask/relations.html +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/flask/static/flasky.css_t +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/flask/static/small_flask.css +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/_themes/flask/theme.conf +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/alembic.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/alembic_helpers.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/changelog.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/conf.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/core_tutorial.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/elements.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/make.bat +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/migrate.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/orm_tutorial.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/shape.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/spatial_functions.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/spatial_operators.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/spatialite_tutorial.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/doc/types.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/generate_type_stubs.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/__init__.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/_functions.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/_functions_helpers.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/__init__.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/__init__.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/common.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/geopackage.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/postgresql.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/admin/dialects/sqlite.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/alembic_helpers.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/comparator.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/exc.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/functions.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/functions.pyi +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/py.typed +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/shape.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/common.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/geopackage.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/mysql.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/types/dialects/postgresql.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/geoalchemy2/utils.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/requirements-doc.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/requirements-mypy.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/requirements-rtd.txt +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/setup.cfg +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/setup.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/.dockerignore +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/.gitignore +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/build.sh +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/helpers/entrypoint.sh +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/helpers/init_postgres.sh +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/helpers/install_requirements.sh +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/test_container/run.sh +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/alembic_config/alembic.ini +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/data/spatialite_ge_4.sqlite +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/data/spatialite_geopackage.gpkg +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/data/spatialite_lt_4.sqlite +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/README.rst +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/__init__.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_decipher_raster.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_disable_wrapping.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_insert_raster.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_length_at_insert.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_raster_transform.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_specific_compilation.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/gallery/test_type_decorator.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_comparator.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_elements.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functional_geopackage.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_functions.py +0 -0
- {geoalchemy2-0.15.1 → geoalchemy2-0.16.0}/tests/test_shape.py +0 -0
- {geoalchemy2-0.15.1 → 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
|
64
|
-
- name:
|
65
|
-
uses:
|
94
|
+
# Setup Python
|
95
|
+
- name: Set up Python ${{ matrix.python-version }}
|
96
|
+
uses: actions/setup-python@v5
|
66
97
|
with:
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
#
|
99
|
-
- name:
|
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
|
-
|
102
|
-
|
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: /
|
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,8 +1,6 @@
|
|
1
|
-
default_language_version:
|
2
|
-
python: python3.8
|
3
1
|
repos:
|
4
2
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
5
|
-
rev: v4.
|
3
|
+
rev: v4.6.0
|
6
4
|
hooks:
|
7
5
|
- id: check-added-large-files
|
8
6
|
- id: check-case-conflict
|
@@ -17,11 +15,11 @@ repos:
|
|
17
15
|
hooks:
|
18
16
|
- id: isort
|
19
17
|
- repo: https://github.com/psf/black
|
20
|
-
rev: 24.
|
18
|
+
rev: 24.4.2
|
21
19
|
hooks:
|
22
20
|
- id: black
|
23
21
|
- repo: https://github.com/codespell-project/codespell
|
24
|
-
rev: v2.
|
22
|
+
rev: v2.3.0
|
25
23
|
hooks:
|
26
24
|
- id: codespell
|
27
25
|
- repo: https://github.com/PyCQA/pydocstyle
|
@@ -31,7 +29,7 @@ repos:
|
|
31
29
|
additional_dependencies: ["tomli"]
|
32
30
|
exclude: "tests"
|
33
31
|
- repo: https://github.com/PyCQA/flake8
|
34
|
-
rev: 7.
|
32
|
+
rev: 7.1.0
|
35
33
|
hooks:
|
36
34
|
- id: flake8
|
37
35
|
ci:
|
@@ -1,6 +1,18 @@
|
|
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
|
+
|
11
|
+
0.15.2
|
12
|
+
------
|
13
|
+
|
14
|
+
* Fix: Can handle negative coordinates with Spatialite @adrien-berchet (#517)
|
15
|
+
|
4
16
|
0.15.1
|
5
17
|
------
|
6
18
|
|
@@ -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
|
@@ -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,
|
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)
|
@@ -117,7 +117,7 @@ class WKTElement(_SpatialElement):
|
|
117
117
|
"""
|
118
118
|
|
119
119
|
_REMOVE_SRID = re.compile("(SRID=([0-9]+); ?)?(.*)")
|
120
|
-
SPLIT_WKT_PATTERN = re.compile(r"((SRID=\d+) *; *)?([\w ]+) *(\([
|
120
|
+
SPLIT_WKT_PATTERN = re.compile(r"((SRID=\d+) *; *)?([\w ]+) *(\([-\d\. ,\(\)]+\))")
|
121
121
|
|
122
122
|
geom_from: str = "ST_GeomFromText"
|
123
123
|
geom_from_extended_version: str = "ST_GeomFromEWKT"
|
@@ -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.
|
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
|
-
|
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
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""This module defines specific functions for SQLite dialect."""
|
2
2
|
|
3
3
|
import re
|
4
|
+
import warnings
|
4
5
|
|
5
6
|
from geoalchemy2.elements import RasterElement
|
6
7
|
from geoalchemy2.elements import WKBElement
|
@@ -12,6 +13,10 @@ def format_geom_type(wkt, default_srid=None):
|
|
12
13
|
"""Format the Geometry type for SQLite."""
|
13
14
|
match = re.match(WKTElement.SPLIT_WKT_PATTERN, wkt)
|
14
15
|
if match is None:
|
16
|
+
warnings.warn(
|
17
|
+
"The given WKT could not be parsed by GeoAlchemy2, this could lead to undefined "
|
18
|
+
f"behavior with Z, M or ZM geometries or with incorrect SRID. The WKT string is: {wkt}"
|
19
|
+
)
|
15
20
|
return wkt
|
16
21
|
_, srid, geom_type, coords = match.groups()
|
17
22
|
geom_type = geom_type.replace(" ", "")
|
@@ -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
|
-
|
8
|
-
|
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,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 "
|
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
|
@@ -5,8 +5,7 @@ import shutil
|
|
5
5
|
import sys
|
6
6
|
|
7
7
|
import pytest
|
8
|
-
from packaging import
|
9
|
-
from pkg_resources import parse_version
|
8
|
+
from packaging.version import parse as parse_version
|
10
9
|
from sqlalchemy import __version__ as SA_VERSION
|
11
10
|
from sqlalchemy import create_engine
|
12
11
|
from sqlalchemy import select as raw_select
|
@@ -30,9 +29,9 @@ class test_only_with_dialects:
|
|
30
29
|
|
31
30
|
def get_postgis_major_version(bind):
|
32
31
|
try:
|
33
|
-
return
|
32
|
+
return parse_version(bind.execute(func.postgis_lib_version()).scalar()).major
|
34
33
|
except OperationalError:
|
35
|
-
return
|
34
|
+
return parse_version("0").major
|
36
35
|
|
37
36
|
|
38
37
|
def get_postgres_major_version(bind):
|
@@ -81,7 +80,7 @@ def skip_pypy(msg=None):
|
|
81
80
|
|
82
81
|
|
83
82
|
def select(args):
|
84
|
-
if
|
83
|
+
if parse_version(SA_VERSION) < parse_version("1.4"):
|
85
84
|
return raw_select(args)
|
86
85
|
else:
|
87
86
|
return raw_select(*args)
|