Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -371,16 +371,15 @@ jobs:
scheming.dataset_schemas = ckanext.datapusher_plus:dataset-druf.yaml
scheming.presets = ckanext.scheming:presets.json
scheming.dataset_fallback = false
ckanext.datapusher_plus.use_proxy = false
ckanext.datapusher_plus.download_proxy =
ckanext.datapusher_plus.ssl_verify = false
ckanext.datapusher_plus.upload_log_level = INFO
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsxb xlsm ods geojson shp qgis zip
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsb xlsm ods geojson shp qgis zip
# CKAN's bundled test-core.ini sets the legacy `ckan.datapusher.formats` key, which DPP's
# _submit_to_datapusher checks FIRST (`tk.config.get("ckan.datapusher.formats") or ...`).
# Without overriding it here, the legacy list (csv/xls/xlsx/tsv only) wins and DPP silently
# refuses to auto-submit ssv/tab/ods/geojson/shp/qgis/zip resources.
ckan.datapusher.formats = csv tsv tab ssv xls xlsx xlsxb xlsm ods geojson shp qgis zip
ckan.datapusher.formats = csv tsv tab ssv xls xlsx xlsb xlsm ods geojson shp qgis zip
ckanext.datapusher_plus.pii_screening = false
ckanext.datapusher_plus.pii_found_abort = false
ckanext.datapusher_plus.pii_regex_resource_id_or_alias =
Expand Down Expand Up @@ -717,7 +716,7 @@ jobs:
ssv) echo "$name|$file_url|SSV|text/csv|SSV: $filename" >> /tmp/test_files.txt ;;
xls) echo "$name|$file_url|XLS|application/vnd.ms-excel|XLS: $filename" >> /tmp/test_files.txt ;;
xlsx) echo "$name|$file_url|XLSX|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet|XLSX: $filename" >> /tmp/test_files.txt ;;
xlsxb) echo "$name|$file_url|XLSXB|application/vnd.ms-excel.sheet.binary.macroEnabled.12|XLSXB: $filename" >> /tmp/test_files.txt ;;
xlsb) echo "$name|$file_url|XLSB|application/vnd.ms-excel.sheet.binary.macroEnabled.12|XLSB: $filename" >> /tmp/test_files.txt ;;
xlsm) echo "$name|$file_url|XLSM|application/vnd.ms-excel.sheet.macroEnabled.12|XLSM: $filename" >> /tmp/test_files.txt ;;
ods) echo "$name|$file_url|ODS|application/vnd.oasis.opendocument.spreadsheet|ODS: $filename" >> /tmp/test_files.txt ;;
geojson) echo "$name|$file_url|GEOJSON|application/geo+json|GeoJSON: $filename" >> /tmp/test_files.txt ;;
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,11 @@ jobs:
scheming.dataset_schemas = ckanext.datapusher_plus:dataset-druf.yaml
scheming.presets = ckanext.scheming:presets.json
scheming.dataset_fallback = false
ckanext.datapusher_plus.use_proxy = false
ckanext.datapusher_plus.download_proxy =
ckanext.datapusher_plus.download_proxy =
ckanext.datapusher_plus.ssl_verify = false
# supports INFO, DEBUG, TRACE - use DEBUG or TRACE when debugging scheming Formulas
ckanext.datapusher_plus.upload_log_level = INFO
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsxb xlsm ods geojson shp qgis zip
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsb xlsm ods geojson shp qgis zip
ckanext.datapusher_plus.pii_screening = false
ckanext.datapusher_plus.pii_found_abort = false
ckanext.datapusher_plus.pii_regex_resource_id_or_alias =
Expand Down
107 changes: 83 additions & 24 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,86 @@
name: Tests
on: [push, pull_request]
name: Unit Tests

on:
push:
branches: [main, dev]
pull_request:
branches: [main]
workflow_dispatch:

concurrency:
group: dp-unit-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
QSV_VER: "20.1.0"

jobs:
test:
strategy:
matrix:
python-version: [2.7, 3.6, 3.7, 3.8, 3.9]
fail-fast: false
name: Python ${{ matrix.python-version }}
unit-tests:
name: Unit suite (Python 3.10, CKAN 2.11)
runs-on: ubuntu-latest
timeout-minutes: 30
# The unit suite imports ckan.plugins.toolkit and reads test-core.ini,
# so it needs a full CKAN install. The ckan/ckan-dev:2.11 image ships
# that (Python 3.10). A 3.11-3.13 matrix would mean building CKAN from
# source per version — tracked as a separate follow-up; pyproject
# already classifies 3.10-3.13 support.
container:
image: ckan/ckan-dev:2.11
options: --user root
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install requirements (Python 2)
if: ${{ matrix.python-version == '2.7' }}
run: pip install -r requirements-dev-py2.txt
- name: Install requirements (Python 3)
if: ${{ matrix.python-version != '2.7' }}
run: pip install -r requirements-dev.txt
- name: Run tests
run: pytest --cov=datapusher --cov-append --cov-report=xml --disable-warnings tests
- name: Upload coverage report to codecov
uses: codecov/codecov-action@v1
with:
file: ./coverage.xml
- name: Install system dependencies
run: |
apt-get update -y
apt-get install -y \
build-essential git wget unzip \
gdal-bin libgdal-dev libspatialindex-dev libgeos-dev libproj-dev \
libxslt1-dev libxml2-dev libffi-dev libpq-dev zlib1g-dev

- name: Checkout datapusher-plus
uses: actions/checkout@v4

- name: Install Python dependencies and datapusher-plus
run: |
set -eu
pip install --upgrade pip
# GDAL python binding must match the system libgdal version.
pip install "GDAL==$(gdal-config --version)"
pip install -r requirements.txt -r requirements-dev.txt
pip install -e .

- name: Install qsv
run: |
set -eu
cd /tmp
QSV_ZIP="qsv-${QSV_VER}-x86_64-unknown-linux-musl.zip"
wget -q "https://github.com/dathere/qsv/releases/download/${QSV_VER}/${QSV_ZIP}" -O qsv.zip
unzip -qo qsv.zip
# Install as /usr/local/bin/qsvdp so QSV_BIN is stable regardless
# of whether the archive ships `qsvdp` or `qsv`.
if [ -f qsvdp ]; then SRC_BIN=qsvdp
elif [ -f qsv ]; then SRC_BIN=qsv
else echo "ERROR: no qsv binary in archive"; ls -la; exit 1; fi
chmod +x "$SRC_BIN"
mv -f "$SRC_BIN" /usr/local/bin/qsvdp
/usr/local/bin/qsvdp --version

- name: Run unit test suite
env:
# The ckan-dev image's site-packages registers a pytest plugin
# (ckan.tests.pytest_ckan) that calls make_app() in
# pytest_sessionstart — needs a fully-configured CKAN. Disable
# plugin autoload so plain pytest runs.
PYTEST_DISABLE_PLUGIN_AUTOLOAD: "1"
QSV_BIN: /usr/local/bin/qsvdp
CKAN_INI: /srv/app/src/ckan/test-core.ini
run: |
set -eu
# -o addopts= overrides pyproject.toml's
# [tool.pytest.ini_options] --pdbcls IPython addopt.
# tests/integration is excluded — it needs the full
# docker-compose stack (Prefect, Postgres, Redis, Solr).
python3 -m pytest tests/ --ignore=tests/integration \
-o addopts= -p no:cacheprovider -q
38 changes: 18 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,23 +303,22 @@ ckan config-tool /etc/ckan/default/ckan.ini "ckanext.datapusher_plus.api_token=$

7. Add the rest of the DP+ config to your CKAN config (e.g. `/etc/ckan/default/ckan.ini`):

> **Note:** The block below is an illustrative example, not a list of defaults. Several values (e.g. `preview_rows`, `chunk_size`, `dedup`, `auto_index_threshold`, `ignore_file_hash`) differ from DP+'s actual defaults. The authoritative defaults live in [`config_declaration.yaml`](ckanext/datapusher_plus/config_declaration.yaml). Only set the keys you actually want to override.
> **Note:** The block below lists DP+'s settings at their current defaults, for reference. Set only the keys you actually want to change — pasting the whole block pins every value as an explicit override, so a later change to a DP+ default wouldn't reach you. Authoritative defaults live in [`config_declaration.yaml`](ckanext/datapusher_plus/config_declaration.yaml) and [`config.py`](ckanext/datapusher_plus/config.py).

