From 9999f5508b19dd1c37f38208b260db17efae80de Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Wed, 7 Jan 2026 19:46:31 +0000 Subject: [PATCH 1/6] feat(cli): ds purge; - More options to ds purge command. --- ckanext/datastore/cli.py | 44 ++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/ckanext/datastore/cli.py b/ckanext/datastore/cli.py index d0f0499be99..8428b937789 100644 --- a/ckanext/datastore/cli.py +++ b/ckanext/datastore/cli.py @@ -129,10 +129,16 @@ def _parse_db_config(config_key: str = u'sqlalchemy.url'): @datastore.command( 'purge', - short_help='purge orphaned resources from the datastore.' + short_help='purge orphaned or deleted resources from the datastore.' ) -def purge(): - '''Purge orphaned resources from the datastore using the datastore_delete +# (canada fork only): more options and state=deleted handling +# TODO: upstream contrib!! +@click.option('-l', '--list', is_flag=True, + type=click.BOOL, help='Only output the list of oprhaned Resource IDs.') +@click.option('-q', '--quiet', is_flag=True, + type=click.BOOL, help='Suppress human interaction.') +def purge(list: bool = False, quiet: bool = False): + '''Purge orphaned or deleted resources from the datastore using the datastore_delete action, which drops tables when called without filters.''' site_user = logic.get_action('get_site_user')({'ignore_auth': True}, {}) @@ -150,24 +156,50 @@ def purge(): if record['alias_of']: continue - logic.get_action('resource_show')( + # (canada fork only): more options and state=deleted handling + # TODO: upstream contrib!! + res = logic.get_action('resource_show')( {'user': site_user['name']}, {'id': record['name']} ) + pkg = logic.get_action('package_show')( + {'user': site_user['name']}, + {'id': res['package_id']} + ) except logic.NotFound: resource_id_list.append(record['name']) click.echo("Resource '%s' orphaned - queued for drop" % - record[u'name']) + record['name']) + continue except KeyError: continue + # (canada fork only): more options and state=deleted handling + # TODO: upstream contrib!! + if res['state'] == 'deleted': + resource_id_list.append(record['name']) + click.echo("Resource '%s' deleted - queued for drop" % + record['name']) + if pkg['state'] == 'deleted': + resource_id_list.append(record['name']) + click.echo("Package '%s' deleted - queued for drop" % + pkg['id']) orphaned_table_count = len(resource_id_list) + # (canada fork only): more options and state=deleted handling + # TODO: upstream contrib!! + if list: + click.echo('\n'.join(resource_id_list)) + return + click.echo('%d orphaned tables found.' % orphaned_table_count) if not orphaned_table_count: return - click.confirm('Proceed with purge?', abort=True) + # (canada fork only): more options and state=deleted handling + # TODO: upstream contrib!! + if not quiet: + click.confirm('Proceed with purge?', abort=True) # Drop the orphaned datastore tables. When datastore_delete is called # without filters, it does a drop table cascade From 2838f9a91058621330f5a4534b09e76cf4bc4588 Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Wed, 7 Jan 2026 20:03:17 +0000 Subject: [PATCH 2/6] feat(misc): changelog; - Added change log file. --- changes/218.canada.changes | 1 + ckanext/datastore/cli.py | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 changes/218.canada.changes diff --git a/changes/218.canada.changes b/changes/218.canada.changes new file mode 100644 index 00000000000..cc7283ac236 --- /dev/null +++ b/changes/218.canada.changes @@ -0,0 +1 @@ +Added `--list` and `--quiet` options to the `datastore purge` command. \ No newline at end of file diff --git a/ckanext/datastore/cli.py b/ckanext/datastore/cli.py index 8428b937789..16c8ac83073 100644 --- a/ckanext/datastore/cli.py +++ b/ckanext/datastore/cli.py @@ -168,8 +168,9 @@ def purge(list: bool = False, quiet: bool = False): ) except logic.NotFound: resource_id_list.append(record['name']) - click.echo("Resource '%s' orphaned - queued for drop" % - record['name']) + if not list: + click.echo("Resource '%s' orphaned - queued for drop" % + record['name']) continue except KeyError: continue @@ -177,20 +178,22 @@ def purge(list: bool = False, quiet: bool = False): # TODO: upstream contrib!! if res['state'] == 'deleted': resource_id_list.append(record['name']) - click.echo("Resource '%s' deleted - queued for drop" % - record['name']) + if not list: + click.echo("Resource '%s' deleted - queued for drop" % + record['name']) if pkg['state'] == 'deleted': resource_id_list.append(record['name']) - click.echo("Package '%s' deleted - queued for drop" % - pkg['id']) + if not list: + click.echo("Package '%s' deleted - queued for drop" % + pkg['id']) - orphaned_table_count = len(resource_id_list) # (canada fork only): more options and state=deleted handling # TODO: upstream contrib!! if list: click.echo('\n'.join(resource_id_list)) return + orphaned_table_count = len(resource_id_list) click.echo('%d orphaned tables found.' % orphaned_table_count) if not orphaned_table_count: From e4c3714d53ba37d8c6ade7647c29272ef08efc0e Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Wed, 7 Jan 2026 20:07:05 +0000 Subject: [PATCH 3/6] feat(misc): changelog; - Added change log file. --- changes/218.canada.changes | 2 +- ckanext/datastore/cli.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/changes/218.canada.changes b/changes/218.canada.changes index cc7283ac236..9f11cfa46d0 100644 --- a/changes/218.canada.changes +++ b/changes/218.canada.changes @@ -1 +1 @@ -Added `--list` and `--quiet` options to the `datastore purge` command. \ No newline at end of file +Added `--list` and `--quiet` options to the `datastore purge` command. The command now handled soft-deleted Resources and Datasets. \ No newline at end of file diff --git a/ckanext/datastore/cli.py b/ckanext/datastore/cli.py index 16c8ac83073..1803f9519ca 100644 --- a/ckanext/datastore/cli.py +++ b/ckanext/datastore/cli.py @@ -134,7 +134,8 @@ def _parse_db_config(config_key: str = u'sqlalchemy.url'): # (canada fork only): more options and state=deleted handling # TODO: upstream contrib!! @click.option('-l', '--list', is_flag=True, - type=click.BOOL, help='Only output the list of oprhaned Resource IDs.') + type=click.BOOL, + help='Only output the list of oprhaned or deleted Resource IDs.') @click.option('-q', '--quiet', is_flag=True, type=click.BOOL, help='Suppress human interaction.') def purge(list: bool = False, quiet: bool = False): From 6209d300212d6f62af243921ff506215f9f20438 Mon Sep 17 00:00:00 2001 From: Jesse Vickery Date: Fri, 9 Jan 2026 19:41:25 +0000 Subject: [PATCH 4/6] feat(misc): changelog; - Added change log file. --- ckanext/datastore/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ckanext/datastore/cli.py b/ckanext/datastore/cli.py index 1803f9519ca..17372b75012 100644 --- a/ckanext/datastore/cli.py +++ b/ckanext/datastore/cli.py @@ -136,9 +136,9 @@ def _parse_db_config(config_key: str = u'sqlalchemy.url'): @click.option('-l', '--list', is_flag=True, type=click.BOOL, help='Only output the list of oprhaned or deleted Resource IDs.') -@click.option('-q', '--quiet', is_flag=True, +@click.option('-y', '--yes', is_flag=True, type=click.BOOL, help='Suppress human interaction.') -def purge(list: bool = False, quiet: bool = False): +def purge(list: bool = False, yes: bool = False): '''Purge orphaned or deleted resources from the datastore using the datastore_delete action, which drops tables when called without filters.''' @@ -202,7 +202,7 @@ def purge(list: bool = False, quiet: bool = False): # (canada fork only): more options and state=deleted handling # TODO: upstream contrib!! - if not quiet: + if not yes: click.confirm('Proceed with purge?', abort=True) # Drop the orphaned datastore tables. When datastore_delete is called From c38547adf5ff1f1e59067c43c8d3bf6a5ff49f8e Mon Sep 17 00:00:00 2001 From: Jesse Vickery <97247789+JVickery-TBS@users.noreply.github.com> Date: Mon, 12 Jan 2026 09:14:21 -0500 Subject: [PATCH 5/6] Update changes/218.canada.changes Co-authored-by: Ian Ward --- changes/218.canada.changes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes/218.canada.changes b/changes/218.canada.changes index 9f11cfa46d0..b0c4fe1baeb 100644 --- a/changes/218.canada.changes +++ b/changes/218.canada.changes @@ -1 +1 @@ -Added `--list` and `--quiet` options to the `datastore purge` command. The command now handled soft-deleted Resources and Datasets. \ No newline at end of file +Added `--list` and `--yes` options to the `datastore purge` command. The command now handled soft-deleted Resources and Datasets. \ No newline at end of file From 919e022d4fa1b2f05734c1b8fb25ddda6c31ba2f Mon Sep 17 00:00:00 2001 From: Jesse Vickery <97247789+JVickery-TBS@users.noreply.github.com> Date: Mon, 12 Jan 2026 09:14:34 -0500 Subject: [PATCH 6/6] Update ckanext/datastore/cli.py Co-authored-by: Ian Ward --- ckanext/datastore/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckanext/datastore/cli.py b/ckanext/datastore/cli.py index 17372b75012..2748ff79680 100644 --- a/ckanext/datastore/cli.py +++ b/ckanext/datastore/cli.py @@ -137,7 +137,7 @@ def _parse_db_config(config_key: str = u'sqlalchemy.url'): type=click.BOOL, help='Only output the list of oprhaned or deleted Resource IDs.') @click.option('-y', '--yes', is_flag=True, - type=click.BOOL, help='Suppress human interaction.') + type=click.BOOL, help='Purge without asking for confirmation.') def purge(list: bool = False, yes: bool = False): '''Purge orphaned or deleted resources from the datastore using the datastore_delete action, which drops tables when called without filters.'''