Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend Status Badges #224

Open
wants to merge 175 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
175 commits
Select commit Hold shift + click to select a range
d59f4ea
Upgrade to GitHub-native Dependabot
dependabot-preview[bot] Apr 28, 2021
8ecfa62
Merge pull request #29 from qld-gov-au/dependabot/add-v2-config-file
duttonw Apr 30, 2021
79d6ea0
Merge pull request #31 from qld-gov-au/develop
ThrawnCA Jun 28, 2021
0b1b9c5
Merge pull request #33 from qld-gov-au/develop
ThrawnCA Oct 27, 2021
450c8ab
Merge pull request #35 from qld-gov-au/develop
ThrawnCA Nov 1, 2021
a4e350e
Merge pull request #37 from qld-gov-au/develop
ThrawnCA May 5, 2022
e336c83
Merge pull request #39 from qld-gov-au/develop
ThrawnCA Aug 17, 2022
031de33
Merge pull request #42 from qld-gov-au/develop
ThrawnCA Sep 7, 2022
963ada1
fix workflow
duttonw Nov 8, 2022
a938b26
Merge pull request #43 from qld-gov-au/develop
duttonw Mar 8, 2023
9f96e16
[QOLDEV-347] apply 'str' fallback type correctly, #182
ThrawnCA Apr 17, 2023
cf04a5c
[QOLDEV-347] fix validation errors on empty strings, #182
ThrawnCA Apr 17, 2023
f4f3665
Merge branch 'master' of https://github.com/qld-gov-au/ckanext-xloade…
ThrawnCA Apr 17, 2023
b8b9914
[QOLDEV-347] add tests for edge cases we're fixing
ThrawnCA Apr 17, 2023
b62aa6c
[QOLDEV-347] tighten Flake8 rules
ThrawnCA Apr 17, 2023
93aaf0c
Merge pull request #44 from qld-gov-au/QOLDEV-347-fix-ckan-2.10
ThrawnCA Apr 17, 2023
939ff6b
[QOLSVC-1863] truncate on-page XLoader logs if there are too many
ThrawnCA May 19, 2023
05b2b88
[QOLSVC-1863] make XLoader log truncation configurable
ThrawnCA May 19, 2023
d937dea
[QOLSVC-1863] adjust XLoader log truncation appearance
ThrawnCA May 19, 2023
288b0ab
[QOLSVC-1863] ignore negative numbers of logs to display
ThrawnCA May 19, 2023
5481f8b
Merge pull request #46 from qld-gov-au/QOLSVC-1863-xloader-page-timeout
ThrawnCA May 19, 2023
99d538c
Merge pull request #45 from qld-gov-au/develop
ThrawnCA May 23, 2023
b351e95
[QOLDEV-424] add unit test for parsing CSV file with commas inside qu…
ThrawnCA May 26, 2023
83e1b86
[QOLDEV-424] add unit test for parsing CSV file with commas inside qu…
ThrawnCA May 26, 2023
9ae1b26
[QOLDEV-424] add unit test for parsing CSV file with a mixture of sin…
ThrawnCA May 28, 2023
0829801
[QOLDEV-424] reuse sample size constant for both loading methods
ThrawnCA May 29, 2023
b444c6c
[QOLDEV-424] increase CSV sample size to better match Messytables beh…
ThrawnCA May 29, 2023
37a2a54
[QOLDEV-424] set default CSV sample size in config
ThrawnCA May 29, 2023
51fffad
[QOLDEV-424] alter sample mixed-quotes file to use generic data
ThrawnCA May 29, 2023
a7ead01
Merge pull request #47 from qld-gov-au/QOLDEV-424-fix-desbt-parsing
ThrawnCA May 29, 2023
818aee9
Merge branch 'develop' into feature/qld-gov-au/conditional-datastore-tab
JVickery-TBS Jun 19, 2023
712edd4
Merge pull request #50 from JVickery-TBS/feature/qld-gov-au/condition…
ThrawnCA Jun 19, 2023
4656f06
[QOLDEV-424] fix tests to avoid hardcoding resource IDs
ThrawnCA Jul 28, 2023
19d4b96
Merge pull request #51 from qld-gov-au/QOLDEV-424-fix-desbt-parsing
ThrawnCA Jul 28, 2023
b23b22c
[QOLDEV-424] ensure consistent column name ordering in tests
ThrawnCA Jul 28, 2023
b171d3f
Merge pull request #52 from qld-gov-au/QOLDEV-424-fix-desbt-parsing
ThrawnCA Jul 28, 2023
971a3ed
Merge pull request #48 from qld-gov-au/develop
ThrawnCA Jul 28, 2023
bef37d2
[QOLDEV-490] use fast loading for resources that already have a data …
ThrawnCA Aug 1, 2023
9200968
[QOLDEV-490] extend job timeout if type guessing is needed
ThrawnCA Aug 1, 2023
1ccd71b
Merge pull request #53 from qld-gov-au/QOLDEV-490-fast-load-enhancements
ThrawnCA Aug 1, 2023
507508e
[QOLDEV-490] always use COPY for large files
ThrawnCA Aug 1, 2023
d425e31
adjust datastore tab link to work on current CKAN 2.10
ThrawnCA Aug 1, 2023
03989cc
Merge pull request #54 from qld-gov-au/QOLDEV-490-fast-load-enhancements
ThrawnCA Aug 6, 2023
6df99ea
[QOLDEV-490] fix timeout extension
ThrawnCA Aug 6, 2023
388bc7b
[QOLDEV-490] fix load method logic
ThrawnCA Aug 6, 2023
340778b
Merge pull request #55 from qld-gov-au/QOLDEV-490-fast-load-enhancements
ThrawnCA Aug 7, 2023
1938a07
Merge pull request #56 from qld-gov-au/develop
ThrawnCA Aug 7, 2023
da8c602
[QOLDEV-554] fix overly aggressive timestamp parsing
ThrawnCA Aug 22, 2023
13d076f
[QOLDEV-554] skip conversion if value already has the desired type
ThrawnCA Aug 22, 2023
03967f7
[QOLDEV-554] add unit test for time ranges being preserved as strings
ThrawnCA Aug 22, 2023
f5fad5b
[QOLDEV-554] add extra data to the unit test
ThrawnCA Aug 22, 2023
e6b05c6
[QOLDEV-554] restrict recognised date types
ThrawnCA Aug 22, 2023
00ee904
[QOLDEV-554] fix missing comma
ThrawnCA Aug 22, 2023
e54b212
[QOLDEV-554] replace custom parser with post-processing
ThrawnCA Aug 22, 2023
3854f72
Merge pull request #57 from qld-gov-au/QOLDEV-554-timestamp-error
ThrawnCA Aug 22, 2023
28ee0f4
Merge pull request #58 from qld-gov-au/develop
ThrawnCA Aug 23, 2023
d40e245
[QOLSVC-3224] handle any falsy url_type the same way as empty string
ThrawnCA Oct 11, 2023
46441ed
Merge pull request #59 from qld-gov-au/QOLSVC-3224-missing-datastore-…
ThrawnCA Oct 11, 2023
bdb5166
Merge pull request #60 from qld-gov-au/develop
ThrawnCA Oct 11, 2023
5898000
[QOLSVC-2984] add test for ISO-8859-1 CSV encoding
ThrawnCA Oct 23, 2023
af6aea6
[QOLSVC-2984] handle Latin-1 encoding if UTF-8 fails
ThrawnCA Oct 23, 2023
25caed1
Merge pull request #61 from qld-gov-au/QOLSVC-2984_non-utf8
ThrawnCA Oct 27, 2023
121592b
[QOLSVC-2984] handle Latin-1 encoding during 'save' call
ThrawnCA Oct 31, 2023
e1cf13e
Merge pull request #63 from qld-gov-au/QOLSVC-2984_non-utf8
ThrawnCA Oct 31, 2023
f4282d6
Merge remote-tracking branch 'ckan:ckanext-xloader:master' into qld-g…
duttonw Oct 31, 2023
34577df
Merge pull request #64 from qld-gov-au/include-upstream
duttonw Nov 1, 2023
202d130
QOLSVC-2984 use chardet library to guess format type and use it if it…
duttonw Nov 1, 2023
cb54151
QOLSVC-2984 updates per comments
duttonw Nov 1, 2023
ba6e2e7
Merge remote-tracking branch 'origin/upstream_updates' into QOLSVC-29…
duttonw Nov 1, 2023
d276791
Merge pull request #65 from qld-gov-au/QOLSVC-2984_guessEncodingBetter
duttonw Nov 1, 2023
cd32d61
[QOLSVC-2984] sniff using Windows-1252 encoding rather than Latin-1
ThrawnCA Nov 1, 2023
3340e02
Merge pull request #66 from qld-gov-au/QOLSVC-2984_non-utf8
ThrawnCA Nov 2, 2023
d0013aa
Merge pull request #62 from qld-gov-au/develop
ThrawnCA Nov 2, 2023
743b026
Merge branch 'master-queensland' into feature/qld-gov-au/remove-unsup…
JVickery-TBS Nov 8, 2023
c87a310
Merge branch 'master-queensland' into feature/qld-gov-au/delete-datas…
JVickery-TBS Nov 8, 2023
ae354e5
feat(templates): added missing csrf field;
JVickery-TBS Nov 8, 2023
340f629
feat(templates): added missing form action;
JVickery-TBS Nov 8, 2023
c2059d6
fix(semantics): removed word table;
JVickery-TBS Nov 9, 2023
93b14b1
removal(views): replace ckanapi with toolkit;
JVickery-TBS Nov 9, 2023
beb3be7
feat(dev): code improvements;
JVickery-TBS Nov 9, 2023
2e50f7c
removal(import): removed ckanapi import;
JVickery-TBS Nov 9, 2023
0a210cf
fix(dev): falsy values for datastore and variable logging;
JVickery-TBS Nov 9, 2023
8328132
fix(dev): falsy for url type;
JVickery-TBS Nov 10, 2023
0bc5f9b
fix(dev): falsy fix, removed lower from logging;
JVickery-TBS Nov 15, 2023
93ae552
feat(views): check resource owner;
JVickery-TBS Nov 16, 2023
2f5314d
fix(views): syntax, and template;
JVickery-TBS Nov 16, 2023
ea89015
Merge branch 'master-queensland' into fix/qld-gov-au/job-enqueue-prio…
JVickery-TBS Nov 16, 2023
8ea5328
fix(dev): check url_changed in domain implementation;
JVickery-TBS Nov 16, 2023
8ecf84a
Merge pull request #69 from JVickery-TBS/fix/qld-gov-au/job-enqueue-p…
ThrawnCA Nov 16, 2023
ba15d1e
Merge pull request #68 from JVickery-TBS/feature/qld-gov-au/delete-da…
ThrawnCA Nov 16, 2023
783c45d
fix datastore delete button layout
ThrawnCA Nov 24, 2023
b65cfeb
Merge pull request #70 from qld-gov-au/delete-datastore-button
ThrawnCA Nov 24, 2023
527ea50
[QOLSVC-3914] fix indentation to make Flake8 happy
ThrawnCA Dec 22, 2023
6d19b45
[QOLSVC-3914] truncate tables instead of dropping if fields are uncha…
ThrawnCA Dec 22, 2023
8fdfcc9
[QOLSVC-3914] extract truncation logic to a helper function
ThrawnCA Dec 22, 2023
c30c73b
[QOLSVC-3914] add more documentation
ThrawnCA Dec 22, 2023
0db407d
fix datastore delete action
ThrawnCA Dec 28, 2023
d5583a3
[QOLSVC-3914] add unit testing of Tabulator populating type overrides
ThrawnCA Jan 2, 2024
fa7f826
Merge pull request #74 from qld-gov-au/delete-datastore-button
ThrawnCA Jan 2, 2024
fbd6a08
Merge pull request #73 from qld-gov-au/QOLSVC-3902-reduce-deadlocks
ThrawnCA Jan 2, 2024
8ed9ce9
Merge pull request #72 from qld-gov-au/develop
ThrawnCA Jan 2, 2024
24033de
[QOLSVC-3902] reduce lock timeout to avoid deadlocks
ThrawnCA Jan 11, 2024
6cae283
Merge pull request #75 from qld-gov-au/QOLSVC-3902-reduce-deadlocks
ThrawnCA Jan 12, 2024
b7aa0e5
[QOLSVC-3902] replace try-finally structures with context manager
ThrawnCA Jan 12, 2024
3a47541
Merge pull request #76 from qld-gov-au/develop
ThrawnCA Jan 15, 2024
b483cce
Merge branch 'master-queensland' into fix/qld-gov-au/stringish-type-g…
JVickery-TBS Jan 15, 2024
97b04d1
Merge branch 'develop' of https://github.com/qld-gov-au/ckanext-xload…
ThrawnCA Jan 24, 2024
d39d5cd
[QOLSVC-3902] retry jobs that fail due to locking problems
ThrawnCA Jan 24, 2024
325b6f2
[QOLSVC-3902] pre-emptively lock resource for editing when updating m…
ThrawnCA Jan 24, 2024
fc7bcc6
Merge pull request #77 from qld-gov-au/QOLSVC-3902-reduce-deadlocks
ThrawnCA Jan 24, 2024
edcace5
[QOLDEV-708] document the PostgreSQL datestyle setting
ThrawnCA Jan 25, 2024
fd1ed50
Merge pull request #80 from qld-gov-au/QOLDEV-708-postgresql-datestyle
ThrawnCA Jan 25, 2024
afc45b7
Merge pull request #79 from qld-gov-au/develop
ThrawnCA Jan 25, 2024
29de39c
feat(misc): config description;
JVickery-TBS Jan 29, 2024
78145ab
Merge pull request #78 from JVickery-TBS/fix/qld-gov-au/stringish-typ…
ThrawnCA Jan 29, 2024
8b756c5
[QOLCHG-440] add another test case for type guessing
ThrawnCA Jan 30, 2024
8d6c169
[QOLCHG-440] include testing of '0' values in type guessing
ThrawnCA Jan 30, 2024
d2d6acf
[QOLCHG-440] allow zero to be recognised as a valid number
ThrawnCA Jan 30, 2024
217b443
Merge pull request #81 from qld-gov-au/QOLCHG-440-testing-errors
ThrawnCA Jan 31, 2024
523df62
[QOLSVC-4689] add CLI option to process datasets immediately, #202
ThrawnCA Jan 31, 2024
7fabca4
fix(syntax): flake8;
JVickery-TBS Jan 31, 2024
e454e90
Merge branch 'master-queensland' into feature/qld-gov-au/remove-unsup…
JVickery-TBS Jan 31, 2024
cef20a9
feat(tests): added new test;
JVickery-TBS Jan 31, 2024
9c79600
[QOLSVC-4689] add option to specify custom execution queue
ThrawnCA Jan 31, 2024
d7236fe
fix(tests): finalized test method;
JVickery-TBS Feb 1, 2024
80b2f45
[QOLSVC-4689] don't retry jobs on custom queues
ThrawnCA Feb 2, 2024
8ea4a4c
[QOLSVC-4689] add descriptive titles to queued XLoader jobs
ThrawnCA Feb 2, 2024
772f0bf
Merge pull request #82 from qld-gov-au/QOLSVC-4689-oft-locations
ThrawnCA Feb 2, 2024
8b6cab9
replace complex indirect fixtures with simple 'with' blocks
ThrawnCA Feb 2, 2024
9960e60
[QOLSVC-4689] make job titles more machine-readable
ThrawnCA Feb 2, 2024
696387e
Merge pull request #83 from qld-gov-au/QOLSVC-4689-oft-locations
ThrawnCA Feb 2, 2024
eba7676
Merge branch 'master' of https://github.com/ckan/ckanext-xloader into…
ThrawnCA Feb 2, 2024
967615e
Merge pull request #85 from qld-gov-au/merge-upstream
ThrawnCA Feb 2, 2024
497048d
Merge pull request #84 from qld-gov-au/develop
ThrawnCA Feb 2, 2024
60e9f34
Merge pull request #4 from qld-gov-au/feature/qld-gov-au/remove-unsup…
JVickery-TBS Feb 2, 2024
ee5760b
Merge pull request #67 from JVickery-TBS/feature/qld-gov-au/remove-un…
duttonw Feb 3, 2024
c1c3417
Merge pull request #86 from qld-gov-au/develop
ThrawnCA Feb 6, 2024
7605577
[QOLSVC-4959] try direct COPY if type guessing fails
ThrawnCA Feb 26, 2024
0d7232d
Merge pull request #87 from qld-gov-au/QOLSVC-4959-type-guessing-failure
ThrawnCA Feb 27, 2024
b1ef90a
[QOLSVC-5123] handle empty cells past end of row
ThrawnCA Mar 8, 2024
7857c1a
Merge pull request #89 from qld-gov-au/QOLSVC-5123-empty-columns
ThrawnCA Mar 8, 2024
3e169a8
[QOLSVC-5123] skip rows that are completely blank instead of erroring…
ThrawnCA Mar 15, 2024
541a343
[QOLSVC-5123] add unit tests for blank cells and lines
ThrawnCA Mar 15, 2024
0f79888
Merge pull request #90 from qld-gov-au/QOLSVC-5123-empty-columns
ThrawnCA Mar 15, 2024
fc38b56
Merge pull request #88 from qld-gov-au/develop
ThrawnCA Mar 15, 2024
a30ce5c
[QOLSVC-5551] restart all sequences when truncating table
ThrawnCA Apr 12, 2024
43c400b
Merge pull request #91 from qld-gov-au/QOLSVC-5551-reset-sequence-on-…
ThrawnCA Apr 12, 2024
ad1361b
Merge pull request #92 from qld-gov-au/develop
ThrawnCA Apr 12, 2024
e1619f5
[QOLSVC-3902] make deadlock handling slightly more forgiving
ThrawnCA Apr 28, 2024
310fc2b
Merge pull request #93 from qld-gov-au/QOLSVC-3902-reduce-deadlocks
ThrawnCA Apr 29, 2024
047ba79
Merge pull request #94 from qld-gov-au/develop
ThrawnCA May 1, 2024
f65a9c1
fix: dev-requirements.txt to reduce vulnerabilities
snyk-bot May 24, 2024
b78e476
fix: dev-requirements.txt to reduce vulnerabilities
snyk-bot Jun 22, 2024
8048086
fix: requirements.txt to reduce vulnerabilities
snyk-bot Jun 22, 2024
e66b2be
Merge pull request #99 from qld-gov-au/snyk-fix-b146b49f1bfcca8238b90…
ThrawnCA Jul 10, 2024
eec3299
Merge branch 'develop' of https://github.com/qld-gov-au/ckanext-xload…
ThrawnCA Jul 10, 2024
9315ed0
Merge branch 'develop' of https://github.com/qld-gov-au/ckanext-xload…
ThrawnCA Jul 10, 2024
ece1486
allow urllib3 to use the 1.x series depending on Python version
ThrawnCA Jul 11, 2024
68277e5
Merge pull request #100 from qld-gov-au/snyk-fix-d49eba2e68db7fd86d11…
ThrawnCA Jul 11, 2024
a5e77f0
Merge branch 'develop' of https://github.com/qld-gov-au/ckanext-xload…
ThrawnCA Jul 11, 2024
153d4e8
Merge pull request #95 from qld-gov-au/snyk-fix-110a30f34fefdcf77c73c…
ThrawnCA Jul 11, 2024
129416a
fix: requirements.txt to reduce vulnerabilities
snyk-bot Jul 13, 2024
17fbf43
fix: dev-requirements.txt to reduce vulnerabilities
snyk-bot Jul 13, 2024
9a9bb9b
Merge branch 'develop' of https://github.com/qld-gov-au/ckanext-xload…
ThrawnCA Jul 15, 2024
26b3aa2
Merge pull request #103 from qld-gov-au/snyk-fix-851688264b3f13bfae11…
ThrawnCA Jul 15, 2024
d941134
limit urllib3 to versions compatible with Python 3.7
ThrawnCA Jul 17, 2024
ac9d2bf
Merge pull request #102 from qld-gov-au/snyk-fix-705136bc5e6de16a7715…
ThrawnCA Jul 17, 2024
cc7e33c
feat(dev): implement IPipeValidation;
JVickery-TBS Jul 23, 2024
8186398
Merge pull request #104 from JVickery-TBS/feature/qld-gov-au/minified…
duttonw Jul 23, 2024
16eb59b
Merge pull request #105 from qld-gov-au/develop
duttonw Jul 29, 2024
e72cc37
feat(templates): status badges;
JVickery-TBS Aug 1, 2024
e7eee6d
fix(logic): reverse debug logic;
JVickery-TBS Aug 9, 2024
7a0db13
Merge remote-tracking branch 'qld-gov-au/master' into ckan/master(qld…
duttonw Oct 15, 2024
ded839c
Pin setuptools only for 2.9 to allow CICD to pass
duttonw Oct 15, 2024
2f817af
Merge branch 'qldGovAuToCkan' into feature/badges
ThrawnCA Oct 15, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:

steps:
- uses: actions/checkout@v4
- if: ${{ matrix.ckan-version == 2.9 }}
run: pip install "setuptools>=44.1.0,<71"
- name: Install requirements
run: |
pip install -r requirements.txt
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ CKAN version Compatibility
=============== =============
2.7 no longer supported (last supported version: 0.12.2)
2.8 no longer supported (last supported version: 0.12.2)
2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2))
2.9 yes (Python3) (last supported version for Python 2.7: 0.12.2)), Must: ``pip install "setuptools>=44.1.0,<71"``
2.10 yes
2.11 yes
=============== =============
Expand Down
33 changes: 33 additions & 0 deletions ckanext/xloader/config_declaration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,23 @@ groups:
to True.
type: bool
required: false
- key: ckanext.xloader.validation.requires_successful_report
default: False
example: True
description: |
Resources are required to pass Validation from the ckanext-validation
plugin to be able to get XLoadered.
type: bool
required: false
- key: ckanext.xloader.validation.enforce_schema
default: True
example: False
description: |
Resources are expected to have a Validation Schema, or use the default ones if not.
If this option is set to `False`, Resources that do not have
a Validation Schema will be treated like they do not require Validation.
See https://github.com/frictionlessdata/ckanext-validation?tab=readme-ov-file#data-schema
for more details.
- key: ckanext.xloader.clean_datastore_tables
default: False
example: True
Expand All @@ -136,5 +153,21 @@ groups:
that is not in ckanext.xloader.formats after a Resource is updated.
type: bool
required: false
- key: ckanext.xloader.show_badges
default: True
example: False
description: |
Controls whether or not the status badges display in the front end.
type: bool
required: false
- key: ckanext.xloader.debug_badges
default: False
example: True
description: |
Controls whether or not the status badges display all of the statuses. By default,
the badges will display "pending", "running", and "error". With debug_badges enabled,
they will also display "complete", "active", "inactive", and "unknown".
type: bool
required: false


81 changes: 81 additions & 0 deletions ckanext/xloader/helpers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import ckan.plugins.toolkit as toolkit
from ckanext.xloader.utils import XLoaderFormats
from markupsafe import Markup
from html import escape as html_escape


def xloader_status(resource_id):
Expand Down Expand Up @@ -42,3 +44,82 @@ def is_resource_supported_by_xloader(res_dict, check_access=True):
else:
is_supported_url_type = True
return (is_supported_format or is_datastore_active) and user_has_access and is_supported_url_type


def xloader_badge(resource):
# type: (dict) -> str
"""
Displays a custom badge for the status of Xloader and DataStore for the specified resource.
"""
if not toolkit.asbool(toolkit.config.get('ckanext.xloader.show_badges', True)):
return ''

if not XLoaderFormats.is_it_an_xloader_format(resource.get('format')):
# we only want to show badges for supported xloader formats
return ''

is_datastore_active = resource.get('datastore_active', False)

try:
xloader_job = toolkit.get_action("xloader_status")({'ignore_auth': True},
{"resource_id": resource.get('id')})
except toolkit.ObjectNotFound:
xloader_job = {}

if xloader_job.get('status') == 'complete':
duttonw marked this conversation as resolved.
Show resolved Hide resolved
# the xloader task is complete, show datastore active or inactive.
# xloader will delete the datastore table at the beggining of the job run.
# so this will only be true if the job is fully finished.
status = 'active' if is_datastore_active else 'inactive'
elif xloader_job.get('status') in ['submitting', 'pending', 'running', 'running_but_viewable', 'error']:
# the job is running or pending or errored
# show the xloader status
status = xloader_job.get('status')
if status == 'running_but_viewable':
# treat running_but_viewable the same as running
status = 'running'
elif status == 'submitting':
# treat submitting the same as pending
status = 'pending'
else:
# we do not know what the status is
status = 'unknown'

