Skip to content

Commit da34655

Browse files
committed
Merge branch 'master' into switch-to-sqlalchemy-2
2 parents da467c5 + 958b80b commit da34655

File tree

93 files changed

+3143
-1939
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+3143
-1939
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ defaults:
3737

3838
redis_image: &redis_image
3939
# Note, this should be in sync with test-infrastructure/docker-compose.yml
40-
image: redis:3
40+
image: redis:7
4141
name: ckan-redis
4242

4343
solr_image: &solr_image

.github/workflows/publish-pypi.yml

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Publish to PyPI and TestPyPI
2+
3+
on: push
4+
5+
jobs:
6+
build:
7+
name: Build distribution
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- uses: actions/checkout@v4
12+
- name: Set up Python
13+
uses: actions/setup-python@v5
14+
with:
15+
python-version: "3.9"
16+
- name: Install pypa/build
17+
run: >-
18+
python3 -m
19+
pip install
20+
build
21+
--user
22+
- name: Build a binary wheel and a source tarball
23+
run: python3 -m build
24+
- name: Store the distribution packages
25+
uses: actions/upload-artifact@v3
26+
with:
27+
name: python-package-distributions
28+
path: dist/
29+
30+
publish-to-pypi:
31+
name: Publish Python distribution on PyPI
32+
# Publish to PyPI when pushing a tag
33+
if: startsWith(github.ref, 'refs/tags/')
34+
needs:
35+
- build
36+
runs-on: ubuntu-latest
37+
environment:
38+
name: pypi
39+
url: https://pypi.org/p/ckan
40+
permissions:
41+
id-token: write
42+
steps:
43+
- name: Download all the dists
44+
uses: actions/download-artifact@v3
45+
with:
46+
name: python-package-distributions
47+
path: dist/
48+
- name: Publish distribution to PyPI
49+
uses: pypa/gh-action-pypi-publish@release/v1
50+
51+
publish-to-testpypi:
52+
name: Publish Python distribution on TestPyPI
53+
# Publish to Test PyPI when a pull request is merged
54+
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
55+
needs:
56+
- build
57+
runs-on: ubuntu-latest
58+
environment:
59+
name: pypi
60+
url: https://test.pypi.org/p/ckan
61+
permissions:
62+
id-token: write
63+
steps:
64+
- name: Download all the dists
65+
uses: actions/download-artifact@v3
66+
with:
67+
name: python-package-distributions
68+
path: dist/
69+
- name: Publish distribution to PyPI
70+
uses: pypa/gh-action-pypi-publish@release/v1
71+
with:
72+
repository-url: https://test.pypi.org/legacy/

MANIFEST.in

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ recursive-include ckanext *.py
1515
recursive-include ckanext/*/i18n *
1616
recursive-include ckanext/*/public *
1717
recursive-include ckanext/*/assets *
18+
recursive-include ckanext/*/migration *
1819
recursive-include ckanext/*/templates *
1920
recursive-include ckanext/*/theme/public *
2021
recursive-include ckanext/*/theme/templates *

README.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ future plans as well as questions and discussions about CKAN development, deploy
7171
Community Chat
7272
~~~~~~~~~~~~~~
7373

74-
If you want to talk about CKAN development say hi to the CKAN developers and members of
75-
the CKAN community on the public `CKAN chat on Gitter`_. Gitter is free and open-source;
76-
you can sign in with your GitHub, GitLab, or Twitter account.
74+
If you want to talk about CKAN development, say hi to the CKAN developers and members of
75+
the CKAN community on the public `CKAN chat on Gitter`_. Gitter is free and open-source, and
76+
you can sign in using your GitHub, GitLab, or X (formerly known as Twitter) account.
7777

7878
The logs for the old `#ckan`_ IRC channel (2014 to 2018) can be found here:
7979
https://github.com/ckan/irc-logs.

changes/5468.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix Page view tracking of datasets is not working if ckan is running at a subpath

changes/5847.feature

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Allow configuring datastore full text field indexes with new
2+
ckan.datastore.default_fts_index_field_types config option.
3+
4+
The default is an empty list, avoiding automatically creating
5+
separate full text indexes for any individual columns. The
6+
whole-row full text index still exists for all tables.
7+
8+
Use the `ckan datastore fts-index` command to remove existing
9+
column indexes to reclaim database space.
File renamed without changes.

changes/8407.feature

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Faster dataset metadata updates by detecting changes and only updating resource
2+
metadata when dataset fields defined by IDatasetForm.resource_validation_dependencies
3+
have changed (default: none)
4+
5+
Now activities are created and metadata_modified updated only if there is a real change.
6+
7+
metadata_modified may now be set by sysadmins which is useful for harvesting or mirroring.
8+
9+
The allow_partial_update context parameter has been removed, now normal API
10+
users may call package_update without passing resources. In this case the existing
11+
resources will remain untouched instead of being deleted.
12+
13+
package_update and actions that call it now report whether there was a real change by
14+
adding the package id to a new changed_entities context value or changed_entities
15+
envelope value for API calls.

changes/8447.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix `tracking` extension to use ORM models and comply with new `ckan.model` models

changes/8482.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix internal server error when viewing a deleted user.

changes/8483.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix display of user organizations page if user belongs to no organizations.

changes/8492.feature

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Adds new logo and updates UI header in `midnight-blue` theme.
2+
Adds macro for creating navigation links.
3+
Adds helpers `endpoint_from_url` and `page_is_active`.

changes/8496.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix for upload regression from #8360

changes/8499.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Avoid exceptions in tracking extension when dataset fields are missing

changes/8501.bugfix

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix error when viewing history of a deleted resource or its package before
2+
the deletion date.

changes/8504.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Upgrade requirements to latest versions

changes/8507.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Register pytest plugins as entrypoints to make them available to all extensions

changes/8519.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Don't add author email to pyproject.toml if empty when creating an extension

changes/8520.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Automate publishing CKAN package to PyPI

changes/8537.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix showing '0 members' for all groups on a dataset page.

ckan/lib/dictization/__init__.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from __future__ import annotations
33

44
import datetime
5-
from typing import Any, Callable, Iterable
5+
from typing import Any, Callable, Iterable, Literal
66

77
import sqlalchemy
88
from sqlalchemy import Table
@@ -109,15 +109,21 @@ def get_unique_constraints(table: Table, context: Context) -> list[list[str]]:
109109
return list_of_constraints
110110

111111

112-
def table_dict_save(table_dict: dict[str, Any],
113-
ModelClass: Any,
114-
context: Context,
115-
extra_attrs: Iterable[str] = ()) -> Any:
112+
def table_dict_save(
113+
table_dict: dict[str, Any],
114+
ModelClass: Any,
115+
context: Context,
116+
extra_attrs: Iterable[str] = ()
117+
) -> tuple[Any, Literal['create', 'update', None]]:
116118
'''Given a dict and a model class, update or create a sqlalchemy object.
117119
This will use an existing object if "id" is supplied OR if any unique
118120
constraints are met. e.g supplying just a tag name will get out that tag
119121
obj.
120122
123+
Returns (obj, change) where change is:
124+
- 'create' if this is a new object
125+
- 'update' if any fields were changed or extra_attrs passed
126+
- None if no change for an existing object
121127
'''
122128
session = context["session"]
123129

@@ -130,7 +136,8 @@ def table_dict_save(table_dict: dict[str, Any],
130136
if id:
131137
obj = session.get(ModelClass, id)
132138

133-
if not obj and isinstance(table, Table):
139+
new = not obj
140+
if new:
134141
unique_constraints = get_unique_constraints(table, context)
135142
for constraint in unique_constraints:
136143
params = dict((key, table_dict.get(key)) for key in constraint)
@@ -146,11 +153,13 @@ def table_dict_save(table_dict: dict[str, Any],
146153
if not obj:
147154
obj = ModelClass()
148155

149-
obj.from_dict(table_dict)
156+
changed, _skipped = obj.from_dict(table_dict)
150157
for a in extra_attrs:
151158
if a in table_dict:
152159
setattr(obj, a, table_dict[a])
153160

154161
session.add(obj)
155162

156-
return obj
163+
return (
164+
obj, 'create' if new else 'update' if changed or extra_attrs else None
165+
)

0 commit comments

Comments
 (0)