```ini
# datapusher-plus settings
ckanext.datapusher_plus.use_proxy = false
ckanext.datapusher_plus.download_proxy =
ckanext.datapusher_plus.ssl_verify = false
ckanext.datapusher_plus.ssl_verify = true
# supports INFO, DEBUG, TRACE - use DEBUG or TRACE when debugging scheming Formulas
ckanext.datapusher_plus.upload_log_level = INFO
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx ods geojson shp qgis zip
ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsm xlsb ods geojson shp qgis zip
ckanext.datapusher_plus.pii_screening = false
ckanext.datapusher_plus.pii_found_abort = false
ckanext.datapusher_plus.pii_regex_resource_id_or_alias =
ckanext.datapusher_plus.pii_show_candidates = false
ckanext.datapusher_plus.pii_quick_screen = false
ckanext.datapusher_plus.qsv_bin = /usr/local/bin/qsvdp
ckanext.datapusher_plus.preview_rows = 100
ckanext.datapusher_plus.preview_rows = 0
ckanext.datapusher_plus.download_timeout = 300
ckanext.datapusher_plus.max_content_length = 1256000000000
ckanext.datapusher_plus.chunk_size = 16384
Expand All @@ -330,7 +329,7 @@ ckanext.datapusher_plus.unsafe_prefix = unsafe_
ckanext.datapusher_plus.reserved_colnames = _id
ckanext.datapusher_plus.prefer_dmy = false
ckanext.datapusher_plus.ignore_file_hash = true
ckanext.datapusher_plus.auto_index_threshold = 3
ckanext.datapusher_plus.auto_index_threshold = 10
ckanext.datapusher_plus.auto_index_dates = true
ckanext.datapusher_plus.auto_unique_index = true
ckanext.datapusher_plus.summary_stats_options =
Expand All @@ -343,11 +342,11 @@ ckanext.datapusher_plus.auto_alias = true
ckanext.datapusher_plus.auto_alias_unique = false
ckanext.datapusher_plus.copy_readbuffer_size = 1048576
ckanext.datapusher_plus.type_mapping = {"String": "text", "Integer": "numeric","Float": "numeric","DateTime": "timestamp","Date": "date","NULL": "text"}
ckanext.datapusher_plus.auto_spatial_simplication = true
ckanext.datapusher_plus.spatial_simplication_relative_tolerance = 0.1
ckanext.datapusher_plus.auto_spatial_simplification = true
ckanext.datapusher_plus.spatial_simplification_relative_tolerance = 0.1
ckanext.datapusher_plus.latitude_fields = latitude,lat
ckanext.datapusher_plus.longitude_fields = longitude,long,lon
ckanext.datapusher_plus.jinja2_bytecode_cache_dir = /tmp/jinja2_butecode_cache
ckanext.datapusher_plus.longitude_fields = longitude,lon
ckanext.datapusher_plus.jinja2_bytecode_cache_dir = /tmp/jinja2_bytecode_cache
ckanext.datapusher_plus.auto_unzip_one_file = true
```

Expand Down Expand Up @@ -412,22 +411,21 @@ scheming.dataset_schemas = ckanext.datapusher_plus:dataset-druf.yaml

Configure DP+ numerous settings. See [config.py](ckanext/datapusher_plus/config.py) and [`config_declaration.yaml`](ckanext/datapusher_plus/config_declaration.yaml) for details.

> **Note:** The block below is an illustrative example, not a list of defaults. Several values differ from DP+'s actual defaults — see [`config_declaration.yaml`](ckanext/datapusher_plus/config_declaration.yaml) for the authoritative defaults. Only set the keys you actually want to override.
> **Note:** The block below lists DP+'s settings at their current defaults, for reference. Set only the keys you actually want to change — pasting the whole block pins every value as an explicit override, so a later change to a DP+ default wouldn't reach you. Authoritative defaults live in [`config_declaration.yaml`](ckanext/datapusher_plus/config_declaration.yaml) and [`config.py`](ckanext/datapusher_plus/config.py).

>```ini
> ckanext.datapusher_plus.use_proxy = false
> ckanext.datapusher_plus.download_proxy =
> ckanext.datapusher_plus.ssl_verify = false
> ckanext.datapusher_plus.ssl_verify = true
> # supports INFO, DEBUG, TRACE - use DEBUG or TRACE when debugging scheming Formulas
> ckanext.datapusher_plus.upload_log_level = INFO
> ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx ods geojson shp qgis zip
> ckanext.datapusher_plus.formats = csv tsv tab ssv xls xlsx xlsm xlsb ods geojson shp qgis zip
> ckanext.datapusher_plus.pii_screening = false
> ckanext.datapusher_plus.pii_found_abort = false
> ckanext.datapusher_plus.pii_regex_resource_id_or_alias =
> ckanext.datapusher_plus.pii_show_candidates = false
> ckanext.datapusher_plus.pii_quick_screen = false
> ckanext.datapusher_plus.qsv_bin = /usr/local/bin/qsvdp
> ckanext.datapusher_plus.preview_rows = 100
> ckanext.datapusher_plus.preview_rows = 0
> ckanext.datapusher_plus.download_timeout = 300
> ckanext.datapusher_plus.max_content_length = 1256000000000
> ckanext.datapusher_plus.chunk_size = 16384
Expand All @@ -438,7 +436,7 @@ Configure DP+ numerous settings. See [config.py](ckanext/datapusher_plus/config.
> ckanext.datapusher_plus.reserved_colnames = _id
> ckanext.datapusher_plus.prefer_dmy = false
> ckanext.datapusher_plus.ignore_file_hash = true
> ckanext.datapusher_plus.auto_index_threshold = 3
> ckanext.datapusher_plus.auto_index_threshold = 10
> ckanext.datapusher_plus.auto_index_dates = true
> ckanext.datapusher_plus.auto_unique_index = true
> ckanext.datapusher_plus.summary_stats_options =
Expand All @@ -451,11 +449,11 @@ Configure DP+ numerous settings. See [config.py](ckanext/datapusher_plus/config.
> ckanext.datapusher_plus.auto_alias_unique = false
> ckanext.datapusher_plus.copy_readbuffer_size = 1048576
> ckanext.datapusher_plus.type_mapping = {"String": "text", "Integer": "numeric","Float": "numeric","DateTime": "timestamp","Date": "date","NULL": "text"}
> ckanext.datapusher_plus.auto_spatial_simplication = true
> ckanext.datapusher_plus.spatial_simplication_relative_tolerance = 0.1
> ckanext.datapusher_plus.auto_spatial_simplification = true
> ckanext.datapusher_plus.spatial_simplification_relative_tolerance = 0.1
> ckanext.datapusher_plus.latitude_fields = latitude,lat
> ckanext.datapusher_plus.longitude_fields = longitude,long,lon
> ckanext.datapusher_plus.jinja2_bytecode_cache_dir = /tmp/jinja2_butecode_cache
> ckanext.datapusher_plus.longitude_fields = longitude,lon
> ckanext.datapusher_plus.jinja2_bytecode_cache_dir = /tmp/jinja2_bytecode_cache
> ckanext.datapusher_plus.auto_unzip_one_file = true
> ckanext.datapusher_plus.api_token = <CKAN service account token for CKAN user with sysadmin privileges>
>```
Expand Down
12 changes: 10 additions & 2 deletions ckanext/datapusher_plus/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
# Supported formats
FORMATS = tk.config.get(
"ckanext.datapusher_plus.formats",
["csv", "tsv", "tab", "ssv", "xls", "xlsx", "ods", "geojson", "shp", "qgis", "zip"],
["csv", "tsv", "tab", "ssv", "xls", "xlsx", "xlsm", "xlsb", "ods", "geojson", "shp", "qgis", "zip"],
)
Comment thread
jqnatividad marked this conversation as resolved.
if isinstance(FORMATS, str):
FORMATS = FORMATS.split()
Expand Down Expand Up @@ -253,8 +253,16 @@
AUTO_SPATIAL_SIMPLIFICATION = tk.asbool(
tk.config.get("ckanext.datapusher_plus.auto_spatial_simplification", True)
)
# Lowercase key is canonical. The legacy UPPERCASE key
# (``...SPATIAL_SIMPLIFICATION_RELATIVE_TOLERANCE``) is still honoured
# as a fallback so deployments that set it don't silently lose the
# setting — same backward-compat shape as ``SSL_VERIFY`` above.
SPATIAL_SIMPLIFICATION_RELATIVE_TOLERANCE = tk.config.get(
"ckanext.datapusher_plus.SPATIAL_SIMPLIFICATION_RELATIVE_TOLERANCE", "0.1"
"ckanext.datapusher_plus.spatial_simplification_relative_tolerance",
tk.config.get(
"ckanext.datapusher_plus.SPATIAL_SIMPLIFICATION_RELATIVE_TOLERANCE",
"0.1",
),
)

# Latitude and longitude column names
Expand Down
22 changes: 7 additions & 15 deletions ckanext/datapusher_plus/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import ckanext.datapusher_plus.logic.action as action
import ckanext.datapusher_plus.logic.auth as auth
import ckanext.datapusher_plus.cli as cli
import ckanext.datapusher_plus.config as conf

tk = p.toolkit

Expand Down Expand Up @@ -139,22 +140,13 @@ def _submit_to_datapusher(self, resource_dict: dict[str, Any]):
)
if not supported_formats:
log.debug(
"No supported formats configured,\
using DataPusher Plus internals"
"No supported formats configured; "
"using the DataPusher+ FORMATS default."
)
supported_formats = [
"csv",
"xls",
"xlsx",
"tsv",
"ssv",
"tab",
"ods",
"geojson",
"shp",
"qgis",
"zip",
]
# Reuse the single canonical default from config.py rather
# than a second hardcoded list that would silently drift
# (e.g. miss xlsm/xlsb the way this list once did).
supported_formats = conf.FORMATS

submit = (
resource_format
Expand Down
Loading
Loading