messages = {
# Default messages
'pending': toolkit._('Data awaiting load to DataStore'),
'running': toolkit._('Loading data into DataStore'),
'error': toolkit._('Failed to load data into DataStore'),
# Debug messages
'complete': toolkit._('Data loaded into DataStore'),
'active': toolkit._('Data available in DataStore'),
'inactive': toolkit._('Resource not active in DataStore'),
'unknown': toolkit._('DataStore status unknown'),
}
basic_statuses = ['pending', 'running', 'error']

if status not in basic_statuses and not toolkit.asbool(toolkit.config.get('ckanext.xloader.debug_badges', False)):
return ''

badge_url = toolkit.h.url_for_static('/static/badges/{lang}/datastore-{status}.svg'.format(
lang=toolkit.h.lang(), status=status))

title = toolkit.h.render_datetime(xloader_job.get('last_updated'), with_hours=True) \
if xloader_job.get('last_updated') else ''

try:
toolkit.check_access('resource_update', {'user': toolkit.g.user}, {'id': resource.get('id')})
pusher_url = toolkit.h.url_for('xloader.resource_data',
id=resource.get('package_id'),
resource_id=resource.get('id'))

return Markup(u'<a href="{pusher_url}" class="loader-badge"><img src="{badge_url}" alt="{alt}" title="{title}"/></a>'.format(
pusher_url=pusher_url,
badge_url=badge_url,
alt=html_escape(messages[status], quote=True),
title=html_escape(title, quote=True)))
except toolkit.NotAuthorized:
return Markup(u'<span class="loader-badge"><img src="{badge_url}" alt="{alt}" title="{title}"/></span>'.format(
badge_url=badge_url,
alt=html_escape(messages[status], quote=True),
title=html_escape(title, quote=True)))
8 changes: 7 additions & 1 deletion ckanext/xloader/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def xloader_data_into_datastore(input):
if tries < MAX_RETRIES:
tries = tries + 1
log.info("Job %s failed due to temporary error [%s], retrying", job_id, e)
logger.info("Job failed due to temporary error [%s], retrying", e)
job_dict['status'] = 'pending'
job_dict['metadata']['tries'] = tries
enqueue_job(
Expand Down Expand Up @@ -245,7 +246,12 @@ def tabulator_load():
logger.info("'use_type_guessing' mode is: %s", use_type_guessing)
try:
if use_type_guessing:
tabulator_load()
try:
tabulator_load()
except JobError as e:
logger.warning('Load using tabulator failed: %s', e)
logger.info('Trying again with direct COPY')
direct_load()
else:
try:
direct_load()
Expand Down
39 changes: 36 additions & 3 deletions ckanext/xloader/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ def _clear_datastore_resource(resource_id):
'''
engine = get_write_engine()
with engine.begin() as conn:
conn.execute("SET LOCAL lock_timeout = '5s'")
conn.execute('TRUNCATE TABLE "{}"'.format(resource_id))
conn.execute("SET LOCAL lock_timeout = '15s'")
conn.execute('TRUNCATE TABLE "{}" RESTART IDENTITY'.format(resource_id))


def load_csv(csv_filepath, resource_id, mimetype='text/csv', logger=None):
Expand Down Expand Up @@ -339,6 +339,18 @@ def create_column_indexes(fields, resource_id, logger):
logger.info('...column indexes created.')


def _save_type_overrides(headers_dicts):
# copy 'type' to 'type_override' if it's not the default type (text)
# and there isn't already an override in place
for h in headers_dicts:
if h['type'] != 'text':
if 'info' in h:
if 'type_override' not in h['info']:
h['info']['type_override'] = h['type']
else:
h['info'] = {'type_override': h['type']}


def load_table(table_filepath, resource_id, mimetype='text/csv', logger=None):
'''Loads an Excel file (or other tabular data recognized by tabulator)
into Datastore and creates indexes.
Expand Down Expand Up @@ -399,7 +411,14 @@ def load_table(table_filepath, resource_id, mimetype='text/csv', logger=None):
}.get(existing_info.get(h, {}).get('type_override'), t)
for t, h in zip(types, headers)]

headers = [header.strip()[:MAX_COLUMN_LENGTH] for header in headers if header.strip()]
# Strip leading and trailing whitespace, then truncate to maximum length,
# then strip again in case the truncation exposed a space.
headers = [
header.strip()[:MAX_COLUMN_LENGTH].strip()
for header in headers
if header and header.strip()
]
header_count = len(headers)
type_converter = TypeConverter(types=types)

with UnknownEncodingStream(table_filepath, file_format, decoding_result,
Expand All @@ -409,6 +428,17 @@ def row_iterator():
for row in stream:
data_row = {}
for index, cell in enumerate(row):
# Handle files that have extra blank cells in heading and body
# eg from Microsoft Excel adding lots of empty cells on export.
# Blank header cells won't generate a column,
# so row length won't match column count.
if index >= header_count:
# error if there's actual data out of bounds, otherwise ignore
if cell:
raise LoaderError("Found data in column %s but resource only has %s header(s)",
index + 1, header_count)
else:
continue
data_row[headers[index]] = cell
yield data_row
result = row_iterator()
Expand All @@ -426,6 +456,9 @@ def row_iterator():
if type_override in list(_TYPE_MAPPING.values()):
h['type'] = type_override

# preserve any types that we have sniffed unless told otherwise
_save_type_overrides(headers_dicts)

logger.info('Determined headers and types: %s', headers_dicts)

'''
Expand Down
42 changes: 40 additions & 2 deletions ckanext/xloader/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@

from ckan.model.domain_object import DomainObjectOperation
from ckan.model.resource import Resource
from ckan.model.package import Package

from . import action, auth, helpers as xloader_helpers, utils
from ckanext.xloader.utils import XLoaderFormats

try:
from ckanext.validation.interfaces import IPipeValidation
HAS_IPIPE_VALIDATION = True
except ImportError:
HAS_IPIPE_VALIDATION = False

try:
config_declarations = toolkit.blanket.config_declarations
except AttributeError:
Expand All @@ -34,6 +39,8 @@ class xloaderPlugin(plugins.SingletonPlugin):
plugins.implements(plugins.IResourceController, inherit=True)
plugins.implements(plugins.IClick)
plugins.implements(plugins.IBlueprint)
if HAS_IPIPE_VALIDATION:
plugins.implements(IPipeValidation)

# IClick
def get_commands(self):
Expand All @@ -51,6 +58,7 @@ def get_blueprint(self):

def update_config(self, config):
toolkit.add_template_directory(config, 'templates')
toolkit.add_public_directory(config, 'public')

# IConfigurable

Expand All @@ -68,6 +76,21 @@ def configure(self, config_):
)
)

# IPipeValidation

def receive_validation_report(self, validation_report):
if utils.requires_successful_validation_report():
res_dict = toolkit.get_action('resource_show')({'ignore_auth': True},
{'id': validation_report.get('resource_id')})
if (toolkit.asbool(toolkit.config.get('ckanext.xloader.validation.enforce_schema', True))
or res_dict.get('schema', None)) and validation_report.get('status') != 'success':
# A schema is present, or required to be present
return
# if validation is running in async mode, it is running from the redis workers.
# thus we need to do sync=True to have Xloader put the job at the front of the queue.
sync = toolkit.asbool(toolkit.config.get(u'ckanext.validation.run_on_update_async', True))
self._submit_to_xloader(res_dict, sync=sync)

# IDomainObjectModification

def notify(self, entity, operation):
Expand Down Expand Up @@ -95,7 +118,16 @@ def notify(self, entity, operation):
if _should_remove_unsupported_resource_from_datastore(resource_dict):
toolkit.enqueue_job(fn=_remove_unsupported_resource_from_datastore, args=[entity.id])

if not getattr(entity, 'url_changed', False):
if utils.requires_successful_validation_report():
# If the resource requires validation, stop here if validation
# has not been performed or did not succeed. The Validation
# extension will call resource_patch and this method should
# be called again. However, url_changed will not be in the entity
# once Validation does the patch.
log.debug("Deferring xloading resource %s because the "
"resource did not pass validation yet.", resource_dict.get('id'))
return
elif not getattr(entity, 'url_changed', False):
# do not submit to xloader if the url has not changed.
return

Expand All @@ -104,6 +136,11 @@ def notify(self, entity, operation):
# IResourceController

def after_resource_create(self, context, resource_dict):
if utils.requires_successful_validation_report():
log.debug("Deferring xloading resource %s because the "
"resource did not pass validation yet.", resource_dict.get('id'))
return

self._submit_to_xloader(resource_dict)

def before_resource_show(self, resource_dict):
Expand Down Expand Up @@ -206,6 +243,7 @@ def get_helpers(self):
"xloader_status": xloader_helpers.xloader_status,
"xloader_status_description": xloader_helpers.xloader_status_description,
"is_resource_supported_by_xloader": xloader_helpers.is_resource_supported_by_xloader,
"xloader_badge": xloader_helpers.xloader_badge,
}


Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading