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

NaturalHistoryMuseum / ckanext-doi / #305

05 Jun 2025 04:44PM UTC coverage: 68.943% (-0.7%) from 69.604%
#305

push

coveralls-python

alycejenni
build: add ruff lint select rules

313 of 454 relevant lines covered (68.94%)

0.69 hits per line

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

85.19
/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
                toolkit.h.flash_success('DataCite DOI created')
1✔
93
            else:
94
                same = client.check_for_update(doi.identifier, xml_dict)
×
95
                if not same:
×
96
                    # Not the same, so we want to update the metadata
97
                    client.set_metadata(doi.identifier, xml_dict)
×
98
                    toolkit.h.flash_success('DataCite DOI metadata updated')
×
99

100
        return pkg_dict
1✔
101

102
    # IPackageController
103
    def after_dataset_show(self, context, pkg_dict):
1✔
104
        """
105
        Add the DOI details to the pkg_dict so it can be displayed.
106
        """
107
        doi = DOIQuery.read_package(pkg_dict['id'])
1✔
108
        if doi:
1✔
109
            pkg_dict['doi'] = doi.identifier
1✔
110
            pkg_dict['doi_status'] = True if doi.published else False
1✔
111
            pkg_dict['domain'] = get_site_url().replace('http://', '')
1✔
112
            pkg_dict['doi_date_published'] = (
1✔
113
                datetime.strftime(doi.published, '%Y-%m-%d') if doi.published else None
114
            )
115
            pkg_dict['doi_publisher'] = toolkit.config.get('ckanext.doi.publisher')
1✔
116

117
    def after_create(self, *args, **kwargs):
1✔
118
        """
119
        CKAN 2.9 compat version of after_dataset_create.
120
        """
121
        return self.after_dataset_create(*args, **kwargs)
×
122

123
    def after_update(self, *args, **kwargs):
1✔
124
        """
125
        CKAN 2.9 compat version of after_dataset_update.
126
        """
127
        return self.after_dataset_update(*args, **kwargs)
×
128

129
    def after_show(self, *args, **kwargs):
1✔
130
        """
131
        CKAN 2.9 compat version of after_dataset_show.
132
        """
133
        return self.after_dataset_show(*args, **kwargs)
×
134

135
    # ITemplateHelpers
136
    def get_helpers(self):
1✔
137
        return {
1✔
138
            'package_get_year': package_get_year,
139
            'now': datetime.now,
140
            'get_site_title': get_site_title,
141
            'doi_test_mode': doi_test_mode,
142
        }
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