From a9dd3266cdfef6f6c680c02aea0f80774e15d1c8 Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Wed, 13 Nov 2024 14:45:18 +0100 Subject: [PATCH 1/6] feature: add validators and some privatedatasets helpers (before implementing templates 2.6) --- .../d4science_theme/controllers/home.py | 2 +- .../d4science_theme/controllers/systemtype.py | 2 +- .../ckanext/d4science_theme/db.py | 62 ++++++ .../ckanext/d4science_theme/helpers.py | 76 +++++++ .../ckanext/d4science_theme/plugin.py | 166 +++++++++++++-- .../templates/snippets/package_item.html | 197 ++++++++++++------ .../ckanext/d4science_theme/validators.py | 24 +++ ckanext-d4science_theme/requirements.txt | 1 + ckanext-d4science_theme/setup.py | 3 +- 9 files changed, 447 insertions(+), 86 deletions(-) create mode 100644 ckanext-d4science_theme/ckanext/d4science_theme/db.py create mode 100644 ckanext-d4science_theme/ckanext/d4science_theme/validators.py diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/controllers/home.py b/ckanext-d4science_theme/ckanext/d4science_theme/controllers/home.py index c5746d5..7e5f31f 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/controllers/home.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/controllers/home.py @@ -57,7 +57,7 @@ class d4SHomeController(): 'sort': 'views_recent desc', 'fq': 'capacity:"public"' } - query = logic.get_action('package_search')(context, data_dict) + query = logic.get_action('package_search')(context, data_dict or {}) c.search_facets = query['search_facets'] c.package_count = query['count'] c.datasets = query['results'] diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/controllers/systemtype.py b/ckanext-d4science_theme/ckanext/d4science_theme/controllers/systemtype.py index 8d94e5b..af16a6f 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/controllers/systemtype.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/controllers/systemtype.py @@ -71,7 +71,7 @@ class d4STypeController(): 'sort': 'views_recent desc', 'fq': 'capacity:"public"' } - query = logic.get_action('package_search')(context, data_dict) + query = logic.get_action('package_search')(context, data_dict or {}) c.search_facets = query['search_facets'] c.package_count = query['count'] c.datasets = query['results'] diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/db.py b/ckanext-d4science_theme/ckanext/d4science_theme/db.py new file mode 100644 index 0000000..034a3ac --- /dev/null +++ b/ckanext-d4science_theme/ckanext/d4science_theme/db.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 CoNWeT Lab., Universidad Politécnica de Madrid + +# This file is part of CKAN Private Dataset Extension. + +# CKAN Private Dataset Extension is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# CKAN Private Dataset Extension is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with CKAN Private Dataset Extension. If not, see . + +from __future__ import absolute_import +from logging import getLogger + +import sqlalchemy as sa + +log = getLogger(__name__) + +AllowedUser = None + +def init_db(model): + log.debug("call initDB...") + global AllowedUser + if AllowedUser is None: + + class _AllowedUser(model.DomainObject): + + @classmethod + def get(cls, **kw): + '''Finds all the instances required.''' + query = model.Session.query(cls).autoflush(False) + results = query.filter_by(**kw).all() + log.debug("results in get %s", results) + if not isinstance(results, list): + log.debug("Errore: il risultato di get() non è una lista. Risultato:", results) + results = [] + return results + + AllowedUser = _AllowedUser + + log.debug("allowed user: %s", AllowedUser) + + # FIXME: Maybe a default value should not be included... + package_allowed_users_table = sa.Table( + 'package_allowed_users', + model.meta.metadata, + sa.Column('package_id', sa.types.UnicodeText, primary_key=True, default=u''), + sa.Column('user_name', sa.types.UnicodeText, primary_key=True, default=u''), + ) + + # Create the table only if it does not exist + package_allowed_users_table.create(checkfirst=True) + + model.meta.mapper(AllowedUser, package_allowed_users_table,) diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/helpers.py b/ckanext-d4science_theme/ckanext/d4science_theme/helpers.py index 2584283..e6ffcbd 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/helpers.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/helpers.py @@ -25,6 +25,8 @@ import collections import ckan.plugins.toolkit as tk import ckan.logic as logic +from ckanext.d4science_theme import db + log = getLogger(__name__) systemtype_field = 'systemtypefield' @@ -730,3 +732,77 @@ def get_site_statistics() -> dict[str, int]: 'group_count': len(logic.get_action('group_list')({}, {})), 'organization_count': len(logic.get_action('organization_list')({}, {})) } + +#private dataset + +def is_dataset_acquired(pkg_dict): + + log.debug("is_dataset package value: %s", pkg_dict) #restituisce True + + db.init_db(model) + log.debug("post init %s", db) + + #return False + if tk.c.user: + return len(db.AllowedUser.get(package_id=pkg_dict['id'], user_name=tk.c.user)) > 0 + else: + return False + +def is_owner(pkg_dict): + return False + #if tk.c.userobj is not None: + # return tk.c.userobj.id == pkg_dict['creator_user_id'] + #else: + # return False + + +def get_allowed_users_str(users): + if users: + return ','.join([user for user in users]) + else: + return '' + + +def can_read(pkg_dict): + try: + context = {'user': tk.c.user, 'userobj': tk.c.userobj, 'model': model} + return tk.check_access('package_show', context, pkg_dict) + except tk.NotAuthorized: + return False + + +def get_config_bool_value(config_name, default_value=False): + env_name = config_name.upper().replace('.', '_') + value = os.environ.get(env_name, tk.config.get(config_name, default_value)) + return value if type(value) == bool else value.strip().lower() in ('true', '1', 'on') + + +def show_acquire_url_on_create(): + return get_config_bool_value('ckan.privatedatasets.show_acquire_url_on_create') + + +def show_acquire_url_on_edit(): + return get_config_bool_value('ckan.privatedatasets.show_acquire_url_on_edit') + + +def acquire_button(package): + ''' + Return a Get Access button for the given package id when the dataset has + an acquisition URL. + + :param package: the the package to request access when the get access + button is clicked + :type package: Package + + :returns: a get access button as an HTML snippet + :rtype: string + + ''' + + if 'acquire_url' in package and request.path.startswith('/dataset')\ + and package['acquire_url'] != '': + url_dest = package['acquire_url'] + data = {'url_dest': url_dest} + return tk.render_snippet('snippets/acquire_button.html', data) + else: + return '' \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py index 5769285..9431c59 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py @@ -4,6 +4,7 @@ from logging import getLogger import ckan.plugins as plugins from ckanext.d4science_theme import helpers +from ckanext.d4science_theme import validators import ckan.plugins.toolkit as toolkit import ckan.model as model from ckanext.d4science_theme.controllers.home import d4SHomeController @@ -47,7 +48,7 @@ def _package_extras_save(extra_dicts, obj, context): session = context["session"] #ADDED BY FRANCESCO MANGIACRAPA - log.debug("extra_dicts: "+ str(extra_dicts)) + log.debug("extra_dicts: %s", extra_dicts) #print "extra_dicts: "+str(extra_dicts) extras_list = obj.extras_list @@ -66,7 +67,7 @@ def _package_extras_save(extra_dicts, obj, context): #print 'extra_dict key: '+extra_dict["key"] + ', value: '+extra_dict["value"] #new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) if extra_dict.get("deleted"): - log.debug("extra_dict deleted: "+str(extra_dict["key"])) + log.debug("extra_dict deleted: %s ", extra_dict["key"]) #print 'extra_dict deleted: '+extra_dict["key"] continue @@ -75,13 +76,13 @@ def _package_extras_save(extra_dicts, obj, context): new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) #ADDED BY FRANCESCO MANGIACRAPA - log.debug("new_extras: "+str(new_extras)) + log.debug("new_extras: %s", new_extras) #print "new_extras: "+str(new_extras) #new for key in set(new_extras.keys()) - set(old_extras.keys()): state = 'active' - log.debug("adding key: "+str(key)) + log.debug("adding key: %s", key) #print "adding key: "+str(key) extra_lst = new_extras[key] for extra in extra_lst: @@ -105,13 +106,13 @@ def _package_extras_save(extra_dicts, obj, context): for value in new_extras[key]: old_occur = old_extras[key].count(value) new_occur = new_extras[key].count(value) - log.debug("value: "+str(value) + ", new_occur: "+str(new_occur)+ ", old_occur: "+str(old_occur)) + log.debug("value: %s\n new_occur: %s\n old_occur: %s", value, new_occur, old_occur) #print "value: "+str(value) + ", new_occur: "+str(new_occur) + ", old_occur: "+str(old_occur) # it is an old value deleted or not if value in old_extras[key]: if old_occur == new_occur: #print "extra - occurrences of: "+str(value) +", are equal into both list" - log.debug("extra - occurrences of: "+str(value) +", are equal into both list") + log.debug("extra - occurrences of: %s are equal into both list", value) #there is a little bug, this code return always the first element, so I'm fixing with #FIX-STATUS extra_values = get_package_for_value(extras[key], value) #extras_list.append(extra) @@ -120,44 +121,44 @@ def _package_extras_save(extra_dicts, obj, context): extra.state = state session.add(extra) #print "extra updated: "+str(extra) - log.debug("extra updated: "+str(extra)) + log.debug("extra updated: %s", extra) elif new_occur > old_occur: #print "extra - a new occurrence of: "+str(value) +", is present into new list, adding it to old list" - log.debug("extra - a new occurrence of: "+str(value) +", is present into new list, adding it to old list") + log.debug("extra - a new occurrence of: %s, is present into new list, adding it to old list", value) state = 'active' extra = model.PackageExtra(state=state, key=key, value=value) extra.state = state session.add(extra) extras_list.append(extra) old_extras[key].append(value) - log.debug("old extra values updated: "+str(old_extras[key])) + log.debug("old extra values updated: %s", old_extras[key]) #print "old extra values updated: "+str(old_extras[key]) else: #remove all occurrences deleted - this code could be optimized, it is run several times but could be performed one shot countDelete = old_occur-new_occur - log.debug("extra - occurrence of: "+str(value) +", is not present into new list, removing "+str(countDelete) + " occurrence/s from old list") + log.debug("extra - occurrence of: %s, is not present into new list, removing: %s occurrence/s from old list", value, countDelete) #print "extra - occurrence of: "+str(value) +", is not present into new list, removing "+str(countDelete)+" occurrence/s from old list" extra_values = get_package_for_value(extras[key], value) for idx, extra in enumerate(extra_values): if idx < countDelete: #print "extra - occurrence of: "+str(value) +", is not present into new list, removing it from old list" - log.debug("pkg extra deleting: "+str(extra.value)) + log.debug("pkg extra deleting: %s", extra.value) #print "pkg extra deleting: "+str(extra.value) state = 'deleted' extra.state = state else: #print "pkg extra reactivating: "+str(extra.value) - log.debug("pkg extra reactivating: "+str(extra.value)) + log.debug("pkg extra reactivating: %s", extra.value) state = 'active' extra.state = state session.add(extra) else: #print "extra new value: "+str(value) - log.debug("extra new value: "+str(value)) + log.debug("extra new value: %s", value) state = 'active' extra = model.PackageExtra(state=state, key=key, value=value) extra.state = state @@ -193,13 +194,15 @@ def get_package_for_value(list_package, value): class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm): plugins.implements(plugins.IConfigurer) - plugins.implements(plugins.IDatasetForm) + plugins.implements(plugins.IDatasetForm, inherit=True) plugins.implements(plugins.ITemplateHelpers) plugins.implements(plugins.IFacets) #plugins.implements(IRoutes, inherit=True) #ckan 2.10 plugins.implements(plugins.IBlueprint) + plugins.implements(plugins.IValidators) + plugins.implements(plugins.IPackageController, inherit=True) # IConfigurer def update_config(self, config_): @@ -219,37 +222,157 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) toolkit.add_resource('assets', 'd4science_theme') # toolkit.add_resource('assets', 'd4science_scripts') + def _modify_package_schema(self): + log.debug("*** modify package ***") + + # Personalizza il campo 'extras' rimuovendo il validatore extra_key_not_in_root_schema + + return { + 'private': [toolkit.get_validator('ignore_missing'), + toolkit.get_validator('boolean_validator')], + 'extras': { + 'id': [toolkit.get_validator('ignore')], # Ignora 'id' come prima + 'key': [toolkit.get_validator('not_empty'), toolkit.get_validator('unicode_safe'), validators.ignore_duplicate_keys], # Aggiunto ignore duplicate + 'value': [toolkit.get_validator('not_missing')] + } + } + #IDatasetForm def create_package_schema(self): # let's grab the default schema in our plugin + log.debug("creating package....") schema = super(D4Science_ThemePlugin, self).create_package_schema() - schema = remove_check_replicated_custom_key(schema) + log.debug("schema after create prima del validator %s", schema) + #schema = remove_check_replicated_custom_key(schema) + #schema.update(self._modify_package_schema(schema)) + schema.update(self._modify_package_schema()) #d.package_dict_save = _package_dict_save + log.debug("create_package1 %s", schema) return schema #IDatasetForm def update_package_schema(self): + log.debug("** update_package **") schema = super(D4Science_ThemePlugin, self).update_package_schema() - schema = remove_check_replicated_custom_key(schema) + #schema = remove_check_replicated_custom_key(schema) + #schema.update(self._modify_package_schema(schema)) + schema.update(self._modify_package_schema()) + log.debug("update_package1 %s", schema) return schema #IDatasetForm def show_package_schema(self): + log.debug("** show package **") schema = super(D4Science_ThemePlugin, self).show_package_schema() - schema = remove_check_replicated_custom_key(schema) + log.debug("show_package1 %s", schema) + #schema = remove_check_replicated_custom_key(schema) + #schema.update(self._modify_package_schema(schema)) + schema.update({ + 'extras': { + 'id': [toolkit.get_validator('ignore')], # Ignora 'id' come prima + 'key': [toolkit.get_validator('not_empty'), toolkit.get_validator('unicode_safe'), validators.ignore_duplicate_keys], # Aggiunto ignore duplicate + 'value': [toolkit.get_validator('not_missing')] + } + }) + log.debug("show_package2 %s", schema) return schema #IDatasetForm def is_fallback(self): # Return True to register this plugin as the default handler for package types not handled by any other IDatasetForm plugin - return False + return True #IDatasetForm def package_types(self): # This plugin doesn't handle any special package types, it just # registers itself as the default (above). return [] + + def get_validators(self): + return { + 'ignore_duplicate_keys': validators.ignore_duplicate_keys + } + #IPackageController + #def before_dataset_search(self, search_params): + # search_params = search_params or {} + # return search_params + # + #def after_dataset_search(self, search_results, data_dict): + # return search_results + # + #def before_search(self, search_params): + # # Controlla se search_params è None e sostituiscilo con un dizionario vuoto + # search_params = search_params or {} + # return search_params + # + #def before_create(self, context, data_dict): + # self.apply_custom_extras_validator(data_dict) + # + #def before_update(self, context, data_dict): + # self.apply_custom_extras_validator(data_dict) + # + + ## utile ## + #def before_dataset_save(self, context, data_dict): + # log.debug("sto chiamando before_dataset_save") + # # Intercetta il salvataggio dei dataset prima che venga effettuato il controllo + # extras_list = data_dict.get('extras', []) + # + # # Aggiungi una logica per evitare che venga applicato un controllo su chiavi duplicate + # # Si elimina la logica di validazione delle chiavi duplicate + # unique_extras = {} + # for extra in extras_list: + # key = extra.get('key') + # if key in unique_extras: + # # Consenti la duplicazione delle chiavi, quindi non lo filtriamo + # unique_extras[key].append(extra) + # else: + # unique_extras[key] = [extra] + # + # # Restituisci un nuovo 'extras' senza rimuovere le chiavi duplicate + # data_dict['extras'] = [e for extras in unique_extras.values() for e in extras] + # return data_dict + def convert_to_boolean(self, value): + log.debug("value boolean %s", value) + if isinstance(value, str): + if value.lower() == 'true': + return True + elif value.lower() == 'false': + return False + return value + + #IValidator + def validate(self, context, data_dict, schema, action): + # Modifica il comportamento del validatore per ignorare le chiavi duplicate + # Assicurati che 'private' sia un valore booleano + log.debug("calling, validate, questo è lo schema: %s", schema) + data_dict['private'] = self.convert_to_boolean(data_dict.get('private', False)) + errors = [] + #todo change this function + if 'extras' in data_dict: + log.debug("extras presente") + extras = data_dict['extras'] + new_extras = [] + log.debug("extras value before for: %s e lunghezza: %s", extras, len(extras)) + # Aggiungi ogni coppia chiave-valore alla nuova lista, mantenendo i duplicati + for extra in extras: + new_extras.append(extra) + log.debug("Aggiunta extra con chiave duplicata: %s -> %s", extra['key'], extra['value']) + + # Aggiorna il data_dict con la lista di extras che include i duplicati + data_dict['extras'] = new_extras + log.debug("new extras mantenendo i duplicati: %s", new_extras) + log.debug("pre return validate %s", data_dict) + return data_dict, errors + + def apply_custom_extras_validator(self, data_dict): + """ + Funzione helper per applicare il validator agli extras + """ + extras = data_dict.get('extras', []) + # Esegui il validator per assicurare il salvataggio dei duplicati + validators.ignore_duplicate_keys('extras', data_dict, [], {}) #ITemplateHelpers def get_helpers(self): @@ -290,6 +413,13 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) 'd4science_get_location_to_bboxes' : helpers.get_location_to_bboxes, 'd4science_get_content_moderator_system_placeholder': helpers.get_content_moderator_system_placeholder, 'd4science_get_site_statistics': helpers.get_site_statistics, + 'is_dataset_acquired': helpers.is_dataset_acquired, + 'get_allowed_users_str': helpers.get_allowed_users_str, + 'is_owner': helpers.is_owner, + 'can_read': helpers.can_read, + 'show_acquire_url_on_create': helpers.show_acquire_url_on_create, + 'show_acquire_url_on_edit': helpers.show_acquire_url_on_edit, + 'acquire_button': helpers.acquire_button } #Overriding package_extras_save method diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/package_item.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/package_item.html index 801d9c8..0e16bed 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/package_item.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/package_item.html @@ -1,70 +1,139 @@ {# -Displays a single of dataset. - -package - A package to display. -item_class - The class name to use on the list item. -hide_resources - If true hides the resources (default: false). - -Example: - - {% snippet 'snippets/package_item.html', package=c.datasets[0] %} - -#} -{% set title = package.title or package.name %} -{% set notes = h.markdown_extract(package.notes, extract_length=180) %} - -{% block package_item %} + Displays a single of dataset. + + package - A package to display. + item_class - The class name to use on the list item. + hide_resources - If true hides the resources (default: false). + banner - If true displays a popular banner (default: false). + truncate - The length to trucate the description to (default: 180) + truncate_title - The length to truncate the title to (default: 80). + + Example: + + {% snippet 'snippets/package_item.html', package=c.datasets[0] %} + + #} + + {% set truncate = truncate or 180 %} + {% set truncate_title = truncate_title or 80 %} + {% set title = package.title or package.name %} + {% set notes = h.markdown_extract(package.notes, extract_length=truncate) %} + + + {# + {% resource 'd4science_theme/custom.css' %} + CHANGED BY FRANCESCO.MANGIACRAPA + #} + + {% block package_item_content %} + + {% if package.private and not h.can_read(package) %}
  • - {% block content %}
    - {% block heading %} -

    - {% block heading_private %} - {% if package.private %} - - - {{ _('Private') }} - - {% endif %} - {% endblock %} - {% block heading_title %} - - {{title|truncate(80)}} - - {% endblock %} - {% block heading_meta %} - {% if package.get('state', '').startswith('draft') %} - {{ _('Draft') }} - {% elif package.get('state', '').startswith('deleted') %} - {{ _('Deleted') }} - {% endif %} - {{ h.popular('recent views', package.tracking_summary.recent, min=10) if package.tracking_summary }} - {% endblock %} -

    - {% endblock %} - {% block notes %} - {% if notes %} -
    {{ notes|urlize }}
    - {% else %} -

    {{ h.humanize_entity_type('package', package.type, 'no description') or _("There is no description for this dataset") }}

    +

    + {% if package.private and not h.can_read(package) %} + + + {{ _('Private') }} + {% endif %} - {% endblock %} -

    - {% block resources %} - {% if package.resources and not hide_resources %} - {% block resources_outer %} -
      - {% block resources_inner %} - {% for resource in h.dict_list_reduce(package.resources, 'format') %} -
    • - {{ resource }} -
    • - {% endfor %} - {% endblock %} -
    - {% endblock %} + + + + {% if package.private and not h.can_read(package) %} + {# {{ _(h.truncate(title, truncate_title)) }} #} + Dataset +
    + {{ h.acquire_button(package) }} + {% else %} + {# {{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }} #} + {{ h.link_to(h.truncate(title, truncate_title), url_for('dataset.read', id=package.name)) }} + {% endif %} + + + {% if package.get('state', '').startswith('draft') %} + {{ _('Draft') }} + {% elif package.get('state', '').startswith('deleted') %} + {{ _('Deleted') }} + {% endif %} + {{ h.popular('recent views', package.tracking_summary.recent, min=10) if package.tracking_summary }} + + {% if banner %} + {% endif %} - {% endblock %} - {% endblock %} + {% if notes %} + + {% endif %} +
  • -{% endblock %} + {% else %} +
  • +
    +

    + {% if package.private and not h.can_read(package) %} + + + {{ _('Private') }} + + {% endif %} + + + + {% if package.private and not h.can_read(package) %} + {{ _(h.truncate(title, truncate_title)) }} +
    + {{ h.acquire_button(package) }} + {% else %} + {# {{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name)) }} #} + {{ h.link_to(h.truncate(title, truncate_title), url_for('dataset.read', id=package.name)) }} + {% endif %} + + + {% if package.get('state', '').startswith('draft') %} + {{ _('Draft') }} + {% elif package.get('state', '').startswith('deleted') %} + {{ _('Deleted') }} + {% endif %} + {{ h.popular('recent views', package.tracking_summary.recent, min=10) if package.tracking_summary }} +

    + {% if banner %} + + {% endif %} + {% if notes %} +
    {{ notes|urlize }}
    + {% endif %} +
    + {% if package.resources and not hide_resources %} + + {% endif %} + +
  • + {% endif %} + {% endblock %} \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/validators.py b/ckanext-d4science_theme/ckanext/d4science_theme/validators.py new file mode 100644 index 0000000..f9780b7 --- /dev/null +++ b/ckanext-d4science_theme/ckanext/d4science_theme/validators.py @@ -0,0 +1,24 @@ +import ckan.plugins.toolkit as toolkit +from logging import getLogger + +log = getLogger(__name__) + +def ignore_duplicate_keys(key, data, errors, context): + """ + Validator che consente chiavi duplicate negli extras. + """ + # Estrarre gli extras dalla richiesta + log.debug("controllo extra (data) %s", data) + extras = data.get(key, []) + + # Log per il debugging + log.debug(f"Contenuto di 'data' per la chiave '{key}': {extras} (tipo: {type(extras)})") + + # Se ci sono duplicati, evita di sollevare un'eccezione + if isinstance(extras, list): # Verifica che extras sia una lista + log.debug(f"Ignorando chiave duplicata: {extra['key']}") + else: + log.debug(f"Errore: 'extras' non è una lista, ma è di tipo {type(extras)}") + + ## Mantieni la lista aggiornata, che consente chiavi duplicate + data[key] = extras \ No newline at end of file diff --git a/ckanext-d4science_theme/requirements.txt b/ckanext-d4science_theme/requirements.txt index 55f2a9b..0e23e19 100644 --- a/ckanext-d4science_theme/requirements.txt +++ b/ckanext-d4science_theme/requirements.txt @@ -1,3 +1,4 @@ webhelpers2 xmltodict pyqrcode +sqlalchemy diff --git a/ckanext-d4science_theme/setup.py b/ckanext-d4science_theme/setup.py index d3a3ba1..a616430 100644 --- a/ckanext-d4science_theme/setup.py +++ b/ckanext-d4science_theme/setup.py @@ -69,8 +69,7 @@ setup( # installed, specify them here. If using Python 2.6 or less, then these # have to be included in MANIFEST.in as well. include_package_data=True, - package_data={ - }, + #package_data={}, # Although 'package_data' is the preferred approach, in some case you may # need to place data files outside of your packages. From 610736b1c07f689f173ccd8fe47373aa686b592f Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Wed, 13 Nov 2024 15:52:11 +0100 Subject: [PATCH 2/6] feature: change template files according to template 2.6 (safe) --- .../templates/package/read.html | 47 ++++--- .../package/snippets/additional_info.html | 101 +++++++++++---- .../package/snippets/extras_table.html | 59 +++++++++ .../templates/package/snippets/info.html | 81 ++++++------ .../package/snippets/qrcdode_show.html | 6 + .../package/snippets/resource_item.html | 122 +++++++++++------- .../package/snippets/resources_list.html | 106 ++++++++++----- .../templates/snippets/tag_list.html | 2 +- 8 files changed, 363 insertions(+), 161 deletions(-) create mode 100644 ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/extras_table.html create mode 100644 ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/qrcdode_show.html diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/read.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/read.html index db5061f..a851298 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/read.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/read.html @@ -1,21 +1,24 @@ -{% extends "package/read_base.html" %} +{% ckan_extends %} +{% set dataset_extent = h.get_pkg_dict_extra(c.pkg_dict, 'spatial', '') %} +{% set d4science_cms_obj_placeholders = h.d4science_get_content_moderator_system_placeholder() %} +{% set moderation_item_status = h.get_pkg_dict_extra(c.pkg_dict,d4science_cms_obj_placeholders.item_status,'') %} {% block primary_content_inner %} - {{ super() }} - {% set dataset_extent = h.get_pkg_dict_extra(c.pkg_dict, 'spatial', '') %} - {% if dataset_extent %} - {% snippet "spatial/snippets/dataset_map.html", extent=dataset_extent %} - {% endif %} +{% if moderation_item_status %} + + {{ moderation_item_status }} + +{% endif %} {% block package_description %} {% if pkg.private %} - - + + {{ _('Private') }} {% endif %} -

    +
    {% block page_heading %} - {{ h.dataset_display_name(pkg) }} + {{ pkg.title or pkg.name }} {% if pkg.state.startswith('draft') %} [{{ _('Draft') }}] {% endif %} @@ -23,28 +26,34 @@ [{{ _('Deleted') }}] {% endif %} {% endblock %} -

    + {% block package_notes %} {% if pkg.notes %} -
    - {{ h.render_markdown(h.get_translated(pkg, 'notes')) }} +
    + {{ h.render_markdown(pkg.notes) }}
    {% endif %} {% endblock %} {# FIXME why is this here? seems wrong #} {% endblock %} + + + {% if dataset_extent %} + {% snippet "spatial/snippets/dataset_map.html", extent=dataset_extent %} + {% endif %} + + {% block package_tags %} +
    {{_('Tags')}}
    + {% snippet "package/snippets/tags.html", tags=pkg.tags %} + {% endblock %} {% block package_resources %} {% snippet "package/snippets/resources_list.html", pkg=pkg, resources=pkg.resources %} {% endblock %} - {% block package_tags %} - {% snippet "package/snippets/tags.html", tags=pkg.tags %} - {% endblock %} - {% block package_additional_info %} {% snippet "package/snippets/additional_info.html", pkg_dict=pkg %} {% endblock %} - -{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/additional_info.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/additional_info.html index d4070ce..e058199 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/additional_info.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/additional_info.html @@ -1,5 +1,74 @@ +{% set key_item_url = _('Item') + ' URL' %} + + + + +
    -

    {{ _('Additional Info') }}

    + {% block extras scoped %} + {# + This performs a sort + {% for extra in h.sorted_extras(pkg_dict.extras) %} + #} + {% if pkg_dict.extras %} + {# Added by Francesco Mangiacrapa, see 17901 #} + {% set extra_item_url = h.get_pkg_dict_extra(pkg_dict,key_item_url) %} + {% if extra_item_url %} +
    {{ key_item_url }}
    + + + + + +
    {{ extra_item_url }}{% snippet "package/snippets/qrcode_show.html", package_url=extra_item_url %}
    + {% endif %} + {% set extras_indexed_for_categories = h.d4science_get_extras_indexed_for_namespaces(pkg_dict.extras) %} + {% for k_cat in extras_indexed_for_categories %} + {% set category_idx = extras_indexed_for_categories[k_cat] %} + {% if(k_cat!='nocategory') %} +
    {{category_idx.category.title}}
    + {% if category_idx.category.description %} +

    Description: {{category_idx.category.description}}

    + {% endif %} + + + + + + + + + {% set my_extras = h.d4science_get_extra_for_category(extras_indexed_for_categories, k_cat) %} + {% snippet "package/snippets/extras_table.html", my_extras=my_extras, key_item_url=key_item_url %} + +
    {{ _('Field') }}{{ _('Value') }}
    +
    + {% endif %} + {% endfor %} + {% set my_extras = h.d4science_get_extra_for_category(extras_indexed_for_categories, 'nocategory') %} + {% if my_extras|length > 0 %} +
    {{ _('Additional Info') }}
    + + + + + + + + + {% snippet "package/snippets/extras_table.html", my_extras=my_extras, key_item_url=key_item_url %} + +
    {{ _('Field') }}{{ _('Value') }}
    +
    + {% endif %} + {% endif %} + {% endblock %} +
    {{ _('Management Info') }}
    @@ -13,11 +82,7 @@ {% if h.is_url(pkg_dict.url) %} - + {% else %} {% endif %} @@ -35,16 +100,17 @@ {% endif %} - + {# Added by Francesco Mangiacrapa #} + {% set user_maintainer = h.d4science_get_user_info(pkg_dict.maintainer) %} {% if pkg_dict.maintainer_email %} - + {% elif pkg_dict.maintainer %} - + {% endif %} @@ -78,18 +144,7 @@ {% endif %} - - {% block extras scoped %} - {% for extra in h.sorted_extras(pkg_dict.extras) %} - {% set key, value = extra %} - - - - - {% endfor %} - {% endblock %} - - {% endblock %} - +
    {{ _('Source') }} - - {{ pkg_dict.url }} - - {{ h.link_to(pkg_dict.url, pkg_dict.url, rel='foaf:homepage', target='_blank') }}{{ pkg_dict.url }}{{ pkg_dict.author }}
    {{ _('Maintainer') }}{{ h.mail_to(email_address=pkg_dict.maintainer_email, name=pkg_dict.maintainer) }}{{ h.mail_to(email_address=pkg_dict.maintainer_email, name=user_maintainer.fullname if (user_maintainer and user_maintainer.fullname) else pkg_dict.maintainer) }}
    {{ _('Maintainer') }}{{ pkg_dict.maintainer }}{{ user_maintainer.fullname if (user_maintainer and user_maintainer.fullname) else pkg_dict.maintainer }}
    {{ _(key|e) }}{{ value }}
    -
    + {% endblock %} + \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/extras_table.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/extras_table.html new file mode 100644 index 0000000..4a809cc --- /dev/null +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/extras_table.html @@ -0,0 +1,59 @@ + + + + {% set d4science_cms_obj_placeholders = h.d4science_get_content_moderator_system_placeholder() %} + {% for extra_lnk in my_extras %} + {% set index = loop.index %} + {% for k in extra_lnk.keys() %} + {# Added by Francesco Mangiacrapa, see: #21701 #} + {% set extra_value = extra_lnk[k] %} + + {% if extra_value is defined and extra_value|length %} + {# Added by Francesco Mangiacrapa, see: #7055 #} + {% set isHttp = extra_value.startswith(('http://', 'https://')) %} + + + {% if k != key_item_url and (not k.startswith(d4science_cms_obj_placeholders.prefix)) %} + {{ _(k) }} + {% if isHttp %} + {% if k == 'graphic-preview-file'%} + {{ + {% else %} + {{ extra_value }} + {% endif %} + {% elif k == 'responsible-party' %} +
    {{ extra_value }}
    + {% elif k == 'dataset-reference-date' %} +
    {{ extra_value }}
    + {% elif k == 'coupled-resource' %} +
    {{ extra_value }}
    + {% elif k.startswith('Zenodo') %} + + {% elif k == 'spatial' %} +
    {{ extra_value }}
    + {% else %} + {{ extra_value }} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% endfor %} \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/info.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/info.html index 20678ff..60420b8 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/info.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/info.html @@ -1,41 +1,48 @@ {# -Displays a sidebar module with information for given package - -pkg - The package dict that owns the resources. - -Example: - - {% snippet "package/snippets/info.html", pkg=pkg %} - -#} -{% block package_info %} - {% if pkg %} -
    -
    -
    - {% block package_info_inner %} - {% block heading %} -

    {{ h.dataset_display_name(pkg) }}

    - {% endblock %} - {% block nums %} - {% set num_followers = h.follow_count('dataset', pkg.id) %} -
    -
    -
    {{ _('Followers') }}
    -
    {{ h.SI_number_span(num_followers) }}
    -
    -
    - {% endblock %} - {% block follow_button %} - {% if not hide_follow_button %} - -
    - {% endif %} -{% endblock %} + + {% endif %} + {% endblock %} + \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/qrcdode_show.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/qrcdode_show.html new file mode 100644 index 0000000..a0ec361 --- /dev/null +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/qrcdode_show.html @@ -0,0 +1,6 @@ +{% set qr_code_image = h.d4science_get_qrcode_for_url(package_url) %} +{% block package_qrcode_for_url %} +
    {{
    +{% endblock %} + + \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resource_item.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resource_item.html index 31d1c56..0f668fc 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resource_item.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resource_item.html @@ -1,82 +1,108 @@ -{# - Renders a single resource with icons and view links. - - res - A resource dict to render - pkg - A package dict that the resource belongs to - can_edit - Whether the user is allowed to edit the resource - url_is_edit - Whether the link to the resource should be to editing it (set to False to make the link view the resource) - url - URL of the resource details page(resource edit/read depending on url_is_edit, by default). - - Example: - - {% snippet "package/snippets/resource_item.html", res=resource, pkg=pkg, can_edit=True, url_is_edit=False %} - -#} -{% set url_action = pkg.type ~ ('_resource.edit' if url_is_edit and can_edit else '_resource.read') %} -{% set url = url or h.url_for(url_action, id=pkg.name, resource_id=res.id) %} - +{% set can_edit = h.check_access('package_update', {'id':pkg.id }) %} +{% set url_action = 'resource_edit' if url_is_edit and can_edit else 'resource_read' %} +{# {% set url = h.url_for(controller='package', action=url_action, id=pkg.name, resource_id=res.id) %} #} +{% set url = h.url_for('dataset_resource.read', id=pkg.name, resource_id=res.id) %}
  • +{# Added by Francesco Mangiacrapa block custom_view_on_resources see:4851 #} +{% block custom_view_on_resources %} +{% set user = c.user %} +{% if user %} {% block resource_item_title %} - {{ h.resource_display_name(res) | truncate(50) }}{{ h.get_translated(res, 'format') }} - {{ h.popular('views', res.tracking_summary.total, min=10) if res.tracking_summary }} + {{ h.resource_display_name(res) | truncate(50) }}{{ res.format }} + {{ h.popular('views', res.tracking_summary.total, min=10) }} {% endblock %} {% block resource_item_description %}

    {% if res.description %} - {{ h.markdown_extract(h.get_translated(res, 'description'), extract_length=80) }} + {{ h.markdown_extract(res.description, extract_length=80) }} {% endif %}

    {% endblock %} {% block resource_item_explore %} {% if not url_is_edit %} + {# Only if can edit, explorer button is shown with several facility #} + {% if can_edit %} + {% else %} + + {{ _('Go to resource') }} + + {% endif %} {% endif %} {% endblock %} +{% else %} + {% block resource_item_title2 %} + {# Updated by Francesco Mangiacrapa, see: #10056 #} + + {{ h.resource_display_name(res) | truncate(50) }}{{ res.format }} + {{ h.popular('views', res.tracking_summary.total, min=10) }} + + {% endblock %} +
    + {% block resource_item_description2 %} +

    + {% if res.description %} + {{ h.markdown_extract(res.description, extract_length=80) }} + {% endif %} +

    + {% endblock %} + The resource: '{{ h.resource_display_name(res) | truncate(30) }}' is not accessible as guest user. You must login to access it! +
    +{% endif %} +{% endblock %}
  • + diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resources_list.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resources_list.html index 9c6dd63..3ab3b78 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resources_list.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/package/snippets/resources_list.html @@ -1,37 +1,77 @@ -{# +{# Renders a list of resources with icons and view links. - - resources - A list of resources (dicts) to render - pkg - A package dict that the resources belong to. - + + resources - A list of resources to render + pkg - A package object that the resources belong to. + Example: - - {% snippet "package/snippets/resources_list.html", pkg=pkg, resources=pkg.resources %} - + + {% snippet "package/snippets/resources_list.html", pkg=pkg, resources=pkg.resources %} + #} - -
    -

    {{ _('Data and Resources') }}

    - {% block resource_list %} - {% if resources %} -
      - {% block resource_list_inner %} - {% set can_edit = can_edit or h.check_access('package_update', {'id':pkg.id }) %} - {% for resource in resources %} - {% snippet 'package/snippets/resource_item.html', pkg=pkg, res=resource, can_edit=can_edit %} - {% endfor %} - {% endblock %} -
    - {% else %} - {% block resource_list_empty %} - {% if h.check_access('resource_create', {'package_id': pkg['id']}) %} - {% trans url=h.url_for(pkg.type ~ '_resource.new', id=pkg.name) %} -

    This dataset has no data, why not add some?

    - {% endtrans %} - {% else %} -

    {{ _('This dataset has no data') }}

    - {% endif %} - {% endblock %} + + + +
    +
    {{ _('Data and Resources') }}
    + {% set user = c.user %} + {# Added by Francesco Mangiacrapa #10389 #} + {% if not user %} +
    To access the resources you must log in
    {% endif %} - {% endblock %} -
    + {# end #} + {% block resource_list %} + {% if resources %} +
      + {% block resource_list_inner %} + {% for resource in resources %} + {% snippet 'package/snippets/resource_item.html', pkg=pkg, res=resource %} + {% endfor %} + {% endblock %} +
    + {% else %} + {% if h.check_access('resource_create', {'package_id': pkg['id']}) %} + {% trans url=h.url_for(controller='package', action='new_resource', id=pkg.name) %} +

    This dataset has no data, why not add some?

    + {% endtrans %} + {% else %} +

    {{ _('This dataset has no data') }}

    + {% endif %} + {% endif %} + {% endblock %} +
    + \ No newline at end of file diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/tag_list.html b/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/tag_list.html index 77f753e..52c9c8d 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/tag_list.html +++ b/ckanext-d4science_theme/ckanext/d4science_theme/templates/snippets/tag_list.html @@ -13,7 +13,7 @@ From 401fcbe1c7327ea5dc79a7bf189dfbaef7826421 Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Wed, 13 Nov 2024 15:52:26 +0100 Subject: [PATCH 3/6] fix: add comment --- ckanext-d4science_theme/ckanext/d4science_theme/validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/validators.py b/ckanext-d4science_theme/ckanext/d4science_theme/validators.py index f9780b7..0168c54 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/validators.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/validators.py @@ -21,4 +21,4 @@ def ignore_duplicate_keys(key, data, errors, context): log.debug(f"Errore: 'extras' non è una lista, ma è di tipo {type(extras)}") ## Mantieni la lista aggiornata, che consente chiavi duplicate - data[key] = extras \ No newline at end of file + #data[key] = extras \ No newline at end of file From 890b920e1b785e16adae1e538639f91874d7c5be Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Thu, 28 Nov 2024 15:19:55 +0100 Subject: [PATCH 4/6] add duplicate keys in extras (missing delete and update) --- .../ckanext/d4science_theme/plugin.py | 350 +++++++++++------- 1 file changed, 212 insertions(+), 138 deletions(-) diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py index 9431c59..e6c9b30 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py @@ -10,16 +10,28 @@ import ckan.model as model from ckanext.d4science_theme.controllers.home import d4SHomeController from ckanext.d4science_theme.controllers.systemtype import d4STypeController from ckanext.d4science_theme.controllers.organization import OrganizationVREController +import sqlalchemy as sa +from ckan.config.middleware.common_middleware import TrackingMiddleware +import ckan.lib.dictization.model_save as model_save #from ckan.controllers.home import HomeController #from ckan.plugins import IRoutes from flask import Blueprint, render_template +from ckan.types import Context + +from typing import ( + Any, Collection, Optional, TYPE_CHECKING, Type, Union, cast, overload, + Literal, +) + +if TYPE_CHECKING: + import ckan.model as modelDict from ckan.common import ( g ) from flask import Flask, g from ckan.lib.app_globals import app_globals -import ckan.plugins.toolkit as toolkit +from ckan.logic import get_action # Created by Francesco Mangiacrapa @@ -38,145 +50,178 @@ def remove_check_replicated_custom_key(schema): #CREATED BY FRANCESCO MANGIACRAPA FOR OVERRIDING THE package_extras_save FROM dictization.model_save.py # Is this needed? -def _package_extras_save(extra_dicts, obj, context): - ''' It can save repeated extras as key-value ''' +def _package_extras_save(extra_dicts: Optional[list[dict[str, Any]]], pkg: 'model.Package', + context: Context) -> None: allow_partial_update = context.get("allow_partial_update", False) if extra_dicts is None and allow_partial_update: + log.debug("extra dicts is NONE") return - - model = context["model"] + + log.debug("USING CUSTOM SAVE") + #pass + #model = context["model"] session = context["session"] - - #ADDED BY FRANCESCO MANGIACRAPA - log.debug("extra_dicts: %s", extra_dicts) - #print "extra_dicts: "+str(extra_dicts) - - extras_list = obj.extras_list - #extras = dict((extra.key, extra) for extra in extras_list) - old_extras = {} - extras = {} - for extra in extras_list or []: - old_extras.setdefault(extra.key, []).append(extra.value) - extras.setdefault(extra.key, []).append(extra) + + old_extras = pkg._extras + log.debug("OLD_EXTRAS", old_extras) - #ADDED BY FRANCESCO MANGIACRAPA - #print "old_extras: "+str(old_extras) - - new_extras = {} + new_extras = [] # Lista di dizionari per supportare chiavi duplicate for extra_dict in extra_dicts or []: - #print 'extra_dict key: '+extra_dict["key"] + ', value: '+extra_dict["value"] - #new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) if extra_dict.get("deleted"): - log.debug("extra_dict deleted: %s ", extra_dict["key"]) - #print 'extra_dict deleted: '+extra_dict["key"] continue - #if extra_dict['value'] is not None and not extra_dict["value"] == "": - if extra_dict['value'] is not None: - new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) + if extra_dict['value'] is None: + pass + else: + new_extras.append({"key": extra_dict["key"], "value": extra_dict["value"]}) - #ADDED BY FRANCESCO MANGIACRAPA - log.debug("new_extras: %s", new_extras) - #print "new_extras: "+str(new_extras) + # new + log.debug("new_extra:", new_extras) + for new_extra in new_extras: + new_key = new_extra["key"] + new_value = new_extra["value"] - #new - for key in set(new_extras.keys()) - set(old_extras.keys()): - state = 'active' - log.debug("adding key: %s", key) - #print "adding key: "+str(key) - extra_lst = new_extras[key] - for extra in extra_lst: - extra = model.PackageExtra(state=state, key=key, value=extra) - session.add(extra) - extras_list.append(extra) + # Verifica se l'extra esiste già in old_extras con lo stesso valore + if not any(extra.key == new_key and extra.value == new_value for extra in old_extras.values()): + # Crea un nuovo extra solo se non esiste già proviamo ad usare il modello packageExtra + #extra = {"key": key, "value": value} + extra = model.PackageExtra(key = new_key, value = new_value, package_id = pkg.id, state= 'active') #state? + log.debug("extra:", extra) + session.add(extra) + #pkg.extras[key] = value + #log.debug("pkg.extras[key]", pkg.extras) + + # changed + for extra in old_extras.values(): + matching_new_extras = [new_extra for new_extra in new_extras if new_extra["key"] == extra.key] + log.debug("MATCHING EXTRAS", matching_new_extras) + if matching_new_extras: + for new_extra in matching_new_extras: + if new_extra["value"] != extra.value: + # Aggiorna il valore se differente + extra.value = new_extra["value"] + extra.state = 'active' + log.debug("changed", extra) + #session.add(extra) per l'update non dovrebbe servire + + # deleted + log.debug("Pre delete", old_extras, old_extras.values()) + log.debug("new extra pre delete", new_extra) + to_delete = [ + extra for extra in old_extras.values() + if not any(new_extra["key"] == extra.key and new_extra["value"] == extra.value for new_extra in new_extras) + ] + log.debug("TO DELETE", to_delete) + for extra in to_delete: + log.debug('delete extra', extra) + extra.state = 'deleted' + session.delete(extra) - #deleted - for key in set(old_extras.keys()) - set(new_extras.keys()): - log.debug("deleting key: "+str(key)) - #print "deleting key: "+str(key) - extra_lst = extras[key] - for extra in extra_lst: - state = 'deleted' - extra.state = state - extras_list.remove(extra) - - #changed - for key in set(new_extras.keys()) & set(old_extras.keys()): - #for each value of new list - for value in new_extras[key]: - old_occur = old_extras[key].count(value) - new_occur = new_extras[key].count(value) - log.debug("value: %s\n new_occur: %s\n old_occur: %s", value, new_occur, old_occur) - #print "value: "+str(value) + ", new_occur: "+str(new_occur) + ", old_occur: "+str(old_occur) - # it is an old value deleted or not - if value in old_extras[key]: - if old_occur == new_occur: - #print "extra - occurrences of: "+str(value) +", are equal into both list" - log.debug("extra - occurrences of: %s are equal into both list", value) - #there is a little bug, this code return always the first element, so I'm fixing with #FIX-STATUS - extra_values = get_package_for_value(extras[key], value) - #extras_list.append(extra) - for extra in extra_values: - state = 'active' - extra.state = state - session.add(extra) - #print "extra updated: "+str(extra) - log.debug("extra updated: %s", extra) - - elif new_occur > old_occur: - #print "extra - a new occurrence of: "+str(value) +", is present into new list, adding it to old list" - log.debug("extra - a new occurrence of: %s, is present into new list, adding it to old list", value) - state = 'active' - extra = model.PackageExtra(state=state, key=key, value=value) - extra.state = state - session.add(extra) - extras_list.append(extra) - old_extras[key].append(value) - log.debug("old extra values updated: %s", old_extras[key]) - #print "old extra values updated: "+str(old_extras[key]) - - else: - #remove all occurrences deleted - this code could be optimized, it is run several times but could be performed one shot - countDelete = old_occur-new_occur - log.debug("extra - occurrence of: %s, is not present into new list, removing: %s occurrence/s from old list", value, countDelete) - #print "extra - occurrence of: "+str(value) +", is not present into new list, removing "+str(countDelete)+" occurrence/s from old list" - extra_values = get_package_for_value(extras[key], value) - for idx, extra in enumerate(extra_values): - if idx < countDelete: - #print "extra - occurrence of: "+str(value) +", is not present into new list, removing it from old list" - log.debug("pkg extra deleting: %s", extra.value) - #print "pkg extra deleting: "+str(extra.value) - state = 'deleted' - extra.state = state - - else: - #print "pkg extra reactivating: "+str(extra.value) - log.debug("pkg extra reactivating: %s", extra.value) - state = 'active' - extra.state = state - session.add(extra) - - else: - #print "extra new value: "+str(value) - log.debug("extra new value: %s", value) - state = 'active' - extra = model.PackageExtra(state=state, key=key, value=value) - extra.state = state - session.add(extra) - extras_list.append(extra) - - - #for each value of old list - for value in old_extras[key]: - #if value is not present in new list - if value not in new_extras[key]: - extra_values = get_package_for_value(extras[key], value) - for extra in extra_values: - #print "not present extra deleting: "+str(extra) - log.debug("not present extra deleting: "+str(extra)) - state = 'deleted' - extra.state = state + ##ADDED BY FRANCESCO MANGIACRAPA + # + #extras_list = pkg.extras + ##extras_list = list(obj.extras) + ##extras = dict((extra.key, extra) for extra in extras_list) + #old_extras = {} + ##old_extras = {extra.key: extra for extra in extras_list} + #extras = {} + #for extra in extras_list or []: + # old_extras.setdefault(extra.key, []).append(extra.value) + # extras.setdefault(extra.key, []).append(extra) + # + ##ADDED BY FRANCESCO MANGIACRAPA + ##print "old_extras: "+str(old_extras) + # + #new_extras = {} + #for extra_dict in extra_dicts or []: + # #new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) + # if extra_dict.get("deleted"): + # continue + # + # #if extra_dict['value'] is not None and not extra_dict["value"] == "": + # if extra_dict['value'] is not None: + # new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) + # + ##ADDED BY FRANCESCO MANGIACRAPA + #log.debug("new_extras: %s", new_extras) + ##print "new_extras: "+str(new_extras) + # + ##new + #for key in set(new_extras.keys()) - set(old_extras.keys()): + # state = 'active' + # extra_lst = new_extras[key] + # for extra in extra_lst: + # extra = model.PackageExtra(state=state, key=key, value=extra) + # session.add(extra) + # extras_list.append(extra) + # + ##deleted + #for key in set(old_extras.keys()) - set(new_extras.keys()): + # extra_lst = extras[key] + # for extra in extra_lst: + # state = 'deleted' + # extra.state = state + # extras_list.remove(extra) + # + ##changed + #for key in set(new_extras.keys()) & set(old_extras.keys()): + # #for each value of new list + # for value in new_extras[key]: + # old_occur = old_extras[key].count(value) + # new_occur = new_extras[key].count(value) + # # it is an old value deleted or not + # if value in old_extras[key]: + # if old_occur == new_occur: + # #there is a little bug, this code return always the first element, so I'm fixing with #FIX-STATUS + # extra_values = get_package_for_value(extras[key], value) + # #extras_list.append(extra) + # for extra in extra_values: + # state = 'active' + # extra.state = state + # session.add(extra) + # #print "extra updated: "+str(extra) + # log.debug("extra updated: %s", extra) + # + # elif new_occur > old_occur: + # state = 'active' + # extra = model.PackageExtra(state=state, key=key, value=value) + # extra.state = state + # session.add(extra) + # extras_list.append(extra) + # old_extras[key].append(value) + # + # else: + # #remove all occurrences deleted - this code could be optimized, it is run several times but could be performed one shot + # countDelete = old_occur-new_occur + # extra_values = get_package_for_value(extras[key], value) + # for idx, extra in enumerate(extra_values): + # if idx < countDelete: + # state = 'deleted' + # extra.state = state + # + # else: + # state = 'active' + # extra.state = state + # session.add(extra) + # + # else: + # state = 'active' + # extra = model.PackageExtra(state=state, key=key, value=value) + # extra.state = state + # session.add(extra) + # extras_list.append(extra) + # + # + # #for each value of old list + # for value in old_extras[key]: + # #if value is not present in new list + # if value not in new_extras[key]: + # extra_values = get_package_for_value(extras[key], value) + # for extra in extra_values: + # state = 'deleted' + # extra.state = state + #ADDED BY FRANCESCO MANGIACRAPA def get_package_for_value(list_package, value): @@ -191,6 +236,31 @@ def get_package_for_value(list_package, value): return lst +#OVERRIDING BASE SQL ALCHEMY ENGINE INSTANCE serve per la connessione con gcube? +def _init_TrackingMiddleware(self, app, config): + self.app = app + log.debug('TrackingMiddleware d4Science instance') + sqlalchemy_url = config.get('sqlalchemy.url') + log.debug('sqlalchemy_url read: '+str(sqlalchemy_url)) + + sqlalchemy_pool = config.get('sqlalchemy.pool_size') + if sqlalchemy_pool is None: + sqlalchemy_pool = 5 + + log.debug('sqlalchemy_pool read: '+str(sqlalchemy_pool)) + sqlalchemy_overflow = config.get('sqlalchemy.max_overflow') + + if sqlalchemy_overflow is None: + sqlalchemy_overflow = 10 + + log.debug('sqlalchemy_overflow read: '+str(sqlalchemy_overflow)) + + try: + self.engine = sa.create_engine(sqlalchemy_url, pool_size=int(sqlalchemy_pool), max_overflow=int(sqlalchemy_overflow)) + except TypeError as e: + log.error('pool size does not work: ' +str(e.args)) + self.engine = sa.create_engine(sqlalchemy_url) + class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm): plugins.implements(plugins.IConfigurer) @@ -220,7 +290,6 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) # that we'll use to refer to this fanstatic directory from CKAN # templates. toolkit.add_resource('assets', 'd4science_theme') - # toolkit.add_resource('assets', 'd4science_scripts') def _modify_package_schema(self): log.debug("*** modify package ***") @@ -242,30 +311,33 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) # let's grab the default schema in our plugin log.debug("creating package....") schema = super(D4Science_ThemePlugin, self).create_package_schema() - log.debug("schema after create prima del validator %s", schema) - #schema = remove_check_replicated_custom_key(schema) + #log.debug("schema after create prima del validator %s", schema) + schema = remove_check_replicated_custom_key(schema) + #log.debug("create_package1 (remove __before): %s", schema) #schema.update(self._modify_package_schema(schema)) schema.update(self._modify_package_schema()) #d.package_dict_save = _package_dict_save - log.debug("create_package1 %s", schema) + #log.debug("create_package2 (remove extras validator): %s", schema) return schema #IDatasetForm def update_package_schema(self): log.debug("** update_package **") schema = super(D4Science_ThemePlugin, self).update_package_schema() - #schema = remove_check_replicated_custom_key(schema) + schema = remove_check_replicated_custom_key(schema) + #log.debug("update_package1 (remove __before) %s", schema) #schema.update(self._modify_package_schema(schema)) schema.update(self._modify_package_schema()) - log.debug("update_package1 %s", schema) + #log.debug("update_package2 (remove extras validator) %s", schema) return schema #IDatasetForm def show_package_schema(self): log.debug("** show package **") schema = super(D4Science_ThemePlugin, self).show_package_schema() - log.debug("show_package1 %s", schema) - #schema = remove_check_replicated_custom_key(schema) + #log.debug("show_package1 %s", schema) + schema = remove_check_replicated_custom_key(schema) + #log.debug("show_package1.5 no before %s", schema) #schema.update(self._modify_package_schema(schema)) schema.update({ 'extras': { @@ -274,7 +346,7 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) 'value': [toolkit.get_validator('not_missing')] } }) - log.debug("show_package2 %s", schema) + #log.debug("show_package2 %s", schema) return schema #IDatasetForm @@ -424,7 +496,7 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) #Overriding package_extras_save method # Is this needed? - # model_save.package_extras_save = _package_extras_save + model_save.package_extras_save = _package_extras_save #Overriding index home controller - rimosso in ckan 2.10 #d4sHC = d4SHomeController() @@ -432,6 +504,9 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) global d4s_ctg_namespaces_controller + #OVERRIDING BASE SQL ALCHEMY ENGINE INSTANCE + TrackingMiddleware.__init__ = _init_TrackingMiddleware + #if d4s_ctg_namespaces_controller is None: # log.info("d4s_ctg_namespaces_controller instancing...") # d4s_ctg_namespaces_controller = helpers.get_d4s_namespace_controller() @@ -567,4 +642,3 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) return facets_dict - From 691798a2b96a276c8be179f64f9b27315539431f Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Fri, 29 Nov 2024 14:36:32 +0100 Subject: [PATCH 5/6] feat: duplicate key in extras update d4science theme to ckan 2.10 --- .../ckanext/d4science_theme/plugin.py | 312 +++++------------- 1 file changed, 91 insertions(+), 221 deletions(-) diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py index e6c9b30..0a50fa7 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py @@ -23,21 +23,12 @@ from typing import ( Literal, ) -if TYPE_CHECKING: - import ckan.model as modelDict - from ckan.common import ( g ) from flask import Flask, g -from ckan.lib.app_globals import app_globals -from ckan.logic import get_action -# Created by Francesco Mangiacrapa -# francesco.mangiacrapa@isti.cnr.it -# ISTI-CNR Pisa (ITALY) - log = getLogger(__name__) d4s_ctg_namespaces_controller = None @@ -48,193 +39,112 @@ def remove_check_replicated_custom_key(schema): return schema -#CREATED BY FRANCESCO MANGIACRAPA FOR OVERRIDING THE package_extras_save FROM dictization.model_save.py -# Is this needed? -def _package_extras_save(extra_dicts: Optional[list[dict[str, Any]]], pkg: 'model.Package', +def _package_extras_save( + extra_dicts: Optional[list[dict[str, Any]]], pkg: 'model.Package', context: Context) -> None: allow_partial_update = context.get("allow_partial_update", False) if extra_dicts is None and allow_partial_update: - log.debug("extra dicts is NONE") return - - log.debug("USING CUSTOM SAVE") - #pass - #model = context["model"] + session = context["session"] - - old_extras = pkg._extras - log.debug("OLD_EXTRAS", old_extras) + model = context["model"] + #extras_list = obj.extras_list + extras_list = session.query(model.PackageExtra).filter_by(package_id=pkg.id).all() + #extras = dict((extra.key, extra) for extra in extras_list) + old_extras = {} + extras = {} + for extra in extras_list or []: + old_extras.setdefault(extra.key, []).append(extra.value) + extras.setdefault(extra.key, []).append(extra) - new_extras = [] # Lista di dizionari per supportare chiavi duplicate + new_extras = {} for extra_dict in extra_dicts or []: + #new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) if extra_dict.get("deleted"): continue - if extra_dict['value'] is None: - pass - else: - new_extras.append({"key": extra_dict["key"], "value": extra_dict["value"]}) + #if extra_dict['value'] is not None and not extra_dict["value"] == "": + if extra_dict['value'] is not None: + new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) - # new - log.debug("new_extra:", new_extras) - for new_extra in new_extras: - new_key = new_extra["key"] - new_value = new_extra["value"] - - # Verifica se l'extra esiste già in old_extras con lo stesso valore - if not any(extra.key == new_key and extra.value == new_value for extra in old_extras.values()): - # Crea un nuovo extra solo se non esiste già proviamo ad usare il modello packageExtra - #extra = {"key": key, "value": value} - extra = model.PackageExtra(key = new_key, value = new_value, package_id = pkg.id, state= 'active') #state? - log.debug("extra:", extra) - session.add(extra) - #pkg.extras[key] = value - #log.debug("pkg.extras[key]", pkg.extras) - - # changed - for extra in old_extras.values(): - matching_new_extras = [new_extra for new_extra in new_extras if new_extra["key"] == extra.key] - log.debug("MATCHING EXTRAS", matching_new_extras) - if matching_new_extras: - for new_extra in matching_new_extras: - if new_extra["value"] != extra.value: - # Aggiorna il valore se differente - extra.value = new_extra["value"] - extra.state = 'active' - log.debug("changed", extra) - #session.add(extra) per l'update non dovrebbe servire - - # deleted - log.debug("Pre delete", old_extras, old_extras.values()) - log.debug("new extra pre delete", new_extra) - to_delete = [ - extra for extra in old_extras.values() - if not any(new_extra["key"] == extra.key and new_extra["value"] == extra.value for new_extra in new_extras) - ] - log.debug("TO DELETE", to_delete) - for extra in to_delete: - log.debug('delete extra', extra) - extra.state = 'deleted' - session.delete(extra) + #new + for key in set(new_extras.keys()) - set(old_extras.keys()): + state = 'active' + extra_lst = new_extras[key] + for extra in extra_lst: + extra = model.PackageExtra(state=state, key=key, value=extra, package_id = pkg.id) + session.add(extra) + extras_list.append(extra) + #deleted + for key in set(old_extras.keys()) - set(new_extras.keys()): + extra_lst = extras[key] + for extra in extra_lst: + state = 'deleted' + extra.state = state + extras_list.remove(extra) + + #changed + for key in set(new_extras.keys()) & set(old_extras.keys()): + #for each value of new list + for value in new_extras[key]: + old_occur = old_extras[key].count(value) + new_occur = new_extras[key].count(value) + # it is an old value deleted or not + if value in old_extras[key]: + if old_occur == new_occur: + #there is a little bug, this code return always the first element, so I'm fixing with #FIX-STATUS + extra_values = get_package_for_value(extras[key], value) + #extras_list.append(extra) + for extra in extra_values: + state = 'active' + extra.state = state + session.add(extra) + + elif new_occur > old_occur: + state = 'active' + extra = model.PackageExtra(state=state, key=key, value=value, package_id = pkg.id) + extra.state = state + session.add(extra) + extras_list.append(extra) + old_extras[key].append(value) + + else: + #remove all occurrences deleted - this code could be optimized, it is run several times but could be performed one shot + countDelete = old_occur-new_occur + extra_values = get_package_for_value(extras[key], value) + for idx, extra in enumerate(extra_values): + if idx < countDelete: + state = 'deleted' + extra.state = state + + else: + state = 'active' + extra.state = state + session.add(extra) #valuta se metterlo dentro il for, ma fuori dall'else + + else: + state = 'active' + extra = model.PackageExtra(state=state, key=key, value=value, package_id = pkg.id) + extra.state = state + session.add(extra) + extras_list.append(extra) + + + #for each value of old list + for value in old_extras[key]: + #if value is not present in new list + if value not in new_extras[key]: + extra_values = get_package_for_value(extras[key], value) + for extra in extra_values: + state = 'deleted' + extra.state = state + #add session.delete(extra)? - ##ADDED BY FRANCESCO MANGIACRAPA - # - #extras_list = pkg.extras - ##extras_list = list(obj.extras) - ##extras = dict((extra.key, extra) for extra in extras_list) - #old_extras = {} - ##old_extras = {extra.key: extra for extra in extras_list} - #extras = {} - #for extra in extras_list or []: - # old_extras.setdefault(extra.key, []).append(extra.value) - # extras.setdefault(extra.key, []).append(extra) - # - ##ADDED BY FRANCESCO MANGIACRAPA - ##print "old_extras: "+str(old_extras) - # - #new_extras = {} - #for extra_dict in extra_dicts or []: - # #new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) - # if extra_dict.get("deleted"): - # continue - # - # #if extra_dict['value'] is not None and not extra_dict["value"] == "": - # if extra_dict['value'] is not None: - # new_extras.setdefault(extra_dict["key"], []).append(extra_dict["value"]) - # - ##ADDED BY FRANCESCO MANGIACRAPA - #log.debug("new_extras: %s", new_extras) - ##print "new_extras: "+str(new_extras) - # - ##new - #for key in set(new_extras.keys()) - set(old_extras.keys()): - # state = 'active' - # extra_lst = new_extras[key] - # for extra in extra_lst: - # extra = model.PackageExtra(state=state, key=key, value=extra) - # session.add(extra) - # extras_list.append(extra) - # - ##deleted - #for key in set(old_extras.keys()) - set(new_extras.keys()): - # extra_lst = extras[key] - # for extra in extra_lst: - # state = 'deleted' - # extra.state = state - # extras_list.remove(extra) - # - ##changed - #for key in set(new_extras.keys()) & set(old_extras.keys()): - # #for each value of new list - # for value in new_extras[key]: - # old_occur = old_extras[key].count(value) - # new_occur = new_extras[key].count(value) - # # it is an old value deleted or not - # if value in old_extras[key]: - # if old_occur == new_occur: - # #there is a little bug, this code return always the first element, so I'm fixing with #FIX-STATUS - # extra_values = get_package_for_value(extras[key], value) - # #extras_list.append(extra) - # for extra in extra_values: - # state = 'active' - # extra.state = state - # session.add(extra) - # #print "extra updated: "+str(extra) - # log.debug("extra updated: %s", extra) - # - # elif new_occur > old_occur: - # state = 'active' - # extra = model.PackageExtra(state=state, key=key, value=value) - # extra.state = state - # session.add(extra) - # extras_list.append(extra) - # old_extras[key].append(value) - # - # else: - # #remove all occurrences deleted - this code could be optimized, it is run several times but could be performed one shot - # countDelete = old_occur-new_occur - # extra_values = get_package_for_value(extras[key], value) - # for idx, extra in enumerate(extra_values): - # if idx < countDelete: - # state = 'deleted' - # extra.state = state - # - # else: - # state = 'active' - # extra.state = state - # session.add(extra) - # - # else: - # state = 'active' - # extra = model.PackageExtra(state=state, key=key, value=value) - # extra.state = state - # session.add(extra) - # extras_list.append(extra) - # - # - # #for each value of old list - # for value in old_extras[key]: - # #if value is not present in new list - # if value not in new_extras[key]: - # extra_values = get_package_for_value(extras[key], value) - # for extra in extra_values: - # state = 'deleted' - # extra.state = state - -#ADDED BY FRANCESCO MANGIACRAPA def get_package_for_value(list_package, value): - ''' Returns a list of packages containing the value passed in input - ''' - lst = [] - for x in list_package: - if x.value == value: - lst.append(x) - else: - return lst - - return lst + '''Returns a list of packages containing the value passed in input''' + return [x for x in list_package if x.value == value] #OVERRIDING BASE SQL ALCHEMY ENGINE INSTANCE serve per la connessione con gcube? def _init_TrackingMiddleware(self, app, config): @@ -364,47 +274,7 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) return { 'ignore_duplicate_keys': validators.ignore_duplicate_keys } - - #IPackageController - #def before_dataset_search(self, search_params): - # search_params = search_params or {} - # return search_params - # - #def after_dataset_search(self, search_results, data_dict): - # return search_results - # - #def before_search(self, search_params): - # # Controlla se search_params è None e sostituiscilo con un dizionario vuoto - # search_params = search_params or {} - # return search_params - # - #def before_create(self, context, data_dict): - # self.apply_custom_extras_validator(data_dict) - # - #def before_update(self, context, data_dict): - # self.apply_custom_extras_validator(data_dict) - # - ## utile ## - #def before_dataset_save(self, context, data_dict): - # log.debug("sto chiamando before_dataset_save") - # # Intercetta il salvataggio dei dataset prima che venga effettuato il controllo - # extras_list = data_dict.get('extras', []) - # - # # Aggiungi una logica per evitare che venga applicato un controllo su chiavi duplicate - # # Si elimina la logica di validazione delle chiavi duplicate - # unique_extras = {} - # for extra in extras_list: - # key = extra.get('key') - # if key in unique_extras: - # # Consenti la duplicazione delle chiavi, quindi non lo filtriamo - # unique_extras[key].append(extra) - # else: - # unique_extras[key] = [extra] - # - # # Restituisci un nuovo 'extras' senza rimuovere le chiavi duplicate - # data_dict['extras'] = [e for extras in unique_extras.values() for e in extras] - # return data_dict def convert_to_boolean(self, value): log.debug("value boolean %s", value) if isinstance(value, str): From 543a954125186a20e2f2d0e2e4722d14fad1b8d2 Mon Sep 17 00:00:00 2001 From: Alessio Fabrizio Date: Fri, 29 Nov 2024 15:22:36 +0100 Subject: [PATCH 6/6] style: :fire: removed comments removed comments --- ckanext-d4science_theme/ckanext/d4science_theme/plugin.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py index 0a50fa7..2076b60 100644 --- a/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py +++ b/ckanext-d4science_theme/ckanext/d4science_theme/plugin.py @@ -224,7 +224,6 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) #log.debug("schema after create prima del validator %s", schema) schema = remove_check_replicated_custom_key(schema) #log.debug("create_package1 (remove __before): %s", schema) - #schema.update(self._modify_package_schema(schema)) schema.update(self._modify_package_schema()) #d.package_dict_save = _package_dict_save #log.debug("create_package2 (remove extras validator): %s", schema) @@ -236,7 +235,6 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) schema = super(D4Science_ThemePlugin, self).update_package_schema() schema = remove_check_replicated_custom_key(schema) #log.debug("update_package1 (remove __before) %s", schema) - #schema.update(self._modify_package_schema(schema)) schema.update(self._modify_package_schema()) #log.debug("update_package2 (remove extras validator) %s", schema) return schema @@ -248,7 +246,6 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) #log.debug("show_package1 %s", schema) schema = remove_check_replicated_custom_key(schema) #log.debug("show_package1.5 no before %s", schema) - #schema.update(self._modify_package_schema(schema)) schema.update({ 'extras': { 'id': [toolkit.get_validator('ignore')], # Ignora 'id' come prima @@ -256,7 +253,6 @@ class D4Science_ThemePlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm) 'value': [toolkit.get_validator('not_missing')] } }) - #log.debug("show_package2 %s", schema) return schema #IDatasetForm