• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NaturalHistoryMuseum / ckanext-doi / #382

22 Sep 2025 02:04PM UTC coverage: 68.261% (-1.3%) from 69.604%
#382

push

coveralls-python

web-flow
merge: PR #128 from dev

Weekly release 2025-09-22

2 of 8 new or added lines in 1 file covered. (25.0%)

3 existing lines in 1 file now uncovered.

314 of 460 relevant lines covered (68.26%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.33
/ckanext/doi/plugin.py
1
#!/usr/bin/env python3
2
# encoding: utf-8
3
#
4
# This file is part of ckanext-doi
5
# Created by the Natural History Museum in London, UK
6

7
from datetime import datetime
1✔
8
from logging import getLogger
1✔
9

10
from ckan.plugins import SingletonPlugin, implements, interfaces, toolkit
1✔
11

12
from ckanext.doi import cli
1✔
13
from ckanext.doi.lib.api import DataciteClient
1✔
14
from ckanext.doi.lib.helpers import (
1✔
15
    doi_test_mode,
16
    get_site_title,
17
    get_site_url,
18
    package_get_year,
19
)
20
from ckanext.doi.lib.metadata import build_metadata_dict, build_xml_dict
1✔
21
from ckanext.doi.model.crud import DOIQuery
1✔
22

23
log = getLogger(__name__)
1✔
24

25

26
class DOIPlugin(SingletonPlugin, toolkit.DefaultDatasetForm):
1✔
27
    """
28
    CKAN DOI Extension.
29
    """
30

31
    implements(interfaces.IConfigurer)
1✔
32
    implements(interfaces.IPackageController, inherit=True)
1✔
33
    implements(interfaces.ITemplateHelpers, inherit=True)
1✔
34
    implements(interfaces.IClick)
1✔
35

36
    ## IClick
37
    def get_commands(self):
1✔
38
        return cli.get_commands()
×
39

40
    ## IConfigurer
41
    def update_config(self, config):
1✔
42
        """
43
        Adds templates.
44
        """
45
        toolkit.add_template_directory(config, 'theme/templates')
1✔
46

47
    ## IPackageController
48
    def after_dataset_create(self, context, pkg_dict):
1✔
49
        """
50
        A new dataset has been created, so we need to create a new DOI.
51

52
        NB: This is called after creation of a dataset, before resources have been
53
        added, so state = draft.
54
        """
55
        DOIQuery.read_package(pkg_dict['id'], create_if_none=True)
1✔
56

57
    ## IPackageController
58
    def after_dataset_update(self, context, pkg_dict):
1✔
59
        """
60
        Dataset has been created/updated.
61

62
        Check status of the dataset to determine if we should publish DOI to datacite
63
        network.
64
        """
65
        # Is this active and public? If so we need to make sure we have an active DOI
66
        if pkg_dict.get('state', 'active') == 'active' and not pkg_dict.get(
1✔
67
            'private', False
68
        ):
69
            package_id = pkg_dict['id']
1✔
70

71
            # remove user-defined update schemas first (if needed)
72
            context.pop('schema', None)
1✔
73

74
            # Load the package_show version of the dict
75
            pkg_show_dict = toolkit.get_action('package_show')(
1✔
76
                context, {'id': package_id}
77
            )
78

79
            # Load or create the local DOI (package may not have a DOI if extension was loaded
80
            # after package creation)
81
            doi = DOIQuery.read_package(package_id, create_if_none=True)
1✔
82

83
            metadata_dict = build_metadata_dict(pkg_show_dict)
1✔
84
            xml_dict = build_xml_dict(metadata_dict)
1✔
85

86
            client = DataciteClient()
1✔
87

88
            if doi.published is None:
1✔
89
                # metadata gets created before minting
90
                client.set_metadata(doi.identifier, xml_dict)
1✔
91
                client.mint_doi(doi.identifier, package_id)
1✔
92

93
                try:
1✔
94
                    toolkit.h.flash_success('DataCite DOI created')
1✔
NEW
95
                except RuntimeError:
×
96
                    # fix out of context issue while running cli commands
NEW
97
                    pass
×
98
            else:
99
                same = client.check_for_update(doi.identifier, xml_dict)
×
100
                if not same:
×
101
                    # Not the same, so we want to update the metadata
102
                    client.set_metadata(doi.identifier, xml_dict)
×
103

NEW
104
                    try:
×
NEW
105
                        toolkit.h.flash_success('DataCite DOI metadata updated')
×
NEW
106
                    except RuntimeError:
×
107
                        # fix out of context issue while running cli commands
NEW
108
                        pass
×
109

110
        return pkg_dict
1✔
111

112
    # IPackageController
113
    def after_dataset_show(self, context, pkg_dict):
1✔
114
        """
115
        Add the DOI details to the pkg_dict so it can be displayed.
116
        """
117
        doi = DOIQuery.read_package(pkg_dict['id'])
1✔
118
        if doi:
1✔
119
            pkg_dict['doi'] = doi.identifier
1✔
120
            pkg_dict['doi_status'] = True if doi.published else False
1✔
121
            pkg_dict['domain'] = get_site_url().replace('http://', '')
1✔
122
            pkg_dict['doi_date_published'] = (
1✔
123
                datetime.strftime(doi.published, '%Y-%m-%d') if doi.published else None
124
            )
125
            pkg_dict['doi_publisher'] = toolkit.config.get('ckanext.doi.publisher')
1✔
126

127
    def after_create(self, *args, **kwargs):
1✔
128
        """
129
        CKAN 2.9 compat version of after_dataset_create.
130
        """
UNCOV
131
        return self.after_dataset_create(*args, **kwargs)
×
132

133
    def after_update(self, *args, **kwargs):
1✔
134
        """
135
        CKAN 2.9 compat version of after_dataset_update.
136
        """
UNCOV
137
        return self.after_dataset_update(*args, **kwargs)
×
138

139
    def after_show(self, *args, **kwargs):
1✔
140
        """
141
        CKAN 2.9 compat version of after_dataset_show.
142
        """
UNCOV
143
        return self.after_dataset_show(*args, **kwargs)
×
144

145
    # ITemplateHelpers
146
    def get_helpers(self):
1✔
147
        return {
1✔
148
            'package_get_year': package_get_year,
149
            'now': datetime.now,
150
            'get_site_title': get_site_title,
151
            'doi_test_mode': doi_test_mode,
152
        }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc