diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f25ff8..60a3533 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,20 +1,30 @@
+# 6.3.0 (2026-06-29)
+
+## Changes
+
+- Automated annotation adding in write-record-endpoints has been removed.
+ The new query parameter `add_submission_tag` is added to write-record-endpoints.
+ If set to True, the server will add an automated annotation with the annotation
+ tags that are defined in the server-configuration (the default is False).
+
+
# 6.2.2 (2026-06-26)
-# Bugfixes
+## Bugfixes
- Fix a bug in authentication when non-config tokens are used.
# 6.2.1 (2026-06-26)
-# Bugfixes
+## Bugfixes
- Fix a bug in curator-writing when non-config tokens are used.
# 6.2.0 (2026-06-24)
-# New features
+## New features
- Add PUT-methods to the administration endpoints `/tokens`, `/collections` and
`/admin_tokens`. This allows to update collections, tokens, and
@@ -31,7 +41,7 @@
# 6.1.0 (2026-06-22)
-# New features
+## New features
- Add the option: `--ignore-default-config-file`. If the option is provided
a version 6 server will not try to initialize its configuration from the
diff --git a/dump_things_service/__about__.py b/dump_things_service/__about__.py
index ac1df1f..89d98bf 100644
--- a/dump_things_service/__about__.py
+++ b/dump_things_service/__about__.py
@@ -1 +1 @@
-__version__ = '6.2.2'
+__version__ = '6.3.0'
diff --git a/dump_things_service/collection.py b/dump_things_service/collection.py
index d670cbc..71c1533 100644
--- a/dump_things_service/collection.py
+++ b/dump_things_service/collection.py
@@ -84,10 +84,11 @@ _endpoint_template = """
def {name}(
data: {model_var_name}.{class_name} | Annotated[str, Body(media_type='text/plain')],
api_key: str = Depends(api_key_header_scheme),
+ add_submission_tag: bool = False,
format: Format = Format.json,
) -> JSONResponse | PlainTextResponse:
- logger.info('{name}(%s, %s, %s, %s)', repr(data), repr('{class_name}'), repr({model_var_name}), repr(format))
- return {handler}('{collection}', data, '{class_name}', {model_var_name}, format, api_key)
+ logger.info('{name}(%s, %s, %s, %s, %s)', repr(data), repr('{class_name}'), repr({model_var_name}), repr(add_submission_tag), repr(format))
+ return {handler}('{collection}', data, '{class_name}', {model_var_name}, format, add_submission_tag, api_key)
"""
_endpoint_curated_template = """
@@ -536,6 +537,7 @@ def store_record(
class_name: str,
model: Any,
input_format: Format,
+ add_submission_tag: bool,
api_key: str | None = Depends(api_key_header_scheme),
) -> JSONResponse | PlainTextResponse:
if input_format == Format.json and isinstance(data, str):
@@ -597,7 +599,10 @@ def store_record(
instance_state.validators[collection].validate(record)
with wrap_http_exception(CurieResolutionError):
- stored_records = store.store_object(obj=record, submitter=user_id)
+ stored_records = store.store_object(
+ obj=record,
+ submitter=user_id if add_submission_tag else None,
+ )
if input_format == Format.ttl:
format_converter = FormatConverter(
diff --git a/dump_things_service/collection_endpoints.py b/dump_things_service/collection_endpoints.py
index 34b9dfe..5972996 100644
--- a/dump_things_service/collection_endpoints.py
+++ b/dump_things_service/collection_endpoints.py
@@ -24,7 +24,6 @@ from dump_things_service import (
from dump_things_service.abstract_config import (
Configuration,
CollectionConfig,
- StrictModel,
store_config,
get_config, get_token_permissions,
)
@@ -59,9 +58,6 @@ class TagSpec(BaseModel):
submission_time_tag: str = 'http://semanticscience.org/resource/SIO_001083'
-from pydantic import ConfigDict, Field
-from dump_things_service.abstract_config import RecordDirBackendConfig, SQLiteBackendConfig, GitAuditBackendConfig
-
class CollectionRequest(CollectionConfig):
name: str
@@ -124,7 +120,7 @@ async def create_or_replace_collection(
# Check for distinct directories.
# TODO: we skip this currently because a number of version 5 installations
- # deliberately put inboxes into the same path. Those configuration cannot
+ # deliberately put inboxes into the same path. Those configurations cannot
# be established if this check is performed. Instead of the `if False:`-
# clause, we should introduce a configuration for the server to specify
# whether unique directories are required.
diff --git a/dump_things_service/store/model_store.py b/dump_things_service/store/model_store.py
index 1ec971e..f77be4e 100644
--- a/dump_things_service/store/model_store.py
+++ b/dump_things_service/store/model_store.py
@@ -45,7 +45,7 @@ class _ModelStore:
def store_object(
self,
obj: BaseModel,
- submitter: str,
+ submitter: str | None,
) -> Iterable[tuple[str, dict]]:
if obj.__class__.__name__ == 'Thing' and 'dlthings:placeholder' in (obj.annotations or dict()):
return []
@@ -72,7 +72,7 @@ class _ModelStore:
def _store_flat_object(
self,
obj: BaseModel,
- submitter: str,
+ submitter: str | None,
) -> dict:
iri = self.pid_to_iri(obj.pid)
class_name = obj.__class__.__name__
@@ -83,7 +83,9 @@ class _ModelStore:
)
# Add the submitter id to the record annotations
- self.annotate(json_object, submitter)
+ if submitter:
+ self.annotate(json_object, submitter)
+
self.backend.add_record(
iri=iri,
class_name=class_name,
diff --git a/dump_things_service/tests/test_basic.py b/dump_things_service/tests/test_basic.py
index 34ce9f7..7591678 100644
--- a/dump_things_service/tests/test_basic.py
+++ b/dump_things_service/tests/test_basic.py
@@ -202,9 +202,7 @@ def test_store_record(fastapi_client_simple):
headers={'x-dumpthings-token': token},
)
assert response.status_code == HTTP_200_OK
- assert (
- cleaned_json(response.json(), remove_keys=('annotations',)) == extra_record
- )
+ assert response.json() == extra_record
# Check that other collections do not report the new record
for i in range(3, 6):
@@ -223,13 +221,12 @@ def test_store_record(fastapi_client_simple):
f'/collection_{i}/records/Thing',
headers={'x-dumpthings-token': token},
)
- cleaned_response = cleaned_json(response.json(), remove_keys=('annotations',))
- assert extra_record in cleaned_response
+ assert extra_record in response.json()
assert {
'schema_type': 'abc:Person',
'pid': pid,
'given_name': given_name,
- } in cleaned_response
+ } in response.json()
# Check pagination
for i, token in basic_write_locations:
@@ -240,14 +237,12 @@ def test_store_record(fastapi_client_simple):
assert response.status_code == HTTP_200_OK
for key in ('items', 'total', 'page', 'size', 'pages'):
assert key in response.json()
- records = response.json()['items']
- cleaned_response = cleaned_json(records, remove_keys=('annotations',))
- assert extra_record in cleaned_response
+ assert extra_record in response.json()['items']
assert {
'schema_type': 'abc:Person',
'pid': pid,
'given_name': given_name,
- } in cleaned_response
+ } in response.json()['items']
def test_encoding(fastapi_client_simple):
diff --git a/dump_things_service/tests/test_collection_administration.py b/dump_things_service/tests/test_collection_administration.py
index 259d375..f98b02a 100644
--- a/dump_things_service/tests/test_collection_administration.py
+++ b/dump_things_service/tests/test_collection_administration.py
@@ -144,7 +144,7 @@ def test_collection_adding(fastapi_client_simple):
headers={'x-dumpthings-token': new_token_representation},
)
assert response.status_code == HTTP_200_OK
- assert cleaned_json(response.json()[0], ('annotations',)) == new_record
+ assert response.json()[0] == new_record
# Remove the token
response = test_client.delete(
diff --git a/dump_things_service/tests/test_roundtrip.py b/dump_things_service/tests/test_roundtrip.py
index 175d154..50bbb7f 100644
--- a/dump_things_service/tests/test_roundtrip.py
+++ b/dump_things_service/tests/test_roundtrip.py
@@ -24,6 +24,30 @@ ttl_result_record_a = """@prefix abc: .
@prefix oxo: .
@prefix xyz: .
+xyz:HenryAdams a abc:Person ;
+ abc:annotations [ a abc:Annotation ;
+ abc:annotation_tag ;
+ abc:annotation_value "1970-01-01T00:00:00" ] ;
+ abc:given_name "Henryöäß" ;
+ abc:schema_type "abc:Person" .
+"""
+
+ttl_result_record_b = """@prefix abc: .
+@prefix oxo: .
+@prefix xyz: .
+
+xyz:HenryAdams a abc:Person ;
+ abc:annotations [ a abc:Annotation ;
+ abc:annotation_tag oxo:NCIT_C54269 ;
+ abc:annotation_value "test_user_1" ] ;
+ abc:given_name "Henryöäß" ;
+ abc:schema_type "abc:Person" .
+"""
+
+ttl_result_record_with_annotations_a = """@prefix abc: .
+@prefix oxo: .
+@prefix xyz: .
+
xyz:HenryAdams a abc:Person ;
abc:annotations [ a abc:Annotation ;
abc:annotation_tag ;
@@ -35,7 +59,7 @@ xyz:HenryAdams a abc:Person ;
abc:schema_type "abc:Person" .
"""
-ttl_result_record_b = """@prefix abc: .
+ttl_result_record_with_annotations_b = """@prefix abc: .
@prefix oxo: .
@prefix xyz: .
diff --git a/dump_things_service/tests/test_roundtrip_flatsocial.py b/dump_things_service/tests/test_roundtrip_flatsocial.py
index 8c7f8d9..bb2481c 100644
--- a/dump_things_service/tests/test_roundtrip_flatsocial.py
+++ b/dump_things_service/tests/test_roundtrip_flatsocial.py
@@ -35,7 +35,23 @@ dlflatsocial:test_john_ttl a dlflatsocial:Person ;
dlsocialmx:given_name "Johnöüß" .
"""
-ttl_output_record_a = """@prefix dlflat: .
+ttl_output_record_a = """@prefix dlflatsocial: .
+@prefix dlsocialmx: .
+
+dlflatsocial:another_john_ttl a dlflatsocial:Person ;
+ dlsocialmx:given_name "Johnöüß" .
+"""
+
+
+ttl_output_record_b = """@prefix dlflatsocial: .
+@prefix dlsocialmx: .
+
+dlflatsocial:another_john_ttl a dlflatsocial:Person ;
+ dlsocialmx:given_name "Johnöüß" .
+"""
+
+
+ttl_output_record_with_annotation_a = """@prefix dlflat: .
@prefix dlflatsocial: .
@prefix dlsocialmx: .
@prefix dlthings: .
@@ -52,7 +68,7 @@ dlflatsocial:another_john_ttl a dlflatsocial:Person ;
"""
-ttl_output_record_b = """@prefix dlflat: .
+ttl_output_record_with_annotation_b = """@prefix dlflat: .
@prefix dlflatsocial: .
@prefix dlsocialmx: .
@prefix dlthings: .
@@ -108,7 +124,7 @@ def test_json_ttl_json_dlflatsocial(fastapi_client_simple):
headers={'x-dumpthings-token': 'token-all'},
)
assert response.status_code == HTTP_200_OK
- json_object = cleaned_json(response.json(), remove_keys=('annotations',))
+ json_object = response.json()
assert cleaned_json(json_object, remove_keys=('schema_type',)) != json_record
json_object['pid'] = json_record['pid']
assert json_object == json_record_out
diff --git a/dump_things_service/validate.py b/dump_things_service/validate.py
index 4dd6f6f..eae50f2 100644
--- a/dump_things_service/validate.py
+++ b/dump_things_service/validate.py
@@ -38,6 +38,7 @@ def validate_record(
class_name: str,
model: Any,
input_format: Format,
+ _: bool,
api_key: str | None = Depends(api_key_header_scheme),
) -> JSONResponse: