From 204d807b969727a1dd2f547e96eeeefb2b20cee4 Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 28 Mar 2012 18:12:26 +0100 Subject: [PATCH 001/109] domain_object fixes --- ckan/lib/search/__init__.py | 3 ++- ckan/model/authorization_group.py | 6 +++--- ckan/model/authz.py | 7 ++++--- ckan/model/core.py | 6 +++--- ckan/model/domain_object.py | 8 ++++---- ckan/model/group_extra.py | 3 ++- ckan/model/package_extra.py | 3 ++- ckan/model/package_relationship.py | 3 ++- ckan/model/rating.py | 3 ++- ckan/model/resource.py | 5 +++-- ckan/model/task_status.py | 3 ++- ckan/model/types.py | 17 ++++++++--------- ckan/model/user.py | 4 ++-- ckan/model/vocabulary.py | 5 +++-- 14 files changed, 42 insertions(+), 34 deletions(-) diff --git a/ckan/lib/search/__init__.py b/ckan/lib/search/__init__.py index fbb924a8faa..9072b55edb8 100644 --- a/ckan/lib/search/__init__.py +++ b/ckan/lib/search/__init__.py @@ -5,6 +5,7 @@ from ckan.model import DomainObjectOperation from ckan.plugins import SingletonPlugin, implements, IDomainObjectModification from ckan.logic import get_action +import ckan.model.domain_object from common import (SearchIndexError, SearchError, SearchQueryError, make_connection, is_available, SolrSettings) @@ -58,7 +59,7 @@ def text_traceback(): _QUERIES['package'] = sql.PackageSearchQuery def _normalize_type(_type): - if isinstance(_type, model.DomainObject): + if isinstance(_type, ckan.model.domain_object.DomainObject): _type = _type.__class__ if isinstance(_type, type): _type = _type.__name__ diff --git a/ckan/model/authorization_group.py b/ckan/model/authorization_group.py index 55720c562c1..d00241b5c55 100644 --- a/ckan/model/authorization_group.py +++ b/ckan/model/authorization_group.py @@ -1,9 +1,9 @@ import datetime from meta import * -from core import DomainObject from user import User, user_table from types import make_uuid +import domain_object authorization_group_table = Table('authorization_group', metadata, Column('id', UnicodeText, primary_key=True, default=make_uuid), @@ -19,7 +19,7 @@ ) -class AuthorizationGroup(DomainObject): +class AuthorizationGroup(domain_object.DomainObject): @classmethod def search(cls, querystr, sqlalchemy_query=None): @@ -42,7 +42,7 @@ def get(cls, auth_group_reference): cls.id==auth_group_reference)) return query.first() -class AuthorizationGroupUser(DomainObject): +class AuthorizationGroupUser(domain_object.DomainObject): pass def user_in_authorization_group(user, authorization_group): diff --git a/ckan/model/authz.py b/ckan/model/authz.py index 72695733999..b7c627c588b 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -10,6 +10,7 @@ from user import User from core import System from authorization_group import AuthorizationGroup, authorization_group_table +import domain_object PSEUDO_USER__LOGGED_IN = u'logged_in' PSEUDO_USER__VISITOR = u'visitor' @@ -121,7 +122,7 @@ class Role(Enum): ) -class RoleAction(DomainObject): +class RoleAction(domain_object.DomainObject): def __repr__(self): return '<%s role="%s" action="%s" context="%s">' % \ (self.__class__.__name__, self.role, self.action, self.context) @@ -130,7 +131,7 @@ def __repr__(self): # dictionary mapping protected objects (e.g. Package) to related ObjectRole protected_objects = {} -class UserObjectRole(DomainObject): +class UserObjectRole(domain_object.DomainObject): name = None protected_object = None @@ -439,7 +440,7 @@ def setup_default_user_roles(domain_object, admins=[]): admins) def clear_user_roles(domain_object): - assert isinstance(domain_object, DomainObject) + assert isinstance(domain_object, domain_object.DomainObject) if isinstance(domain_object, Package): q = Session.query(PackageRole).filter_by(package=domain_object) elif isinstance(domain_object, Group): diff --git a/ckan/model/core.py b/ckan/model/core.py index 824a56fc8c9..d5af4d3d758 100644 --- a/ckan/model/core.py +++ b/ckan/model/core.py @@ -1,14 +1,15 @@ +import datetime from meta import metadata, mapper from sqlalchemy import Column, DateTime, Text, Boolean import vdm.sqlalchemy -from domain_object import DomainObject +import domain_object ## VDM-specific tables revision_table = vdm.sqlalchemy.make_revision_table(metadata) revision_table.append_column(Column('approved_timestamp', DateTime)) -class System(DomainObject): +class System(domain_object.DomainObject): name = 'system' @@ -29,7 +30,6 @@ def by_name(cls, name): def make_revisioned_table(table): - import datetime revision_table = vdm.sqlalchemy.make_revisioned_table(table) revision_table.append_column(Column('expired_id', Text)) diff --git a/ckan/model/domain_object.py b/ckan/model/domain_object.py index 590ae514b82..77c9869bde9 100644 --- a/ckan/model/domain_object.py +++ b/ckan/model/domain_object.py @@ -3,7 +3,7 @@ from sqlalchemy import orm from sqlalchemy.util import OrderedDict -from meta import Session +import meta class Enum(set): '''Simple enumeration @@ -24,7 +24,7 @@ def __getattr__(self, name): class DomainObject(object): text_search_fields = [] - Session = Session + Session = meta.Session def __init__(self, **kwargs): for k,v in kwargs.items(): @@ -36,7 +36,7 @@ def count(cls): @classmethod def by_name(cls, name, autoflush=True): - obj = Session.query(cls).autoflush(autoflush)\ + obj = meta.Session.query(cls).autoflush(autoflush)\ .filter_by(name=name).first() return obj @@ -53,7 +53,7 @@ def text_search(cls, query, term): @classmethod def active(cls): from core import State - return Session.query(cls).filter_by(state=State.ACTIVE) + return meta.Session.query(cls).filter_by(state=State.ACTIVE) def save(self): self.add() diff --git a/ckan/model/group_extra.py b/ckan/model/group_extra.py index a11d466342b..73774c40e76 100644 --- a/ckan/model/group_extra.py +++ b/ckan/model/group_extra.py @@ -6,6 +6,7 @@ from package import * from group import * from types import JsonType +import domain_object __all__ = ['GroupExtra', 'group_extra_table', 'GroupExtraRevision'] @@ -23,7 +24,7 @@ class GroupExtra(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): pass mapper(GroupExtra, group_extra_table, properties={ diff --git a/ckan/model/package_extra.py b/ckan/model/package_extra.py index fcdcbda6dad..cf3a3432ef9 100644 --- a/ckan/model/package_extra.py +++ b/ckan/model/package_extra.py @@ -6,6 +6,7 @@ from package import * from types import JsonType from ckan.model import extension +import domain_object __all__ = ['PackageExtra', 'package_extra_table', 'PackageExtraRevision', 'extra_revision_table'] @@ -23,7 +24,7 @@ class PackageExtra(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): def related_packages(self): return [self.package] diff --git a/ckan/model/package_relationship.py b/ckan/model/package_relationship.py index 0a5a20283fe..1683fe3270b 100644 --- a/ckan/model/package_relationship.py +++ b/ckan/model/package_relationship.py @@ -4,6 +4,7 @@ from core import * from package import * from types import make_uuid +import domain_object # i18n only works when this is run as part of pylons, # which isn't the case for paster commands. @@ -28,7 +29,7 @@ def _(txt): class PackageRelationship(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): '''The rule with PackageRelationships is that they are stored in the model always as the "forward" relationship - i.e. "child_of" but never as "parent_of". However, the model functions provide the relationships diff --git a/ckan/model/rating.py b/ckan/model/rating.py index 76da00891f6..56261ebbdb4 100644 --- a/ckan/model/rating.py +++ b/ckan/model/rating.py @@ -5,6 +5,7 @@ from package import * from types import make_uuid from user import User +import domain_object __all__ = ['Rating'] @@ -17,7 +18,7 @@ Column('created', DateTime, default=datetime.datetime.now), ) -class Rating(DomainObject): +class Rating(domain_object.DomainObject): pass mapper(Rating, rating_table, diff --git a/ckan/model/resource.py b/ckan/model/resource.py index 3d0857580c7..937d5adde93 100644 --- a/ckan/model/resource.py +++ b/ckan/model/resource.py @@ -10,6 +10,7 @@ from package import * from ckan.model import extension from ckan.model.activity import ActivityDetail +import domain_object __all__ = ['Resource', 'resource_table', 'ResourceGroup', 'resource_group_table', @@ -66,7 +67,7 @@ class Resource(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): extra_columns = None def __init__(self, resource_group_id=None, url=u'', format=u'', description=u'', hash=u'', @@ -158,7 +159,7 @@ def activity_stream_detail(self, activity_id, activity_type): class ResourceGroup(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): extra_columns = None def __init__(self, package_id=None, sort_order=u'', label=u'', extras=None, **kwargs): diff --git a/ckan/model/task_status.py b/ckan/model/task_status.py index 5f0f5445edf..0feaf1415b8 100644 --- a/ckan/model/task_status.py +++ b/ckan/model/task_status.py @@ -3,6 +3,7 @@ from core import * from types import make_uuid from datetime import datetime +import domain_object __all__ = ['TaskStatus', 'task_status_table'] @@ -19,7 +20,7 @@ sa.UniqueConstraint('entity_id', 'task_type', 'key') ) -class TaskStatus(DomainObject): +class TaskStatus(domain_object.DomainObject): @classmethod def get(cls, reference): '''Returns a task status object referenced by its id.''' diff --git a/ckan/model/types.py b/ckan/model/types.py index bd5e5948d52..54873e6f376 100644 --- a/ckan/model/types.py +++ b/ckan/model/types.py @@ -1,16 +1,16 @@ +## IMPORTS FIXED import datetime import copy +import uuid from sqlalchemy import types -from pylons import config - -from ckan.model import meta +import meta +import ckan.lib.helpers as h def make_uuid(): return unicode(uuid.uuid4()) -import uuid class UuidType(types.TypeDecorator): impl = types.Unicode @@ -30,7 +30,6 @@ def default(cls): return unicode(uuid.uuid4()) -from ckan.lib.helpers import json class JsonType(types.TypeDecorator): '''Store data as JSON serializing on save and unserializing on use. @@ -45,17 +44,17 @@ def process_bind_param(self, value, engine): return None else: # ensure_ascii=False => allow unicode but still need to convert - return unicode(json.dumps(value, ensure_ascii=False)) + return unicode(h.json.dumps(value, ensure_ascii=False)) def process_result_value(self, value, engine): if value is None: return {} else: - return json.loads(value) + return h.json.loads(value) def copy(self): return JsonType(self.impl.length) - + def is_mutable(self): return True @@ -73,7 +72,7 @@ def process_bind_param(self, value, engine): if isinstance(value, basestring): return unicode(value) else: - return unicode(json.dumps(value, ensure_ascii=False)) + return unicode(h.json.dumps(value, ensure_ascii=False)) def copy(self): return JsonDictType(self.impl.length) diff --git a/ckan/model/user.py b/ckan/model/user.py index 780cb94ef00..3768ed9cfd1 100644 --- a/ckan/model/user.py +++ b/ckan/model/user.py @@ -6,8 +6,8 @@ from sqlalchemy.orm import synonym from meta import * -from core import DomainObject from types import make_uuid +import domain_object user_table = Table('user', metadata, Column('id', UnicodeText, primary_key=True, default=make_uuid), @@ -22,7 +22,7 @@ Column('about', UnicodeText), ) -class User(DomainObject): +class User(domain_object.DomainObject): VALID_NAME = re.compile(r"^[a-zA-Z0-9_\-]{3,255}$") DOUBLE_SLASH = re.compile(':\/([^/])') diff --git a/ckan/model/vocabulary.py b/ckan/model/vocabulary.py index 8501629c144..98c736933ac 100644 --- a/ckan/model/vocabulary.py +++ b/ckan/model/vocabulary.py @@ -1,7 +1,8 @@ from meta import Table, types, Session -from core import metadata, Column, DomainObject, mapper +from core import metadata, Column, mapper from types import make_uuid import tag +import domain_object VOCABULARY_NAME_MIN_LENGTH = 2 VOCABULARY_NAME_MAX_LENGTH = 100 @@ -13,7 +14,7 @@ unique=True), ) -class Vocabulary(DomainObject): +class Vocabulary(domain_object.DomainObject): def __init__(self, name): self.id = make_uuid() From 62113e17419a7007912d37496761a1c68d40631c Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 28 Mar 2012 18:20:49 +0100 Subject: [PATCH 002/109] more model import cleans vocab and core --- ckan/model/core.py | 23 ++++++++++++----------- ckan/model/vocabulary.py | 26 ++++++++++++++------------ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/ckan/model/core.py b/ckan/model/core.py index d5af4d3d758..a0ece1ae088 100644 --- a/ckan/model/core.py +++ b/ckan/model/core.py @@ -1,40 +1,41 @@ import datetime -from meta import metadata, mapper + from sqlalchemy import Column, DateTime, Text, Boolean import vdm.sqlalchemy +import meta import domain_object ## VDM-specific tables -revision_table = vdm.sqlalchemy.make_revision_table(metadata) +revision_table = vdm.sqlalchemy.make_revision_table(meta.metadata) revision_table.append_column(Column('approved_timestamp', DateTime)) class System(domain_object.DomainObject): - + name = 'system' - + def __unicode__(self): return u'<%s>' % self.__class__.__name__ - + def purge(self): pass - + @classmethod - def by_name(cls, name): - return System() + def by_name(cls, name): + return System() # VDM-specific domain objects State = vdm.sqlalchemy.State State.all = [ State.ACTIVE, State.DELETED ] -Revision = vdm.sqlalchemy.make_Revision(mapper, revision_table) +Revision = vdm.sqlalchemy.make_Revision(meta.mapper, revision_table) def make_revisioned_table(table): revision_table = vdm.sqlalchemy.make_revisioned_table(table) - revision_table.append_column(Column('expired_id', + revision_table.append_column(Column('expired_id', Text)) revision_table.append_column(Column('revision_timestamp', DateTime)) - revision_table.append_column(Column('expired_timestamp', DateTime, + revision_table.append_column(Column('expired_timestamp', DateTime, default=datetime.datetime(9999, 12, 31))) revision_table.append_column(Column('current', Boolean)) return revision_table diff --git a/ckan/model/vocabulary.py b/ckan/model/vocabulary.py index 98c736933ac..c853fd638e2 100644 --- a/ckan/model/vocabulary.py +++ b/ckan/model/vocabulary.py @@ -1,32 +1,34 @@ -from meta import Table, types, Session -from core import metadata, Column, mapper -from types import make_uuid +## IMPORTS FIXED +import sqlalchemy as sa + +import meta +import types import tag import domain_object VOCABULARY_NAME_MIN_LENGTH = 2 VOCABULARY_NAME_MAX_LENGTH = 100 -vocabulary_table = Table( - 'vocabulary', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), - Column('name', types.Unicode(VOCABULARY_NAME_MAX_LENGTH), nullable=False, +vocabulary_table = meta.Table( + 'vocabulary', meta.metadata, + sa.Column('id', sa.types.UnicodeText, primary_key=True, default=types.make_uuid), + sa.Column('name', sa.types.Unicode(VOCABULARY_NAME_MAX_LENGTH), nullable=False, unique=True), ) class Vocabulary(domain_object.DomainObject): def __init__(self, name): - self.id = make_uuid() + self.id = types.make_uuid() self.name = name @classmethod def get(cls, id_or_name): """Return a Vocabulary object referenced by its id or name, or None if there is no vocabulary with the given id or name. - + """ - query = Session.query(Vocabulary).filter(Vocabulary.id==id_or_name) + query = meta.Session.query(Vocabulary).filter(Vocabulary.id==id_or_name) vocab = query.first() if vocab is None: vocab = Vocabulary.by_name(id_or_name) @@ -34,6 +36,6 @@ def get(cls, id_or_name): @property def tags(self): - return Session.query(tag.Tag).filter(tag.Tag.vocabulary_id==self.id) + return meta.Session.query(tag.Tag).filter(tag.Tag.vocabulary_id==self.id) -mapper(Vocabulary, vocabulary_table) +meta.mapper(Vocabulary, vocabulary_table) From 92bb334ff7e4b175cd2e823fb512b7c80bff2aa0 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 10:32:08 +0100 Subject: [PATCH 003/109] more import cleanups --- ckan/model/authz.py | 42 ++++++++++++++++++------------------- ckan/model/domain_object.py | 3 ++- ckan/model/user.py | 9 ++++---- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/ckan/model/authz.py b/ckan/model/authz.py index b7c627c588b..84e5e51d27b 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -342,18 +342,18 @@ def init_authz_const_data(): Session.remove() ## TODO: this should be in ckan/authz.py -def setup_user_roles(domain_object, visitor_roles, logged_in_roles, admins=[]): +def setup_user_roles(_domain_object, visitor_roles, logged_in_roles, admins=[]): '''NB: leaves caller to commit change''' assert type(admins) == type([]) admin_roles = [Role.ADMIN] visitor = User.by_name(PSEUDO_USER__VISITOR) assert visitor for role in visitor_roles: - add_user_to_role(visitor, role, domain_object) + add_user_to_role(visitor, role, _domain_object) logged_in = User.by_name(PSEUDO_USER__LOGGED_IN) assert logged_in for role in logged_in_roles: - add_user_to_role(logged_in, role, domain_object) + add_user_to_role(logged_in, role, _domain_object) for admin in admins: # not sure if admin would reasonably by None if admin is not None: @@ -361,7 +361,7 @@ def setup_user_roles(domain_object, visitor_roles, logged_in_roles, admins=[]): if admin.name in (PSEUDO_USER__LOGGED_IN, PSEUDO_USER__VISITOR): raise NotRealUserException('Invalid user for domain object admin %r' % admin.name) for role in admin_roles: - add_user_to_role(admin, role, domain_object) + add_user_to_role(admin, role, _domain_object) def give_all_packages_default_user_roles(): # if this command gives an exception, you probably @@ -401,11 +401,11 @@ def give_all_packages_default_user_roles(): global _default_user_roles_cache _default_user_roles_cache = {} -def get_default_user_roles(domain_object): +def get_default_user_roles(_domain_object): # TODO: Should this func go in lib rather than model now? from ckan.lib.helpers import json from pylons import config - def _get_default_user_roles(domain_object): + def _get_default_user_roles(_domain_object): config_key = 'ckan.default_roles.%s' % obj_type user_roles_json = config.get(config_key) if user_roles_json is None: @@ -414,37 +414,37 @@ def _get_default_user_roles(domain_object): user_roles_str = json.loads(user_roles_json) if user_roles_json else {} unknown_keys = set(user_roles_str.keys()) - set(('visitor', 'logged_in')) assert not unknown_keys, 'Auth config for %r has unknown key %r' % \ - (domain_object, unknown_keys) + (_domain_object, unknown_keys) user_roles_ = {} for user in ('visitor', 'logged_in'): roles_str = user_roles_str.get(user, []) user_roles_[user] = [getattr(Role, role_str.upper()) for role_str in roles_str] return user_roles_ - obj_type = domain_object.__class__.__name__ + obj_type = _domain_object.__class__.__name__ global _default_user_roles_cache - if not _default_user_roles_cache.has_key(domain_object): - _default_user_roles_cache[domain_object] = _get_default_user_roles(domain_object) - return _default_user_roles_cache[domain_object] + if not _default_user_roles_cache.has_key(_domain_object): + _default_user_roles_cache[_domain_object] = _get_default_user_roles(_domain_object) + return _default_user_roles_cache[_domain_object] -def setup_default_user_roles(domain_object, admins=[]): +def setup_default_user_roles(_domain_object, admins=[]): ''' sets up roles for visitor, logged-in user and any admins provided @param admins - a list of User objects NB: leaves caller to commit change. ''' - assert isinstance(domain_object, (Package, Group, System, AuthorizationGroup)), domain_object + assert isinstance(_domain_object, (Package, Group, System, AuthorizationGroup)), _domain_object assert isinstance(admins, list) - user_roles_ = get_default_user_roles(domain_object) - setup_user_roles(domain_object, + user_roles_ = get_default_user_roles(_domain_object) + setup_user_roles(_domain_object, user_roles_['visitor'], user_roles_['logged_in'], admins) -def clear_user_roles(domain_object): - assert isinstance(domain_object, domain_object.DomainObject) - if isinstance(domain_object, Package): - q = Session.query(PackageRole).filter_by(package=domain_object) - elif isinstance(domain_object, Group): - q = Session.query(GroupRole).filter_by(group=domain_object) +def clear_user_roles(_domain_object): + assert isinstance(_domain_object, domain_object.DomainObject) + if isinstance(_domain_object, Package): + q = Session.query(PackageRole).filter_by(package=_domain_object) + elif isinstance(_domain_object, Group): + q = Session.query(GroupRole).filter_by(group=_domain_object) else: raise NotImplementedError() user_roles = q.all() diff --git a/ckan/model/domain_object.py b/ckan/model/domain_object.py index 77c9869bde9..76871a0ca7b 100644 --- a/ckan/model/domain_object.py +++ b/ckan/model/domain_object.py @@ -1,5 +1,6 @@ import datetime +import sqlalchemy as sa from sqlalchemy import orm from sqlalchemy.util import OrderedDict @@ -47,7 +48,7 @@ def text_search(cls, query, term): q = None for field in cls.text_search_fields: attr = getattr(register, field) - q = or_(q, make_like(attr, term)) + q = sa.or_(q, make_like(attr, term)) return query.filter(q) @classmethod diff --git a/ckan/model/user.py b/ckan/model/user.py index 3768ed9cfd1..50c91456ba9 100644 --- a/ckan/model/user.py +++ b/ckan/model/user.py @@ -2,21 +2,22 @@ import re import os from hashlib import sha1 + from sqlalchemy.sql.expression import or_ from sqlalchemy.orm import synonym from meta import * -from types import make_uuid +import types as _types import domain_object user_table = Table('user', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', UnicodeText, nullable=False, unique=True), Column('openid', UnicodeText), Column('password', UnicodeText), Column('fullname', UnicodeText), Column('email', UnicodeText), - Column('apikey', UnicodeText, default=make_uuid), + Column('apikey', UnicodeText, default=_types.make_uuid), Column('created', DateTime, default=datetime.datetime.now), Column('reset_key', UnicodeText), Column('about', UnicodeText), @@ -128,7 +129,7 @@ def check_name_available(cls, name): return cls.by_name(name) == None def as_dict(self): - _dict = DomainObject.as_dict(self) + _dict = domain_object.DomainObject.as_dict(self) del _dict['password'] return _dict From 5c063b1f43314e3fc5be24e81bf7b06ed5f1f89e Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 10:50:12 +0100 Subject: [PATCH 004/109] some more import cleaning --- ckan/model/activity.py | 13 ++++++------- ckan/model/authorization_group.py | 10 +++++----- ckan/model/authz.py | 16 ++++++++-------- ckan/model/group_extra.py | 7 +++---- ckan/model/package_relationship.py | 4 ++-- ckan/model/rating.py | 8 ++++---- ckan/model/resource.py | 12 ++++++------ ckan/model/task_status.py | 7 ++++--- 8 files changed, 38 insertions(+), 39 deletions(-) diff --git a/ckan/model/activity.py b/ckan/model/activity.py index 82b77019e63..252560f4b67 100644 --- a/ckan/model/activity.py +++ b/ckan/model/activity.py @@ -3,10 +3,9 @@ from sqlalchemy import orm from meta import * -from types import make_uuid -from types import JsonDictType from core import * from package import * +import types as _types __all__ = ['Activity', 'activity_table', 'ActivityDetail', 'activity_detail_table', @@ -14,30 +13,30 @@ activity_table = Table( 'activity', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('timestamp', types.DateTime), Column('user_id', types.UnicodeText), Column('object_id', types.UnicodeText), Column('revision_id', types.UnicodeText), Column('activity_type', types.UnicodeText), - Column('data', JsonDictType), + Column('data', _types.JsonDictType), ) activity_detail_table = Table( 'activity_detail', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('activity_id', types.UnicodeText, ForeignKey('activity.id')), Column('object_id', types.UnicodeText), Column('object_type', types.UnicodeText), Column('activity_type', types.UnicodeText), - Column('data', JsonDictType), + Column('data', _types.JsonDictType), ) class Activity(DomainObject): def __init__(self, user_id, object_id, revision_id, activity_type, data=None): - self.id = make_uuid() + self.id = _types.make_uuid() self.timestamp = datetime.datetime.now() self.user_id = user_id self.object_id = object_id diff --git a/ckan/model/authorization_group.py b/ckan/model/authorization_group.py index d00241b5c55..6692e3cc36a 100644 --- a/ckan/model/authorization_group.py +++ b/ckan/model/authorization_group.py @@ -1,18 +1,18 @@ import datetime from meta import * -from user import User, user_table -from types import make_uuid +import user +import types as _types import domain_object authorization_group_table = Table('authorization_group', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', UnicodeText), Column('created', DateTime, default=datetime.datetime.now), ) authorization_group_user_table = Table('authorization_group_user', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('authorization_group_id', UnicodeText, ForeignKey('authorization_group.id'), nullable=False), Column('user_id', UnicodeText, ForeignKey('user.id'), nullable=False) @@ -72,7 +72,7 @@ def remove_user_from_authorization_group(user, authorization_group): mapper(AuthorizationGroup, authorization_group_table, properties={ - 'users': relation(User, lazy=True, secondary=authorization_group_user_table, + 'users': relation(user.User, lazy=True, secondary=authorization_group_user_table, backref=backref('authorization_groups', lazy=True)) }, order_by=authorization_group_table.c.name) diff --git a/ckan/model/authz.py b/ckan/model/authz.py index 84e5e51d27b..d52aace2efc 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -9,7 +9,7 @@ from types import make_uuid from user import User from core import System -from authorization_group import AuthorizationGroup, authorization_group_table +import authorization_group as auth_group import domain_object PSEUDO_USER__LOGGED_IN = u'logged_in' @@ -163,7 +163,7 @@ def user_has_role(cls, user, role, domain_obj): @classmethod def authorization_group_has_role(cls, authorized_group, role, domain_obj): - assert isinstance(authorized_group, AuthorizationGroup), authorized_group + assert isinstance(authorized_group, auth_group.AuthorizationGroup), authorized_group q = cls._authorized_group_query(authorized_group, role, domain_obj) return q.count() == 1 @@ -268,7 +268,7 @@ def __repr__(self): protected_objects[GroupRole.protected_object] = GroupRole class AuthorizationGroupRole(UserObjectRole): - protected_object = AuthorizationGroup + protected_object = auth_group.AuthorizationGroup name = 'authorization_group' def __repr__(self): @@ -431,7 +431,7 @@ def setup_default_user_roles(_domain_object, admins=[]): @param admins - a list of User objects NB: leaves caller to commit change. ''' - assert isinstance(_domain_object, (Package, Group, System, AuthorizationGroup)), _domain_object + assert isinstance(_domain_object, (Package, Group, System, auth_group.AuthorizationGroup)), _domain_object assert isinstance(admins, list) user_roles_ = get_default_user_roles(_domain_object) setup_user_roles(_domain_object, @@ -466,7 +466,7 @@ def clear_user_roles(_domain_object): cascade='all, delete, delete-orphan' ) ), - 'authorized_group': orm.relation(AuthorizationGroup, + 'authorized_group': orm.relation(auth_group.AuthorizationGroup, backref=orm.backref('authorized_roles', cascade='all, delete, delete-orphan' ) @@ -500,11 +500,11 @@ def clear_user_roles(_domain_object): ) mapper(AuthorizationGroupRole, authorization_group_role_table, inherits=UserObjectRole, - polymorphic_identity=unicode(AuthorizationGroup.__name__), + polymorphic_identity=unicode(auth_group.AuthorizationGroup.__name__), properties={ - 'authorization_group': orm.relation(AuthorizationGroup, + 'authorization_group': orm.relation(auth_group.AuthorizationGroup, backref=orm.backref('roles', - primaryjoin=authorization_group_table.c.id==authorization_group_role_table.c.authorization_group_id, + primaryjoin=auth_group.authorization_group_table.c.id==authorization_group_role_table.c.authorization_group_id, cascade='all, delete, delete-orphan' ), ) diff --git a/ckan/model/group_extra.py b/ckan/model/group_extra.py index 73774c40e76..33b54dcec3a 100644 --- a/ckan/model/group_extra.py +++ b/ckan/model/group_extra.py @@ -1,21 +1,20 @@ from meta import * -from types import make_uuid import vdm.sqlalchemy from core import * from package import * from group import * -from types import JsonType +import types as _types import domain_object __all__ = ['GroupExtra', 'group_extra_table', 'GroupExtraRevision'] group_extra_table = Table('group_extra', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('group_id', UnicodeText, ForeignKey('group.id')), Column('key', UnicodeText), - Column('value', JsonType), + Column('value', _types.JsonType), ) vdm.sqlalchemy.make_table_stateful(group_extra_table) diff --git a/ckan/model/package_relationship.py b/ckan/model/package_relationship.py index 1683fe3270b..e7a024dbaa3 100644 --- a/ckan/model/package_relationship.py +++ b/ckan/model/package_relationship.py @@ -3,7 +3,7 @@ from meta import * from core import * from package import * -from types import make_uuid +import types as _types import domain_object # i18n only works when this is run as part of pylons, @@ -17,7 +17,7 @@ def _(txt): package_relationship_table = Table('package_relationship', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('subject_package_id', UnicodeText, ForeignKey('package.id')), Column('object_package_id', UnicodeText, ForeignKey('package.id')), Column('type', UnicodeText), diff --git a/ckan/model/rating.py b/ckan/model/rating.py index 56261ebbdb4..44fb027d712 100644 --- a/ckan/model/rating.py +++ b/ckan/model/rating.py @@ -3,14 +3,14 @@ from meta import * from core import * from package import * -from types import make_uuid -from user import User +import user import domain_object +import types as _types __all__ = ['Rating'] rating_table = Table('rating', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('user_id', UnicodeText, ForeignKey('user.id')), Column('user_ip_address', UnicodeText), # alternative to user_id if not logged in Column('package_id', UnicodeText, ForeignKey('package.id')), @@ -23,7 +23,7 @@ class Rating(domain_object.DomainObject): mapper(Rating, rating_table, properties={ - 'user': orm.relation(User, + 'user': orm.relation(user.User, backref=orm.backref('ratings', cascade='all, delete, delete-orphan' )), diff --git a/ckan/model/resource.py b/ckan/model/resource.py index 937d5adde93..3abbf5bff0b 100644 --- a/ckan/model/resource.py +++ b/ckan/model/resource.py @@ -5,7 +5,7 @@ import vdm.sqlalchemy from meta import * -from types import make_uuid, JsonDictType +import types as _types from core import * from package import * from ckan.model import extension @@ -28,7 +28,7 @@ ##formally package_resource resource_table = Table( 'resource', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('resource_group_id', types.UnicodeText, ForeignKey('resource_group.id')), Column('url', types.UnicodeText, nullable=False), Column('format', types.UnicodeText), @@ -47,16 +47,16 @@ Column('webstore_url', types.UnicodeText), Column('webstore_last_updated', types.DateTime), - Column('extras', JsonDictType), + Column('extras', _types.JsonDictType), ) resource_group_table = Table( 'resource_group', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('package_id', types.UnicodeText, ForeignKey('package.id')), Column('label', types.UnicodeText), Column('sort_order', types.UnicodeText), - Column('extras', JsonDictType), + Column('extras', _types.JsonDictType), ) vdm.sqlalchemy.make_table_stateful(resource_table) @@ -73,7 +73,7 @@ def __init__(self, resource_group_id=None, url=u'', format=u'', description=u'', hash=u'', extras=None, **kwargs): - self.id = make_uuid() + self.id = _types.make_uuid() if resource_group_id: self.resource_group_id = resource_group_id self.url = url diff --git a/ckan/model/task_status.py b/ckan/model/task_status.py index 0feaf1415b8..1fbc410226b 100644 --- a/ckan/model/task_status.py +++ b/ckan/model/task_status.py @@ -1,14 +1,15 @@ import sqlalchemy as sa from meta import * from core import * -from types import make_uuid -from datetime import datetime +import types as _types import domain_object +# se overwrite datetime somewhere in our importing +from datetime import datetime __all__ = ['TaskStatus', 'task_status_table'] task_status_table = Table('task_status', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('entity_id', UnicodeText, nullable=False), Column('entity_type', UnicodeText, nullable=False), Column('task_type', UnicodeText, nullable=False), From d9d6a71a2e588ecb38742434cf9a87d67e5af734 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 11:22:33 +0100 Subject: [PATCH 005/109] further import cleans for models --- ckan/model/activity.py | 5 +++-- ckan/model/authz.py | 32 ++++++++++++++++---------------- ckan/model/group.py | 14 +++++++------- ckan/model/package.py | 12 ++++++------ ckan/model/package_extra.py | 7 +++---- ckan/model/tag.py | 12 ++++++------ ckan/model/term_translation.py | 3 --- 7 files changed, 41 insertions(+), 44 deletions(-) diff --git a/ckan/model/activity.py b/ckan/model/activity.py index 252560f4b67..e31e355c11d 100644 --- a/ckan/model/activity.py +++ b/ckan/model/activity.py @@ -6,6 +6,7 @@ from core import * from package import * import types as _types +import domain_object __all__ = ['Activity', 'activity_table', 'ActivityDetail', 'activity_detail_table', @@ -32,7 +33,7 @@ Column('data', _types.JsonDictType), ) -class Activity(DomainObject): +class Activity(domain_object.DomainObject): def __init__(self, user_id, object_id, revision_id, activity_type, data=None): @@ -49,7 +50,7 @@ def __init__(self, user_id, object_id, revision_id, activity_type, mapper(Activity, activity_table) -class ActivityDetail(DomainObject): +class ActivityDetail(domain_object.DomainObject): def __init__(self, activity_id, object_id, object_type, activity_type, data=None): diff --git a/ckan/model/authz.py b/ckan/model/authz.py index d52aace2efc..f39aa0e99ba 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -5,12 +5,12 @@ from meta import * from core import * from package import * -from group import Group -from types import make_uuid -from user import User +import group +import user as _user from core import System import authorization_group as auth_group import domain_object +import types as _types PSEUDO_USER__LOGGED_IN = u'logged_in' PSEUDO_USER__VISITOR = u'visitor' @@ -88,14 +88,14 @@ class Role(Enum): ## Table Definitions role_action_table = Table('role_action', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('role', UnicodeText), Column('context', UnicodeText, nullable=False), Column('action', UnicodeText), ) user_object_role_table = Table('user_object_role', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('user_id', UnicodeText, ForeignKey('user.id'), nullable=True), Column('authorized_group_id', UnicodeText, ForeignKey('authorization_group.id'), nullable=True), Column('context', UnicodeText, nullable=False), # stores subtype @@ -157,7 +157,7 @@ def get_object_role_class(cls, domain_obj): @classmethod def user_has_role(cls, user, role, domain_obj): - assert isinstance(user, User), user + assert isinstance(user, _user.User), user q = cls._user_query(user, role, domain_obj) return q.count() == 1 @@ -252,7 +252,7 @@ def __repr__(self): protected_objects[PackageRole.protected_object] = PackageRole class GroupRole(UserObjectRole): - protected_object = Group + protected_object = group.Group name = 'group' def __repr__(self): @@ -346,18 +346,18 @@ def setup_user_roles(_domain_object, visitor_roles, logged_in_roles, admins=[]): '''NB: leaves caller to commit change''' assert type(admins) == type([]) admin_roles = [Role.ADMIN] - visitor = User.by_name(PSEUDO_USER__VISITOR) + visitor = _user.User.by_name(PSEUDO_USER__VISITOR) assert visitor for role in visitor_roles: add_user_to_role(visitor, role, _domain_object) - logged_in = User.by_name(PSEUDO_USER__LOGGED_IN) + logged_in = _user.User.by_name(PSEUDO_USER__LOGGED_IN) assert logged_in for role in logged_in_roles: add_user_to_role(logged_in, role, _domain_object) for admin in admins: # not sure if admin would reasonably by None if admin is not None: - assert isinstance(admin, User), admin + assert isinstance(admin, _user.User), admin if admin.name in (PSEUDO_USER__LOGGED_IN, PSEUDO_USER__VISITOR): raise NotRealUserException('Invalid user for domain object admin %r' % admin.name) for role in admin_roles: @@ -381,7 +381,7 @@ def give_all_packages_default_user_roles(): for rev in revs: if rev.revision.author: # rev author is not Unicode!! - user = User.by_name(unicode(rev.revision.author)) + user = _user.User.by_name(unicode(rev.revision.author)) if user: admins.append(user) # remove duplicates @@ -431,7 +431,7 @@ def setup_default_user_roles(_domain_object, admins=[]): @param admins - a list of User objects NB: leaves caller to commit change. ''' - assert isinstance(_domain_object, (Package, Group, System, auth_group.AuthorizationGroup)), _domain_object + assert isinstance(_domain_object, (Package, group.Group, System, auth_group.AuthorizationGroup)), _domain_object assert isinstance(admins, list) user_roles_ = get_default_user_roles(_domain_object) setup_user_roles(_domain_object, @@ -443,7 +443,7 @@ def clear_user_roles(_domain_object): assert isinstance(_domain_object, domain_object.DomainObject) if isinstance(_domain_object, Package): q = Session.query(PackageRole).filter_by(package=_domain_object) - elif isinstance(_domain_object, Group): + elif isinstance(_domain_object, group.Group): q = Session.query(GroupRole).filter_by(group=_domain_object) else: raise NotImplementedError() @@ -461,7 +461,7 @@ def clear_user_roles(_domain_object): polymorphic_on=user_object_role_table.c.context, polymorphic_identity=u'user_object', properties={ - 'user': orm.relation(User, + 'user': orm.relation(_user.User, backref=orm.backref('roles', cascade='all, delete, delete-orphan' ) @@ -488,9 +488,9 @@ def clear_user_roles(_domain_object): ) mapper(GroupRole, group_role_table, inherits=UserObjectRole, - polymorphic_identity=unicode(Group.__name__), + polymorphic_identity=unicode(group.Group.__name__), properties={ - 'group': orm.relation(Group, + 'group': orm.relation(group.Group, backref=orm.backref('roles', cascade='all, delete, delete-orphan' ), diff --git a/ckan/model/group.py b/ckan/model/group.py index 70925563811..d935c8cc412 100644 --- a/ckan/model/group.py +++ b/ckan/model/group.py @@ -3,9 +3,9 @@ from meta import * from core import * from sqlalchemy.orm import eagerload_all -from domain_object import DomainObject from package import * -from types import make_uuid +import types as _types +import domain_object import vdm.sqlalchemy from ckan.model import extension, User from sqlalchemy.ext.associationproxy import association_proxy @@ -15,7 +15,7 @@ 'member_revision_table', 'member_table'] member_table = Table('member', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('table_name', UnicodeText, nullable=False), Column('table_id', UnicodeText, nullable=False), Column('capacity', UnicodeText, nullable=False), @@ -26,7 +26,7 @@ member_revision_table = make_revisioned_table(member_table) group_table = Table('group', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', UnicodeText, nullable=False, unique=True), Column('title', UnicodeText), Column('type', UnicodeText, nullable=False), @@ -41,7 +41,7 @@ class Member(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): def __init__(self, group=None, table_id=None, group_id=None, table_name=None, capacity='member', state='active'): self.group = group @@ -76,7 +76,7 @@ def related_packages(self): class Group(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): def __init__(self, name=u'', title=u'', description=u'', type=u'group', approval_status=u'approved' ): @@ -183,7 +183,7 @@ def search_by_name(cls, text_query, group_type=None): return q.order_by(cls.title) def as_dict(self, ref_package_by='name'): - _dict = DomainObject.as_dict(self) + _dict = domain_object.DomainObject.as_dict(self) _dict['packages'] = [getattr(package, ref_package_by) for package in self.packages] _dict['extras'] = dict([(key, value) for key, value in self.extras.items()]) if ( self.type == 'publisher' ): diff --git a/ckan/model/package.py b/ckan/model/package.py index 26f8022a9aa..17d869df3c8 100644 --- a/ckan/model/package.py +++ b/ckan/model/package.py @@ -12,10 +12,10 @@ from meta import metadata, Session import vdm.sqlalchemy -from types import make_uuid, iso_date_to_datetime_for_sqlite from core import make_revisioned_table, Revision, State from license import License, LicenseRegister -from domain_object import DomainObject +import types as _types +import domain_object import ckan.misc from activity import Activity, ActivityDetail @@ -29,7 +29,7 @@ ## Our Domain Object Tables package_table = Table('package', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', types.Unicode(PACKAGE_NAME_MAX_LENGTH), nullable=False, unique=True), Column('title', types.UnicodeText), @@ -53,7 +53,7 @@ class Package(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): text_search_fields = ['name', 'title'] @@ -248,7 +248,7 @@ def get_average_rating(self): return total / len(self.ratings) def as_dict(self, ref_package_by='name', ref_group_by='name'): - _dict = DomainObject.as_dict(self) + _dict = domain_object.DomainObject.as_dict(self) # Set 'license' in _dict to cater for old clients. # Todo: Remove from Version 2? _dict['license'] = self.license.title if self.license else _dict.get('license_id', '') @@ -554,7 +554,7 @@ def metadata_modified(self): result = conn.execute(query).fetchone() if result: - result_datetime = iso_date_to_datetime_for_sqlite(result[0]) + result_datetime = _types.iso_date_to_datetime_for_sqlite(result[0]) timestamp_without_usecs = result_datetime.utctimetuple() usecs = float(result_datetime.microsecond) / 1e6 # use timegm instead of mktime, because we don't want it localised diff --git a/ckan/model/package_extra.py b/ckan/model/package_extra.py index cf3a3432ef9..7b37a0ce3cb 100644 --- a/ckan/model/package_extra.py +++ b/ckan/model/package_extra.py @@ -1,22 +1,21 @@ from meta import * -from types import make_uuid import vdm.sqlalchemy from core import * from package import * -from types import JsonType from ckan.model import extension import domain_object +import types as _types __all__ = ['PackageExtra', 'package_extra_table', 'PackageExtraRevision', 'extra_revision_table'] package_extra_table = Table('package_extra', metadata, - Column('id', UnicodeText, primary_key=True, default=make_uuid), + Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), # NB: only (package, key) pair is unique Column('package_id', UnicodeText, ForeignKey('package.id')), Column('key', UnicodeText), - Column('value', JsonType), + Column('value', _types.JsonType), ) vdm.sqlalchemy.make_table_stateful(package_extra_table) diff --git a/ckan/model/tag.py b/ckan/model/tag.py index f3fd0f6f148..71d7d5ea0ad 100644 --- a/ckan/model/tag.py +++ b/ckan/model/tag.py @@ -1,11 +1,11 @@ import sqlalchemy import vdm.sqlalchemy -from types import make_uuid from meta import * -from domain_object import DomainObject from package import Package from core import * +import types as _types +import domain_object import vocabulary import activity import ckan @@ -18,7 +18,7 @@ MIN_TAG_LENGTH = 2 tag_table = Table('tag', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', types.Unicode(MAX_TAG_LENGTH), nullable=False), Column('vocabulary_id', types.Unicode(vocabulary.VOCABULARY_NAME_MAX_LENGTH), @@ -27,7 +27,7 @@ ) package_tag_table = Table('package_tag', metadata, - Column('id', types.UnicodeText, primary_key=True, default=make_uuid), + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('package_id', types.UnicodeText, ForeignKey('package.id')), Column('tag_id', types.UnicodeText, ForeignKey('tag.id')), ) @@ -36,7 +36,7 @@ # TODO: this has a composite primary key ... package_tag_revision_table = make_revisioned_table(package_tag_table) -class Tag(DomainObject): +class Tag(domain_object.DomainObject): def __init__(self, name='', vocabulary_id=None): self.name = name self.vocabulary_id = vocabulary_id @@ -186,7 +186,7 @@ def __repr__(self): class PackageTag(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, - DomainObject): + domain_object.DomainObject): def __init__(self, package=None, tag=None, state=None, **kwargs): self.package = package self.tag = tag diff --git a/ckan/model/term_translation.py b/ckan/model/term_translation.py index 394754cceed..822ee74c324 100644 --- a/ckan/model/term_translation.py +++ b/ckan/model/term_translation.py @@ -1,8 +1,5 @@ -import sqlalchemy as sa from meta import * from core import * -from types import make_uuid -from datetime import datetime __all__ = ['term_translation_table'] From cb4c4c2c87565ca6db2b66e293118a746971277f Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 12:58:50 +0100 Subject: [PATCH 006/109] another bunch of import cleans for models --- ckan/lib/search/__init__.py | 15 ++++---- ckan/model/__init__.py | 2 +- ckan/model/domain_object.py | 10 +++--- ckan/model/tag.py | 64 ++++++++++++++++++---------------- ckan/model/term_translation.py | 7 ++-- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/ckan/lib/search/__init__.py b/ckan/lib/search/__init__.py index 9072b55edb8..1ed19a2e739 100644 --- a/ckan/lib/search/__init__.py +++ b/ckan/lib/search/__init__.py @@ -2,10 +2,9 @@ from pylons import config, c from ckan import model -from ckan.model import DomainObjectOperation from ckan.plugins import SingletonPlugin, implements, IDomainObjectModification from ckan.logic import get_action -import ckan.model.domain_object +import ckan.model.domain_object as domain_object from common import (SearchIndexError, SearchError, SearchQueryError, make_connection, is_available, SolrSettings) @@ -59,7 +58,7 @@ def text_traceback(): _QUERIES['package'] = sql.PackageSearchQuery def _normalize_type(_type): - if isinstance(_type, ckan.model.domain_object.DomainObject): + if isinstance(_type, domain_object.DomainObject): _type = _type.__class__ if isinstance(_type, type): _type = _type.__name__ @@ -86,11 +85,11 @@ def dispatch_by_operation(entity_type, entity, operation): """Call the appropriate index method for a given notification.""" try: index = index_for(entity_type) - if operation == DomainObjectOperation.new: + if operation == domain_object.DomainObjectOperation.new: index.insert_dict(entity) - elif operation == DomainObjectOperation.changed: + elif operation == domain_object.DomainObjectOperation.changed: index.update_dict(entity) - elif operation == DomainObjectOperation.deleted: + elif operation == domain_object.DomainObjectOperation.deleted: index.remove_dict(entity) else: log.warn("Unknown operation: %s" % operation) @@ -108,7 +107,7 @@ class SynchronousSearchPlugin(SingletonPlugin): def notify(self, entity, operation): if not isinstance(entity, model.Package): return - if operation != DomainObjectOperation.deleted: + if operation != domain_object.DomainObjectOperation.deleted: dispatch_by_operation( entity.__class__.__name__, get_action('package_show')( @@ -116,7 +115,7 @@ def notify(self, entity, operation): {'id': entity.id}), operation ) - elif operation == DomainObjectOperation.deleted: + elif operation == domain_object.DomainObjectOperation.deleted: dispatch_by_operation(entity.__class__.__name__, {'id': entity.id}, operation) else: diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index 8e191fda3cf..1e14b8d4ca2 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -8,7 +8,7 @@ from paste.deploy.converters import asbool import meta -from domain_object import DomainObjectOperation +#from domain_object import DomainObjectOperation from core import * from package import * from tag import * diff --git a/ckan/model/domain_object.py b/ckan/model/domain_object.py index 76871a0ca7b..890be94710d 100644 --- a/ckan/model/domain_object.py +++ b/ckan/model/domain_object.py @@ -5,6 +5,7 @@ from sqlalchemy.util import OrderedDict import meta +import core class Enum(set): '''Simple enumeration @@ -13,7 +14,7 @@ class Enum(set): ''' def __init__(self, *names): super(Enum, self).__init__(names) - + def __getattr__(self, name): if name in self: return name @@ -23,7 +24,7 @@ def __getattr__(self, name): # TODO: replace this (or at least inherit from) standard SqlalchemyMixin in vdm class DomainObject(object): - + text_search_fields = [] Session = meta.Session @@ -53,8 +54,7 @@ def text_search(cls, query, term): @classmethod def active(cls): - from core import State - return meta.Session.query(cls).filter_by(state=State.ACTIVE) + return meta.Session.query(cls).filter_by(state=core.State.ACTIVE) def save(self): self.add() @@ -108,7 +108,7 @@ def __unicode__(self): repr += u' %s=%s' % (col.name, getattr(self, col.name)) except Exception, inst: repr += u' %s=%s' % (col.name, inst) - + repr += '>' return repr diff --git a/ckan/model/tag.py b/ckan/model/tag.py index 71d7d5ea0ad..96482607529 100644 --- a/ckan/model/tag.py +++ b/ckan/model/tag.py @@ -1,9 +1,11 @@ -import sqlalchemy import vdm.sqlalchemy +from sqlalchemy.orm import relation +from sqlalchemy import types, Column, Table, ForeignKey, and_, UniqueConstraint -from meta import * -from package import Package -from core import * +import package as _package +import extension as _extension +import core +import meta import types as _types import domain_object import vocabulary @@ -17,16 +19,16 @@ MAX_TAG_LENGTH = 100 MIN_TAG_LENGTH = 2 -tag_table = Table('tag', metadata, +tag_table = Table('tag', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', types.Unicode(MAX_TAG_LENGTH), nullable=False), Column('vocabulary_id', types.Unicode(vocabulary.VOCABULARY_NAME_MAX_LENGTH), ForeignKey('vocabulary.id')), - sqlalchemy.UniqueConstraint('name', 'vocabulary_id') + UniqueConstraint('name', 'vocabulary_id') ) -package_tag_table = Table('package_tag', metadata, +package_tag_table = Table('package_tag', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('package_id', types.UnicodeText, ForeignKey('package.id')), Column('tag_id', types.UnicodeText, ForeignKey('tag.id')), @@ -34,7 +36,7 @@ vdm.sqlalchemy.make_table_stateful(package_tag_table) # TODO: this has a composite primary key ... -package_tag_revision_table = make_revisioned_table(package_tag_table) +package_tag_revision_table = core.make_revisioned_table(package_tag_table) class Tag(domain_object.DomainObject): def __init__(self, name='', vocabulary_id=None): @@ -54,7 +56,7 @@ def by_id(cls, tag_id, autoflush=True): tag_id -- The id of the tag to return. """ - query = Session.query(Tag).filter(Tag.id==tag_id) + query = meta.Session.query(Tag).filter(Tag.id==tag_id) query = query.autoflush(autoflush) tag = query.first() return tag @@ -75,10 +77,10 @@ def by_name(cls, name, vocab=None, autoflush=True): """ if vocab: - query = Session.query(Tag).filter(Tag.name==name).filter( + query = meta.Session.query(Tag).filter(Tag.name==name).filter( Tag.vocabulary_id==vocab.id) else: - query = Session.query(Tag).filter(Tag.name==name).filter( + query = meta.Session.query(Tag).filter(Tag.name==name).filter( Tag.vocabulary_id==None) query = query.autoflush(autoflush) tag = query.first() @@ -132,9 +134,9 @@ def search_by_name(cls, search_term, vocab_id_or_name=None): if vocab is None: # The user specified an invalid vocab. return None - query = Session.query(Tag).filter(Tag.vocabulary_id==vocab.id) + query = meta.Session.query(Tag).filter(Tag.vocabulary_id==vocab.id) else: - query = Session.query(Tag) + query = meta.Session.query(Tag) search_term = search_term.strip().lower() query = query.filter(Tag.name.contains(search_term)) query = query.distinct().join(Tag.package_tags) @@ -155,11 +157,11 @@ def all(cls, vocab_id_or_name=None): # The user specified an invalid vocab. raise ckan.logic.NotFound("could not find vocabulary '%s'" % vocab_id_or_name) - query = Session.query(Tag).filter(Tag.vocabulary_id==vocab.id) + query = meta.Session.query(Tag).filter(Tag.vocabulary_id==vocab.id) else: - query = Session.query(Tag).filter(Tag.vocabulary_id == None) + query = meta.Session.query(Tag).filter(Tag.vocabulary_id == None) query = query.distinct().join(PackageTagRevision) - query = query.filter(sqlalchemy.and_( + query = query.filter(and_( PackageTagRevision.state == 'active', PackageTagRevision.current == True)) return query @@ -171,13 +173,13 @@ def packages(self): The list is sorted by package name. """ - q = Session.query(Package) + q = meta.Session.query(_package.Package) q = q.join(PackageTagRevision) q = q.filter(PackageTagRevision.tag_id == self.id) - q = q.filter(sqlalchemy.and_( + q = q.filter(and_( PackageTagRevision.state == 'active', PackageTagRevision.current == True)) - q = q.order_by(Package.name) + q = q.order_by(_package.Package.name) packages = q.all() return packages @@ -242,13 +244,13 @@ def by_name(self, package_name, tag_name, vocab_id_or_name=None, if vocab is None: # The user specified an invalid vocab. return None - query = (Session.query(PackageTag, Tag, Package) + query = (meta.Session.query(PackageTag, Tag, _package.Package) .filter(Tag.vocabulary_id == vocab.id) - .filter(Package.name==package_name) + .filter(_package.Package.name==package_name) .filter(Tag.name==tag_name)) else: - query = (Session.query(PackageTag) - .filter(Package.name==package_name) + query = (meta.Session.query(PackageTag) + .filter(_package.Package.name==package_name) .filter(Tag.name==tag_name)) query = query.autoflush(autoflush) return query.one()[0] @@ -256,7 +258,7 @@ def by_name(self, package_name, tag_name, vocab_id_or_name=None, def related_packages(self): return [self.package] -mapper(Tag, tag_table, properties={ +meta.mapper(Tag, tag_table, properties={ 'package_tags': relation(PackageTag, backref='tag', cascade='all, delete, delete-orphan', ), @@ -266,21 +268,23 @@ def related_packages(self): order_by=tag_table.c.name, ) -mapper(PackageTag, package_tag_table, properties={ - 'pkg':relation(Package, backref='package_tag_all', +meta.mapper(PackageTag, package_tag_table, properties={ + 'pkg':relation(_package.Package, backref='package_tag_all', cascade='none', ) }, order_by=package_tag_table.c.id, extension=[vdm.sqlalchemy.Revisioner(package_tag_revision_table), - extension.PluginMapperExtension(), + _extension.PluginMapperExtension(), ], ) -from package_mapping import * +# FIXME This is very wrong +# It is part of the circular import crazy +import package_mapping -vdm.sqlalchemy.modify_base_object_mapper(PackageTag, Revision, State) -PackageTagRevision = vdm.sqlalchemy.create_object_version(mapper, PackageTag, +vdm.sqlalchemy.modify_base_object_mapper(PackageTag, core.Revision, core.State) +PackageTagRevision = vdm.sqlalchemy.create_object_version(meta.mapper, PackageTag, package_tag_revision_table) PackageTagRevision.related_packages = lambda self: [self.continuity.package] diff --git a/ckan/model/term_translation.py b/ckan/model/term_translation.py index 822ee74c324..77cb2e88056 100644 --- a/ckan/model/term_translation.py +++ b/ckan/model/term_translation.py @@ -1,9 +1,10 @@ -from meta import * -from core import * +from sqlalchemy import Column, Table +from sqlalchemy.types import UnicodeText +import meta __all__ = ['term_translation_table'] -term_translation_table = Table('term_translation', metadata, +term_translation_table = Table('term_translation', meta.metadata, Column('term', UnicodeText, nullable=False), Column('term_translation', UnicodeText, nullable=False), Column('lang_code', UnicodeText, nullable=False), From f1b8aac2a05ca3e30741c9da9a1a36892fb70dfe Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:11:19 +0100 Subject: [PATCH 007/109] import cleans for model/activity --- ckan/model/activity.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/ckan/model/activity.py b/ckan/model/activity.py index e31e355c11d..ff72337f04d 100644 --- a/ckan/model/activity.py +++ b/ckan/model/activity.py @@ -1,19 +1,17 @@ import datetime -from sqlalchemy import orm +from sqlalchemy import orm, types, Column, Table, ForeignKey -from meta import * -from core import * -from package import * +import meta import types as _types import domain_object -__all__ = ['Activity', 'activity_table', +__all__ = ['Activity', 'activity_table', 'ActivityDetail', 'activity_detail_table', ] activity_table = Table( - 'activity', metadata, + 'activity', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('timestamp', types.DateTime), Column('user_id', types.UnicodeText), @@ -24,7 +22,7 @@ ) activity_detail_table = Table( - 'activity_detail', metadata, + 'activity_detail', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('activity_id', types.UnicodeText, ForeignKey('activity.id')), Column('object_id', types.UnicodeText), @@ -48,7 +46,7 @@ def __init__(self, user_id, object_id, revision_id, activity_type, else: self.data = data -mapper(Activity, activity_table) +meta.mapper(Activity, activity_table) class ActivityDetail(domain_object.DomainObject): @@ -63,6 +61,6 @@ def __init__(self, activity_id, object_id, object_type, activity_type, else: self.data = data -mapper(ActivityDetail, activity_detail_table, properties = { +meta.mapper(ActivityDetail, activity_detail_table, properties = { 'activity':orm.relation ( Activity, backref=orm.backref('activity_detail')) }) From 68594504dd0dde1f1e888f1a5d78a87389409d51 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:18:31 +0100 Subject: [PATCH 008/109] import cleans for model/user --- ckan/model/user.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ckan/model/user.py b/ckan/model/user.py index 50c91456ba9..1492cde0ce0 100644 --- a/ckan/model/user.py +++ b/ckan/model/user.py @@ -5,22 +5,23 @@ from sqlalchemy.sql.expression import or_ from sqlalchemy.orm import synonym +from sqlalchemy import types, Column, Table -from meta import * +import meta import types as _types import domain_object -user_table = Table('user', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('name', UnicodeText, nullable=False, unique=True), - Column('openid', UnicodeText), - Column('password', UnicodeText), - Column('fullname', UnicodeText), - Column('email', UnicodeText), - Column('apikey', UnicodeText, default=_types.make_uuid), - Column('created', DateTime, default=datetime.datetime.now), - Column('reset_key', UnicodeText), - Column('about', UnicodeText), +user_table = Table('user', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('name', types.UnicodeText, nullable=False, unique=True), + Column('openid', types.UnicodeText), + Column('password', types.UnicodeText), + Column('fullname', types.UnicodeText), + Column('email', types.UnicodeText), + Column('apikey', types.UnicodeText, default=_types.make_uuid), + Column('created', types.DateTime, default=datetime.datetime.now), + Column('reset_key', types.UnicodeText), + Column('about', types.UnicodeText), ) class User(domain_object.DomainObject): @@ -30,7 +31,7 @@ class User(domain_object.DomainObject): @classmethod def by_openid(cls, openid): - obj = Session.query(cls).autoflush(False) + obj = meta.Session.query(cls).autoflush(False) return obj.filter_by(openid=openid).first() @classmethod @@ -39,7 +40,7 @@ def get(cls, user_reference): # by browsers, so correct that for the openid lookup corrected_openid_user_ref = cls.DOUBLE_SLASH.sub('://\\1', user_reference) - query = Session.query(cls).autoflush(False) + query = meta.Session.query(cls).autoflush(False) query = query.filter(or_(cls.name==user_reference, cls.openid==corrected_openid_user_ref, cls.id==user_reference)) @@ -136,13 +137,13 @@ def as_dict(self): def number_of_edits(self): # have to import here to avoid circular imports import ckan.model as model - revisions_q = model.Session.query(model.Revision).filter_by(author=self.name) + revisions_q = meta.Session.query(model.Revision).filter_by(author=self.name) return revisions_q.count() def number_administered_packages(self): # have to import here to avoid circular imports import ckan.model as model - q = model.Session.query(model.PackageRole) + q = meta.Session.query(model.PackageRole) q = q.filter_by(user=self, role=model.Role.ADMIN) return q.count() @@ -165,7 +166,7 @@ def get_group_ids(self, group_type=None): def get_groups(self, group_type=None, capacity=None): import ckan.model as model - q = model.Session.query(model.Group)\ + q = meta.Session.query(model.Group)\ .join(model.Member, model.Member.group_id == model.Group.id and \ model.Member.table_name == 'user' ).\ join(model.User, model.User.id == model.Member.table_id).\ @@ -189,9 +190,8 @@ def search(cls, querystr, sqlalchemy_query=None): '''Search name, fullname, email and openid. ''' - import ckan.model as model if sqlalchemy_query is None: - query = model.Session.query(cls) + query = meta.Session.query(cls) else: query = sqlalchemy_query qstr = '%' + querystr + '%' @@ -202,7 +202,7 @@ def search(cls, querystr, sqlalchemy_query=None): )) return query -mapper(User, user_table, +meta.mapper(User, user_table, properties = { 'password': synonym('_password', map_column=True) }, From 9fbd51342a0ac450d2557b3053e5a88d643d203c Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:28:09 +0100 Subject: [PATCH 009/109] import cleans for model/authourization_group --- ckan/model/authorization_group.py | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/ckan/model/authorization_group.py b/ckan/model/authorization_group.py index 6692e3cc36a..b4401a02757 100644 --- a/ckan/model/authorization_group.py +++ b/ckan/model/authorization_group.py @@ -1,21 +1,23 @@ import datetime -from meta import * +from sqlalchemy import orm, types, Column, Table, ForeignKey, or_ +#from meta import * +import meta import user import types as _types import domain_object -authorization_group_table = Table('authorization_group', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('name', UnicodeText), - Column('created', DateTime, default=datetime.datetime.now), +authorization_group_table = Table('authorization_group', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('name', types.UnicodeText), + Column('created', types.DateTime, default=datetime.datetime.now), ) -authorization_group_user_table = Table('authorization_group_user', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('authorization_group_id', UnicodeText, ForeignKey('authorization_group.id'), +authorization_group_user_table = Table('authorization_group_user', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('authorization_group_id', types.UnicodeText, ForeignKey('authorization_group.id'), nullable=False), - Column('user_id', UnicodeText, ForeignKey('user.id'), nullable=False) + Column('user_id', types.UnicodeText, ForeignKey('user.id'), nullable=False) ) @@ -25,9 +27,8 @@ class AuthorizationGroup(domain_object.DomainObject): def search(cls, querystr, sqlalchemy_query=None): '''Search name. ''' - import ckan.model as model if sqlalchemy_query is None: - query = model.Session.query(cls) + query = meta.Session.query(cls) else: query = sqlalchemy_query qstr = '%' + querystr + '%' @@ -37,7 +38,7 @@ def search(cls, querystr, sqlalchemy_query=None): @classmethod def get(cls, auth_group_reference): - query = Session.query(cls).autoflush(False) + query = meta.Session.query(cls).autoflush(False) query = query.filter(or_(cls.name==auth_group_reference, cls.id==auth_group_reference)) return query.first() @@ -46,7 +47,7 @@ class AuthorizationGroupUser(domain_object.DomainObject): pass def user_in_authorization_group(user, authorization_group): - q = Session.query(AuthorizationGroup) + q = meta.Session.query(AuthorizationGroup) q = q.filter_by(id=authorization_group.id) q = q.filter(AuthorizationGroup.users.contains(user)) return q.count() == 1 @@ -54,16 +55,16 @@ def user_in_authorization_group(user, authorization_group): def add_user_to_authorization_group(user, authorization_group, role): assert not user_in_authorization_group(user, authorization_group) from authz import add_user_to_role - Session.add(authorization_group) + meta.Session.add(authorization_group) authorization_group.users.append(user) add_user_to_role(user, role, authorization_group) def remove_user_from_authorization_group(user, authorization_group): assert user_in_authorization_group(user, authorization_group) from authz import remove_user_from_role, AuthorizationGroupRole - Session.add(authorization_group) + meta.Session.add(authorization_group) authorization_group.users.remove(user) - q = Session.query(AuthorizationGroupRole) + q = meta.Session.query(AuthorizationGroupRole) q = q.filter_by(authorization_group=authorization_group, user=user) for agr in q: @@ -71,10 +72,10 @@ def remove_user_from_authorization_group(user, authorization_group): -mapper(AuthorizationGroup, authorization_group_table, properties={ - 'users': relation(user.User, lazy=True, secondary=authorization_group_user_table, - backref=backref('authorization_groups', lazy=True)) +meta.mapper(AuthorizationGroup, authorization_group_table, properties={ + 'users': orm.relation(user.User, lazy=True, secondary=authorization_group_user_table, + backref=orm.backref('authorization_groups', lazy=True)) }, order_by=authorization_group_table.c.name) -mapper(AuthorizationGroupUser, authorization_group_user_table) +meta.mapper(AuthorizationGroupUser, authorization_group_user_table) From 570805427a11e72bb82d9b6b1d9c6ab2accfc01b Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:28:51 +0100 Subject: [PATCH 010/109] more cleans for model/authourization_group --- ckan/model/authorization_group.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ckan/model/authorization_group.py b/ckan/model/authorization_group.py index b4401a02757..2933570652e 100644 --- a/ckan/model/authorization_group.py +++ b/ckan/model/authorization_group.py @@ -1,7 +1,7 @@ import datetime from sqlalchemy import orm, types, Column, Table, ForeignKey, or_ -#from meta import * + import meta import user import types as _types @@ -15,7 +15,7 @@ authorization_group_user_table = Table('authorization_group_user', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), - Column('authorization_group_id', types.UnicodeText, ForeignKey('authorization_group.id'), + Column('authorization_group_id', types.UnicodeText, ForeignKey('authorization_group.id'), nullable=False), Column('user_id', types.UnicodeText, ForeignKey('user.id'), nullable=False) ) @@ -25,7 +25,7 @@ class AuthorizationGroup(domain_object.DomainObject): @classmethod def search(cls, querystr, sqlalchemy_query=None): - '''Search name. + '''Search name. ''' if sqlalchemy_query is None: query = meta.Session.query(cls) @@ -42,7 +42,7 @@ def get(cls, auth_group_reference): query = query.filter(or_(cls.name==auth_group_reference, cls.id==auth_group_reference)) return query.first() - + class AuthorizationGroupUser(domain_object.DomainObject): pass @@ -51,7 +51,7 @@ def user_in_authorization_group(user, authorization_group): q = q.filter_by(id=authorization_group.id) q = q.filter(AuthorizationGroup.users.contains(user)) return q.count() == 1 - + def add_user_to_authorization_group(user, authorization_group, role): assert not user_in_authorization_group(user, authorization_group) from authz import add_user_to_role @@ -69,13 +69,13 @@ def remove_user_from_authorization_group(user, authorization_group): user=user) for agr in q: remove_user_from_role(user, agr.role, authorization_group) - + meta.mapper(AuthorizationGroup, authorization_group_table, properties={ - 'users': orm.relation(user.User, lazy=True, secondary=authorization_group_user_table, - backref=orm.backref('authorization_groups', lazy=True)) + 'users': orm.relation(user.User, lazy=True, secondary=authorization_group_user_table, + backref=orm.backref('authorization_groups', lazy=True)) }, order_by=authorization_group_table.c.name) - + meta.mapper(AuthorizationGroupUser, authorization_group_user_table) From d3be023c1f53f9b93e2aec782ad005045b224da9 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:51:31 +0100 Subject: [PATCH 011/109] more cleans for model/authz --- ckan/model/authz.py | 129 ++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/ckan/model/authz.py b/ckan/model/authz.py index f39aa0e99ba..5ceb544f6d6 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -2,15 +2,18 @@ doc/authorization.rst. ''' -from meta import * -from core import * -from package import * +from sqlalchemy import orm, types, Column, Table, ForeignKey +from pylons import config + +import package as _package +import meta import group import user as _user -from core import System +import core import authorization_group as auth_group import domain_object import types as _types +import ckan.lib.helpers as h PSEUDO_USER__LOGGED_IN = u'logged_in' PSEUDO_USER__VISITOR = u'visitor' @@ -87,38 +90,38 @@ class Role(Enum): ## ====================================== ## Table Definitions -role_action_table = Table('role_action', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('role', UnicodeText), - Column('context', UnicodeText, nullable=False), - Column('action', UnicodeText), +role_action_table = Table('role_action', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('role', types.UnicodeText), + Column('context', types.UnicodeText, nullable=False), + Column('action', types.UnicodeText), ) -user_object_role_table = Table('user_object_role', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('user_id', UnicodeText, ForeignKey('user.id'), nullable=True), - Column('authorized_group_id', UnicodeText, ForeignKey('authorization_group.id'), nullable=True), - Column('context', UnicodeText, nullable=False), # stores subtype - Column('role', UnicodeText) +user_object_role_table = Table('user_object_role', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('user_id', types.UnicodeText, ForeignKey('user.id'), nullable=True), + Column('authorized_group_id', types.UnicodeText, ForeignKey('authorization_group.id'), nullable=True), + Column('context', types.UnicodeText, nullable=False), # stores subtype + Column('role', types.UnicodeText) ) -package_role_table = Table('package_role', metadata, - Column('user_object_role_id', UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), - Column('package_id', UnicodeText, ForeignKey('package.id')), +package_role_table = Table('package_role', meta.metadata, + Column('user_object_role_id', types.UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), + Column('package_id', types.UnicodeText, ForeignKey('package.id')), ) -group_role_table = Table('group_role', metadata, - Column('user_object_role_id', UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), - Column('group_id', UnicodeText, ForeignKey('group.id')), +group_role_table = Table('group_role', meta.metadata, + Column('user_object_role_id', types.UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), + Column('group_id', types.UnicodeText, ForeignKey('group.id')), ) -authorization_group_role_table = Table('authorization_group_role', metadata, - Column('user_object_role_id', UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), - Column('authorization_group_id', UnicodeText, ForeignKey('authorization_group.id')), +authorization_group_role_table = Table('authorization_group_role', meta.metadata, + Column('user_object_role_id', types.UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), + Column('authorization_group_id', types.UnicodeText, ForeignKey('authorization_group.id')), ) -system_role_table = Table('system_role', metadata, - Column('user_object_role_id', UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), +system_role_table = Table('system_role', meta.metadata, + Column('user_object_role_id', types.UnicodeText, ForeignKey('user_object_role.id'), primary_key=True), ) @@ -169,7 +172,7 @@ def authorization_group_has_role(cls, authorized_group, role, domain_obj): @classmethod def _user_query(cls, user, role, domain_obj): - q = Session.query(cls).filter_by(role=role) + q = meta.Session.query(cls).filter_by(role=role) # some protected objects are not "contextual" if cls.name is not None: # e.g. filter_by(package=domain_obj) @@ -179,7 +182,7 @@ def _user_query(cls, user, role, domain_obj): @classmethod def _authorized_group_query(cls, authorized_group, role, domain_obj): - q = Session.query(cls).filter_by(role=role) + q = meta.Session.query(cls).filter_by(role=role) # some protected objects are not "contextual" if cls.name is not None: # e.g. filter_by(package=domain_obj) @@ -202,7 +205,7 @@ def add_user_to_role(cls, user, role, domain_obj): objectrole = cls(role=role, user=user) if cls.name is not None: setattr(objectrole, cls.name, domain_obj) - Session.add(objectrole) + meta.Session.add(objectrole) @classmethod def add_authorization_group_to_role(cls, authorization_group, role, domain_obj): @@ -217,26 +220,26 @@ def add_authorization_group_to_role(cls, authorization_group, role, domain_obj): objectrole = cls(role=role, authorized_group=authorization_group) if cls.name is not None: setattr(objectrole, cls.name, domain_obj) - Session.add(objectrole) + meta.Session.add(objectrole) @classmethod def remove_user_from_role(cls, user, role, domain_obj): q = cls._user_query(user, role, domain_obj) for uo_role in q.all(): - Session.delete(uo_role) - Session.commit() - Session.remove() + meta.Session.delete(uo_role) + meta.Session.commit() + meta.Session.remove() @classmethod def remove_authorization_group_from_role(cls, authorization_group, role, domain_obj): q = cls._authorized_group_query(authorization_group, role, domain_obj) for ago_role in q.all(): - Session.delete(ago_role) - Session.commit() - Session.remove() + meta.Session.delete(ago_role) + meta.Session.commit() + meta.Session.remove() class PackageRole(UserObjectRole): - protected_object = Package + protected_object = _package.Package name = 'package' def __repr__(self): @@ -284,7 +287,7 @@ def __repr__(self): protected_objects[AuthorizationGroupRole.protected_object] = AuthorizationGroupRole class SystemRole(UserObjectRole): - protected_object = System + protected_object = core.System name = None protected_objects[SystemRole.protected_object] = SystemRole @@ -320,9 +323,9 @@ def remove_authorization_group_from_role(authorization_group, role, domain_obj): objectrole.remove_authorization_group_from_role(authorization_group, role, domain_obj) def init_authz_configuration_data(): - setup_default_user_roles(System()) - Session.commit() - Session.remove() + setup_default_user_roles(core.System()) + meta.Session.commit() + meta.Session.remove() def init_authz_const_data(): '''Setup all default role-actions. @@ -334,12 +337,12 @@ def init_authz_const_data(): ''' for role, action in default_role_actions: - ra = Session.query(RoleAction).filter_by(role=role, action=action).first() + ra = meta.Session.query(RoleAction).filter_by(role=role, action=action).first() if ra is not None: continue ra = RoleAction(role=role, context=u'', action=action) - Session.add(ra) - Session.commit() - Session.remove() + meta.Session.add(ra) + meta.Session.commit() + meta.Session.remove() ## TODO: this should be in ckan/authz.py def setup_user_roles(_domain_object, visitor_roles, logged_in_roles, admins=[]): @@ -366,12 +369,12 @@ def setup_user_roles(_domain_object, visitor_roles, logged_in_roles, admins=[]): def give_all_packages_default_user_roles(): # if this command gives an exception, you probably # forgot to do 'paster db init' - pkgs = Session.query(Package).all() + pkgs = meta.Session.query(_package.Package).all() for pkg in pkgs: print pkg # weird - should already be in session but complains w/o this - Session.add(pkg) + meta.Session.add(pkg) if len(pkg.roles) > 0: print 'Skipping (already has roles): %s' % pkg.name continue @@ -403,15 +406,13 @@ def give_all_packages_default_user_roles(): def get_default_user_roles(_domain_object): # TODO: Should this func go in lib rather than model now? - from ckan.lib.helpers import json - from pylons import config def _get_default_user_roles(_domain_object): config_key = 'ckan.default_roles.%s' % obj_type user_roles_json = config.get(config_key) if user_roles_json is None: user_roles_str = default_default_user_roles[obj_type] else: - user_roles_str = json.loads(user_roles_json) if user_roles_json else {} + user_roles_str = h.json.loads(user_roles_json) if user_roles_json else {} unknown_keys = set(user_roles_str.keys()) - set(('visitor', 'logged_in')) assert not unknown_keys, 'Auth config for %r has unknown key %r' % \ (_domain_object, unknown_keys) @@ -431,7 +432,7 @@ def setup_default_user_roles(_domain_object, admins=[]): @param admins - a list of User objects NB: leaves caller to commit change. ''' - assert isinstance(_domain_object, (Package, group.Group, System, auth_group.AuthorizationGroup)), _domain_object + assert isinstance(_domain_object, (_package.Package, group.Group, core.System, auth_group.AuthorizationGroup)), _domain_object assert isinstance(admins, list) user_roles_ = get_default_user_roles(_domain_object) setup_user_roles(_domain_object, @@ -441,23 +442,23 @@ def setup_default_user_roles(_domain_object, admins=[]): def clear_user_roles(_domain_object): assert isinstance(_domain_object, domain_object.DomainObject) - if isinstance(_domain_object, Package): - q = Session.query(PackageRole).filter_by(package=_domain_object) + if isinstance(_domain_object, _package.Package): + q = meta.Session.query(PackageRole).filter_by(package=_domain_object) elif isinstance(_domain_object, group.Group): - q = Session.query(GroupRole).filter_by(group=_domain_object) + q = meta.Session.query(GroupRole).filter_by(group=_domain_object) else: raise NotImplementedError() user_roles = q.all() for user_role in user_roles: - Session.delete(user_role) + meta.Session.delete(user_role) ## ====================================== ## Mappers -mapper(RoleAction, role_action_table) +meta.mapper(RoleAction, role_action_table) -mapper(UserObjectRole, user_object_role_table, +meta.mapper(UserObjectRole, user_object_role_table, polymorphic_on=user_object_role_table.c.context, polymorphic_identity=u'user_object', properties={ @@ -475,10 +476,10 @@ def clear_user_roles(_domain_object): order_by=[user_object_role_table.c.id], ) -mapper(PackageRole, package_role_table, inherits=UserObjectRole, - polymorphic_identity=unicode(Package.__name__), +meta.mapper(PackageRole, package_role_table, inherits=UserObjectRole, + polymorphic_identity=unicode(_package.Package.__name__), properties={ - 'package': orm.relation(Package, + 'package': orm.relation(_package.Package, backref=orm.backref('roles', cascade='all, delete, delete-orphan' ) @@ -487,7 +488,7 @@ def clear_user_roles(_domain_object): order_by=[package_role_table.c.user_object_role_id], ) -mapper(GroupRole, group_role_table, inherits=UserObjectRole, +meta.mapper(GroupRole, group_role_table, inherits=UserObjectRole, polymorphic_identity=unicode(group.Group.__name__), properties={ 'group': orm.relation(group.Group, @@ -499,7 +500,7 @@ def clear_user_roles(_domain_object): order_by=[group_role_table.c.user_object_role_id], ) -mapper(AuthorizationGroupRole, authorization_group_role_table, inherits=UserObjectRole, +meta.mapper(AuthorizationGroupRole, authorization_group_role_table, inherits=UserObjectRole, polymorphic_identity=unicode(auth_group.AuthorizationGroup.__name__), properties={ 'authorization_group': orm.relation(auth_group.AuthorizationGroup, @@ -512,7 +513,7 @@ def clear_user_roles(_domain_object): order_by=[authorization_group_role_table.c.user_object_role_id], ) -mapper(SystemRole, system_role_table, inherits=UserObjectRole, - polymorphic_identity=unicode(System.__name__), +meta.mapper(SystemRole, system_role_table, inherits=UserObjectRole, + polymorphic_identity=unicode(core.System.__name__), order_by=[system_role_table.c.user_object_role_id], ) From 079a0b49f16b675e996385bcc0f09e14ad297c40 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 13:55:10 +0100 Subject: [PATCH 012/109] more cleans for model/extensions --- ckan/model/extension.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/ckan/model/extension.py b/ckan/model/extension.py index b29556e6f42..a278081aea3 100644 --- a/ckan/model/extension.py +++ b/ckan/model/extension.py @@ -3,10 +3,10 @@ """ import logging -from sqlalchemy.orm.interfaces import MapperExtension, EXT_CONTINUE, EXT_STOP +from sqlalchemy.orm.interfaces import MapperExtension from sqlalchemy.orm.session import SessionExtension -from ckan.plugins import PluginImplementations, IMapper, ISession +import ckan.plugins as plugins try: from operator import methodcaller @@ -24,7 +24,7 @@ class ObserverNotifier(object): Mixin for hooking into SQLAlchemy MapperExtension/SessionExtension """ - + observers = None def notify_observers(self, func): @@ -42,8 +42,8 @@ class PluginMapperExtension(MapperExtension, ObserverNotifier): Extension that calls plugins implementing IMapper on SQLAlchemy MapperExtension events """ - observers = PluginImplementations(IMapper) - + observers = plugins.PluginImplementations(plugins.IMapper) + def before_insert(self, mapper, connection, instance): return self.notify_observers( methodcaller('before_insert', mapper, connection, instance) @@ -63,17 +63,17 @@ def after_insert(self, mapper, connection, instance): return self.notify_observers( methodcaller('after_insert', mapper, connection, instance) ) - + def after_update(self, mapper, connection, instance): return self.notify_observers( methodcaller('after_update', mapper, connection, instance) ) - + def after_delete(self, mapper, connection, instance): return self.notify_observers( methodcaller('after_delete', mapper, connection, instance) ) - + class PluginSessionExtension(SessionExtension, ObserverNotifier): """ @@ -81,33 +81,33 @@ class PluginSessionExtension(SessionExtension, ObserverNotifier): SessionExtension events """ - observers = PluginImplementations(ISession) - + observers = plugins.PluginImplementations(plugins.ISession) + def after_begin(self, session, transaction, connection): return self.notify_observers( methodcaller('after_begin', session, transaction, connection) ) - + def before_flush(self, session, flush_context, instances): return self.notify_observers( methodcaller('before_flush', session, flush_context, instances) ) - + def after_flush(self, session, flush_context): return self.notify_observers( methodcaller('after_flush', session, flush_context) ) - + def before_commit(self, session): return self.notify_observers( methodcaller('before_commit', session) ) - + def after_commit(self, session): return self.notify_observers( methodcaller('after_commit', session) ) - + def after_rollback(self, session): return self.notify_observers( methodcaller('after_rollback', session) From 25fb6a26cca0486873a6e2cc9f2b4f9b30b59d68 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:11:20 +0100 Subject: [PATCH 013/109] more cleans for model/group --- ckan/model/group.py | 96 +++++++++++++++++++++++---------------------- ckan/model/tag.py | 2 +- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/ckan/model/group.py b/ckan/model/group.py index d935c8cc412..e68e712e763 100644 --- a/ckan/model/group.py +++ b/ckan/model/group.py @@ -1,42 +1,44 @@ import datetime -from meta import * -from core import * -from sqlalchemy.orm import eagerload_all -from package import * +from sqlalchemy import orm, types, Column, Table, ForeignKey +import meta +import core +import package as _package import types as _types import domain_object import vdm.sqlalchemy -from ckan.model import extension, User -from sqlalchemy.ext.associationproxy import association_proxy +import user as _user + +# FIXME why are we passing this around here? +package_revision_table = _package.package_revision_table __all__ = ['group_table', 'Group', 'package_revision_table', 'Member', 'GroupRevision', 'MemberRevision', 'member_revision_table', 'member_table'] -member_table = Table('member', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('table_name', UnicodeText, nullable=False), - Column('table_id', UnicodeText, nullable=False), - Column('capacity', UnicodeText, nullable=False), - Column('group_id', UnicodeText, ForeignKey('group.id')), +member_table = Table('member', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('table_name', types.UnicodeText, nullable=False), + Column('table_id', types.UnicodeText, nullable=False), + Column('capacity', types.UnicodeText, nullable=False), + Column('group_id', types.UnicodeText, ForeignKey('group.id')), ) vdm.sqlalchemy.make_table_stateful(member_table) -member_revision_table = make_revisioned_table(member_table) - -group_table = Table('group', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('name', UnicodeText, nullable=False, unique=True), - Column('title', UnicodeText), - Column('type', UnicodeText, nullable=False), - Column('description', UnicodeText), - Column('created', DateTime, default=datetime.datetime.now), - Column('approval_status', UnicodeText, default=u"approved"), +member_revision_table = core.make_revisioned_table(member_table) + +group_table = Table('group', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('name', types.UnicodeText, nullable=False, unique=True), + Column('title', types.UnicodeText), + Column('type', types.UnicodeText, nullable=False), + Column('description', types.UnicodeText), + Column('created', types.DateTime, default=datetime.datetime.now), + Column('approval_status', types.UnicodeText, default=u"approved"), ) vdm.sqlalchemy.make_table_stateful(group_table) -group_revision_table = make_revisioned_table(group_table) +group_revision_table = core.make_revisioned_table(group_table) class Member(vdm.sqlalchemy.RevisionedObjectMixin, @@ -54,7 +56,7 @@ def __init__(self, group=None, table_id=None, group_id=None, @classmethod def get(cls, reference): '''Returns a group object referenced by its id or name.''' - query = Session.query(cls).filter(cls.id==reference) + query = meta.Session.query(cls).filter(cls.id==reference) member = query.first() if member == None: member = cls.by_name(reference) @@ -72,7 +74,7 @@ def get_related(self, type): def related_packages(self): # TODO do we want to return all related packages or certain ones? - return Session.query(Package).filter_by(id=self.table_id).all() + return meta.Session.query(_package.Package).filter_by(id=self.table_id).all() class Group(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, @@ -96,7 +98,7 @@ def display_name(self): @classmethod def get(cls, reference): '''Returns a group object referenced by its id or name.''' - query = Session.query(cls).filter(cls.id==reference) + query = meta.Session.query(cls).filter(cls.id==reference) group = query.first() if group == None: group = cls.by_name(reference) @@ -108,7 +110,7 @@ def all(cls, group_type=None, state=('active',)): """ Returns all groups. """ - q = Session.query(cls) + q = meta.Session.query(cls) if state: q = q.filter(cls.state.in_(state)) @@ -132,7 +134,7 @@ def set_approval_status(self, status): def members_of_type(self, object_type, capacity=None): from ckan import model object_type_string = object_type.__name__.lower() - query = Session.query(object_type).\ + query = meta.Session.query(object_type).\ filter(model.Group.id == self.id).\ filter(model.Member.state == 'active').\ filter(model.Member.table_name == object_type_string) @@ -152,7 +154,7 @@ def add_child(self, object_instance): object_type_string = object_instance.__class__.__name__.lower() if not object_instance in self.members_of_type(object_instance.__class__).all(): member = Member(group=self, table_id=getattr(object_instance,'id'), table_name=object_type_string) - Session.add(member) + meta.Session.add(member) def get_children_groups(self, type='group'): # Returns a list of dicts where each dict contains "id", "name", and "title" @@ -160,16 +162,16 @@ def get_children_groups(self, type='group'): # problems as it returns only the first level deep apparently not recursing # any deeper than that. If we simplify and request only specific fields then # if returns the full depth of the hierarchy. - results = Session.query("id","name", "title").\ + results = meta.Session.query("id","name", "title").\ from_statement(HIERARCHY_CTE).params(id=self.id, type=type).all() return [ { "id":idf, "name": name, "title": title } for idf,name,title in results ] def active_packages(self, load_eager=True): - query = Session.query(Package).\ + query = meta.Session.query(_package.Package).\ filter_by(state=vdm.sqlalchemy.State.ACTIVE).\ filter(group_table.c.id == self.id).\ filter(member_table.c.state == 'active').\ - join(member_table, member_table.c.table_id == Package.id).\ + join(member_table, member_table.c.table_id == _package.Package.id).\ join(group_table, group_table.c.id == member_table.c.group_id) return query @@ -177,9 +179,9 @@ def active_packages(self, load_eager=True): def search_by_name(cls, text_query, group_type=None): text_query = text_query.strip().lower() if not group_type: - q = Session.query(cls).filter(cls.name.contains(text_query)) + q = meta.Session.query(cls).filter(cls.name.contains(text_query)) else: - q = Session.query(cls).filter(cls.name.contains(text_query)).filter(cls.type==group_type) + q = meta.Session.query(cls).filter(cls.name.contains(text_query)).filter(cls.type==group_type) return q.order_by(cls.title) def as_dict(self, ref_package_by='name'): @@ -187,23 +189,23 @@ def as_dict(self, ref_package_by='name'): _dict['packages'] = [getattr(package, ref_package_by) for package in self.packages] _dict['extras'] = dict([(key, value) for key, value in self.extras.items()]) if ( self.type == 'publisher' ): - _dict['users'] = [getattr(user, "name") for user in self.members_of_type(User)] + _dict['users'] = [getattr(user, "name") for user in self.members_of_type(_user.User)] return _dict def add_package_by_name(self, package_name): if not package_name: return - package = Package.by_name(package_name) + package = _package.Package.by_name(package_name) assert package if not package in self.members_of_type( package.__class__ ).all(): member = Member(group=self, table_id=package.id, table_name='package') - Session.add(member) + meta.Session.add(member) def get_groups(self, group_type=None, capacity=None): """ Get all groups that this group is within """ import ckan.model as model if '_groups' not in self.__dict__: - self._groups = model.Session.query(model.Group).\ + self._groups = meta.Session.query(model.Group).\ join(model.Member, model.Member.group_id == model.Group.id and \ model.Member.table_name == 'group').\ filter(model.Member.state == 'active').\ @@ -231,7 +233,7 @@ def all_related_revisions(self): results[grp_rev.revision].append(grp_rev) for class_ in [Member, GroupExtra]: rev_class = class_.__revision_class__ - obj_revisions = Session.query(rev_class).filter_by(group_id=self.id).all() + obj_revisions = meta.Session.query(rev_class).filter_by(group_id=self.id).all() for obj_rev in obj_revisions: if not results.has_key(obj_rev.revision): results[obj_rev.revision] = [] @@ -245,25 +247,25 @@ def __repr__(self): return '' % self.name -mapper(Group, group_table, +meta.mapper(Group, group_table, extension=[vdm.sqlalchemy.Revisioner(group_revision_table),], ) -vdm.sqlalchemy.modify_base_object_mapper(Group, Revision, State) -GroupRevision = vdm.sqlalchemy.create_object_version(mapper, Group, +vdm.sqlalchemy.modify_base_object_mapper(Group, core.Revision, core.State) +GroupRevision = vdm.sqlalchemy.create_object_version(meta.mapper, Group, group_revision_table) -mapper(Member, member_table, properties={ - 'group': relation(Group, - backref=backref('member_all', cascade='all, delete-orphan') +meta.mapper(Member, member_table, properties={ + 'group': orm.relation(Group, + backref=orm.backref('member_all', cascade='all, delete-orphan') ), }, extension=[vdm.sqlalchemy.Revisioner(member_revision_table),], ) -vdm.sqlalchemy.modify_base_object_mapper(Member, Revision, State) -MemberRevision = vdm.sqlalchemy.create_object_version(mapper, Member, +vdm.sqlalchemy.modify_base_object_mapper(Member, core.Revision, core.State) +MemberRevision = vdm.sqlalchemy.create_object_version(meta.mapper, Member, member_revision_table) #TODO diff --git a/ckan/model/tag.py b/ckan/model/tag.py index 96482607529..804ec393b48 100644 --- a/ckan/model/tag.py +++ b/ckan/model/tag.py @@ -11,6 +11,7 @@ import vocabulary import activity import ckan +import ckan.lib.dictization __all__ = ['tag_table', 'package_tag_table', 'Tag', 'PackageTag', 'PackageTagRevision', 'package_tag_revision_table', @@ -215,7 +216,6 @@ def activity_stream_detail(self, activity_id, activity_type): return None # Return an 'added tag' or 'removed tag' activity. - import ckan.lib.dictization import ckan.model c = {'model': ckan.model} d = {'tag': ckan.lib.dictization.table_dictize(self.tag, c), From 0b4a9007bd5b98882cfb3ccc239a138085cbebb6 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:16:53 +0100 Subject: [PATCH 014/109] more cleans for model/group_extra --- ckan/model/group_extra.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/ckan/model/group_extra.py b/ckan/model/group_extra.py index 33b54dcec3a..138b94f1ea4 100644 --- a/ckan/model/group_extra.py +++ b/ckan/model/group_extra.py @@ -1,24 +1,24 @@ -from meta import * import vdm.sqlalchemy +from sqlalchemy import orm, types, Column, Table, ForeignKey -from core import * -from package import * -from group import * +import group +import meta +import core import types as _types import domain_object __all__ = ['GroupExtra', 'group_extra_table', 'GroupExtraRevision'] -group_extra_table = Table('group_extra', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('group_id', UnicodeText, ForeignKey('group.id')), - Column('key', UnicodeText), +group_extra_table = Table('group_extra', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('group_id', types.UnicodeText, ForeignKey('group.id')), + Column('key', types.UnicodeText), Column('value', _types.JsonType), ) vdm.sqlalchemy.make_table_stateful(group_extra_table) -group_extra_revision_table = make_revisioned_table(group_extra_table) +group_extra_revision_table = core.make_revisioned_table(group_extra_table) class GroupExtra(vdm.sqlalchemy.RevisionedObjectMixin, @@ -26,8 +26,8 @@ class GroupExtra(vdm.sqlalchemy.RevisionedObjectMixin, domain_object.DomainObject): pass -mapper(GroupExtra, group_extra_table, properties={ - 'group': orm.relation(Group, +meta.mapper(GroupExtra, group_extra_table, properties={ + 'group': orm.relation(group.Group, backref=orm.backref('_extras', collection_class=orm.collections.attribute_mapped_collection(u'key'), cascade='all, delete, delete-orphan', @@ -38,8 +38,8 @@ class GroupExtra(vdm.sqlalchemy.RevisionedObjectMixin, extension=[vdm.sqlalchemy.Revisioner(group_extra_revision_table),], ) -vdm.sqlalchemy.modify_base_object_mapper(GroupExtra, Revision, State) -GroupExtraRevision = vdm.sqlalchemy.create_object_version(mapper, GroupExtra, +vdm.sqlalchemy.modify_base_object_mapper(GroupExtra, core.Revision, core.State) +GroupExtraRevision = vdm.sqlalchemy.create_object_version(meta.mapper, GroupExtra, group_extra_revision_table) def _create_extra(key, value): @@ -48,6 +48,6 @@ def _create_extra(key, value): import vdm.sqlalchemy.stateful _extras_active = vdm.sqlalchemy.stateful.DeferredProperty('_extras', vdm.sqlalchemy.stateful.StatefulDict, base_modifier=lambda x: x.get_as_of()) -setattr(Group, 'extras_active', _extras_active) -Group.extras = vdm.sqlalchemy.stateful.OurAssociationProxy('extras_active', 'value', +setattr(group.Group, 'extras_active', _extras_active) +group.Group.extras = vdm.sqlalchemy.stateful.OurAssociationProxy('extras_active', 'value', creator=_create_extra) From c5f44bc5707268aa58d0c11121147cf661384ee2 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:18:32 +0100 Subject: [PATCH 015/109] more cleans for model/license --- ckan/model/license.py | 352 +++++++++++++++++++++--------------------- 1 file changed, 177 insertions(+), 175 deletions(-) diff --git a/ckan/model/license.py b/ckan/model/license.py index f717113ba92..d6490927435 100644 --- a/ckan/model/license.py +++ b/ckan/model/license.py @@ -1,9 +1,11 @@ -from pylons import config import datetime import urllib2 -from ckan.lib.helpers import json import re +from pylons import config + +import ckan.lib.helpers as h + class License(object): """Domain object for a license.""" @@ -55,7 +57,7 @@ def load_licenses(self, license_url): msg = "Couldn't connect to licenses service %r: %s" % (license_url, inst) raise Exception, msg try: - license_data = json.loads(response_body) + license_data = h.json.loads(response_body) except Exception, inst: msg = "Couldn't read response from licenses service %r: %s" % (response_body, inst) raise Exception, inst @@ -81,7 +83,7 @@ def __getitem__(self, key, default=Exception): def get(self, key, default=None): return self.__getitem__(key, default=default) - + def keys(self): return [license.id for license in self.licenses] @@ -90,7 +92,7 @@ def values(self): def items(self): return [(license.id, license) for license in self.licenses] - + def __iter__(self): return iter(self.keys()) @@ -99,204 +101,204 @@ def __len__(self): default_license_list = [ { - "domain_content": False, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "notspecified", - "is_generic": True, - "is_okd_compliant": False, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "License Not Specified", + "domain_content": False, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "notspecified", + "is_generic": True, + "is_okd_compliant": False, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "License Not Specified", "url": "" - }, + }, { - "domain_content": False, - "domain_data": True, - "domain_software": False, - "family": "", - "id": "odc-pddl", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Open Data Commons Public Domain Dedication and Licence (PDDL)", + "domain_content": False, + "domain_data": True, + "domain_software": False, + "family": "", + "id": "odc-pddl", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Open Data Commons Public Domain Dedication and Licence (PDDL)", "url": "http://www.opendefinition.org/licenses/odc-pddl" - }, + }, { - "domain_content": False, - "domain_data": True, - "domain_software": False, - "family": "", - "id": "odc-odbl", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Open Data Commons Open Database License (ODbL)", + "domain_content": False, + "domain_data": True, + "domain_software": False, + "family": "", + "id": "odc-odbl", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Open Data Commons Open Database License (ODbL)", "url": "http://www.opendefinition.org/licenses/odc-odbl" - }, + }, { - "domain_content": False, - "domain_data": True, - "domain_software": False, - "family": "", - "id": "odc-by", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Open Data Commons Attribution License", + "domain_content": False, + "domain_data": True, + "domain_software": False, + "family": "", + "id": "odc-by", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Open Data Commons Attribution License", "url": "http://www.opendefinition.org/licenses/odc-by" - }, + }, { - "domain_content": True, - "domain_data": True, - "domain_software": False, - "family": "", - "id": "cc-zero", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Creative Commons CCZero", + "domain_content": True, + "domain_data": True, + "domain_software": False, + "family": "", + "id": "cc-zero", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Creative Commons CCZero", "url": "http://www.opendefinition.org/licenses/cc-zero" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "cc-by", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Creative Commons Attribution", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "cc-by", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Creative Commons Attribution", "url": "http://www.opendefinition.org/licenses/cc-by" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "cc-by-sa", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Creative Commons Attribution Share-Alike", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "cc-by-sa", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Creative Commons Attribution Share-Alike", "url": "http://www.opendefinition.org/licenses/cc-by-sa" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "gfdl", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "GNU Free Documentation License", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "gfdl", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "GNU Free Documentation License", "url": "http://www.opendefinition.org/licenses/gfdl" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "other-open", - "is_generic": True, - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Other (Open)", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "other-open", + "is_generic": True, + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Other (Open)", "url": "" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "other-pd", - "is_generic": True, - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Other (Public Domain)", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "other-pd", + "is_generic": True, + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Other (Public Domain)", "url": "" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "other-at", - "is_generic": True, - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Other (Attribution)", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "other-at", + "is_generic": True, + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Other (Attribution)", "url": "" - }, + }, { - "domain_content": True, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "uk-ogl", - "is_okd_compliant": True, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "UK Open Government Licence (OGL)", + "domain_content": True, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "uk-ogl", + "is_okd_compliant": True, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "UK Open Government Licence (OGL)", "url": "http://reference.data.gov.uk/id/open-government-licence" - }, + }, { - "domain_content": False, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "cc-nc", - "is_okd_compliant": False, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Creative Commons Non-Commercial (Any)", + "domain_content": False, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "cc-nc", + "is_okd_compliant": False, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Creative Commons Non-Commercial (Any)", "url": "http://creativecommons.org/licenses/by-nc/2.0/" - }, + }, { - "domain_content": False, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "other-nc", - "is_generic": True, - "is_okd_compliant": False, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Other (Non-Commercial)", + "domain_content": False, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "other-nc", + "is_generic": True, + "is_okd_compliant": False, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Other (Non-Commercial)", "url": "" - }, + }, { - "domain_content": False, - "domain_data": False, - "domain_software": False, - "family": "", - "id": "other-closed", - "is_generic": True, - "is_okd_compliant": False, - "is_osi_compliant": False, - "maintainer": "", - "status": "active", - "title": "Other (Not Open)", + "domain_content": False, + "domain_data": False, + "domain_software": False, + "family": "", + "id": "other-closed", + "is_generic": True, + "is_okd_compliant": False, + "is_osi_compliant": False, + "maintainer": "", + "status": "active", + "title": "Other (Not Open)", "url": "" } ] From 323049f8f0de56d9252a700f237890a79b415e76 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:19:34 +0100 Subject: [PATCH 016/109] more cleans for model/misc --- ckan/model/misc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ckan/model/misc.py b/ckan/model/misc.py index 260e3a2a106..94adf7f79f4 100644 --- a/ckan/model/misc.py +++ b/ckan/model/misc.py @@ -2,7 +2,6 @@ Contains miscelaneous set of DB-related functions """ -import re _special_characters = '%_' def escape_sql_like_special_characters(term, escape='\\'): @@ -14,4 +13,3 @@ def escape_sql_like_special_characters(term, escape='\\'): for ch in escape + _special_characters: term = term.replace(ch, escape+ch) return term - From 8406f4ed2c7c0f777aca3db5637ea9623ee40619 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:25:16 +0100 Subject: [PATCH 017/109] more cleans for model/modification --- ckan/model/modification.py | 45 +++++++++++++++----------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/ckan/model/modification.py b/ckan/model/modification.py index 5d1719f9da6..1cd7b2ea6f9 100644 --- a/ckan/model/modification.py +++ b/ckan/model/modification.py @@ -1,24 +1,15 @@ import logging -from vdm.sqlalchemy import State +import ckan.plugins as plugins +import extension +import domain_object -from sqlalchemy.orm import object_session -from sqlalchemy.orm.interfaces import EXT_CONTINUE - -from ckan.plugins import SingletonPlugin, PluginImplementations, implements -from ckan.plugins import ISession, IDomainObjectModification, IResourceUrlChange - -from ckan.model.extension import ObserverNotifier -from ckan.model.domain_object import DomainObjectOperation - -from ckan.model.package import Package -from ckan.model.resource import ResourceGroup, Resource -from ckan.model.package_extra import PackageExtra -from ckan.model.tag import PackageTag +import package as _package +import resource log = logging.getLogger(__name__) -class DomainObjectModificationExtension(SingletonPlugin, ObserverNotifier): +class DomainObjectModificationExtension(plugins.SingletonPlugin, extension.ObserverNotifier): """ A domain object level interface to change notifications @@ -26,8 +17,8 @@ class DomainObjectModificationExtension(SingletonPlugin, ObserverNotifier): out with check_real_change. """ - implements(ISession, inherit=True) - observers = PluginImplementations(IDomainObjectModification) + plugins.implements(plugins.ISession, inherit=True) + observers = plugins.PluginImplementations(plugins.IDomainObjectModification) def before_commit(self, session): @@ -41,22 +32,22 @@ def before_commit(self, session): deleted = obj_cache['deleted'] for obj in set(new): - if isinstance(obj, (Package, Resource)): - self.notify(obj, DomainObjectOperation.new) + if isinstance(obj, (_package.Package, resource.Resource)): + self.notify(obj, domain_object.DomainObjectOperation.new) for obj in set(deleted): - if isinstance(obj, (Package, Resource)): - self.notify(obj, DomainObjectOperation.deleted) + if isinstance(obj, (_package.Package, resource.Resource)): + self.notify(obj, domain_object.DomainObjectOperation.deleted) for obj in set(changed): - if isinstance(obj, Resource): - self.notify(obj, DomainObjectOperation.changed) + if isinstance(obj, resource.Resource): + self.notify(obj, domain_object.DomainObjectOperation.changed) if getattr(obj, 'url_changed', False): - for item in PluginImplementations(IResourceUrlChange): + for item in plugins.PluginImplementations(plugins.IResourceUrlChange): item.notify(obj) - changed_pkgs = set(obj for obj in changed if isinstance(obj, Package)) + changed_pkgs = set(obj for obj in changed if isinstance(obj, _package.Package)) for obj in new | changed | deleted: - if not isinstance(obj, Package): + if not isinstance(obj, _package.Package): try: related_packages = obj.related_packages() except AttributeError: @@ -67,7 +58,7 @@ def before_commit(self, session): if package and package not in deleted | new: changed_pkgs.add(package) for obj in changed_pkgs: - self.notify(obj, DomainObjectOperation.changed) + self.notify(obj, domain_object.DomainObjectOperation.changed) def notify(self, entity, operation): From 368c5e9ae2b5d60d6d27d5544eb53eafcaf2e961 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:36:28 +0100 Subject: [PATCH 018/109] more cleans for model/package --- ckan/model/modification.py | 1 - ckan/model/package.py | 82 ++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/ckan/model/modification.py b/ckan/model/modification.py index 1cd7b2ea6f9..ad48b4f023e 100644 --- a/ckan/model/modification.py +++ b/ckan/model/modification.py @@ -3,7 +3,6 @@ import ckan.plugins as plugins import extension import domain_object - import package as _package import resource diff --git a/ckan/model/package.py b/ckan/model/package.py index 17d869df3c8..8cd682d0466 100644 --- a/ckan/model/package.py +++ b/ckan/model/package.py @@ -1,23 +1,22 @@ import datetime -from time import gmtime from calendar import timegm -from operator import attrgetter import logging logger = logging.getLogger(__name__) -from sqlalchemy.sql import select, and_, union, expression, or_, desc +from sqlalchemy.sql import select, and_, union, or_ from sqlalchemy.orm import eagerload_all from sqlalchemy import types, Column, Table -from pylons import config, session, c, request -from meta import metadata, Session +from pylons import config import vdm.sqlalchemy -from core import make_revisioned_table, Revision, State -from license import License, LicenseRegister +import meta +import core +import license as _license import types as _types import domain_object import ckan.misc -from activity import Activity, ActivityDetail +import activity +import ckan.lib.dictization __all__ = ['Package', 'package_table', 'package_revision_table', 'PACKAGE_NAME_MAX_LENGTH', 'PACKAGE_NAME_MIN_LENGTH', @@ -28,7 +27,7 @@ PACKAGE_VERSION_MAX_LENGTH = 100 ## Our Domain Object Tables -package_table = Table('package', metadata, +package_table = Table('package', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', types.Unicode(PACKAGE_NAME_MAX_LENGTH), nullable=False, unique=True), @@ -46,7 +45,7 @@ vdm.sqlalchemy.make_table_stateful(package_table) -package_revision_table = make_revisioned_table(package_table) +package_revision_table = core.make_revisioned_table(package_table) ## ------------------- ## Mapped classes @@ -66,12 +65,12 @@ def __init__(self, **kw): @classmethod def search_by_name(cls, text_query): text_query = text_query - return Session.query(cls).filter(cls.name.contains(text_query.lower())) + return meta.Session.query(cls).filter(cls.name.contains(text_query.lower())) @classmethod def get(cls, reference): '''Returns a package object referenced by its id or name.''' - query = Session.query(cls).filter(cls.id==reference) + query = meta.Session.query(cls).filter(cls.id==reference) query = query.options(eagerload_all('package_tags.tag')) query = query.options(eagerload_all('resource_groups_all.resources_all')) pkg = query.first() @@ -121,7 +120,7 @@ def get_resource_identity(resource_obj_or_dict): assert isinstance(res_dict, dict) id = res_dict.get('id') if id: - res = Session.query(model.Resource).autoflush(autoflush).get(id) + res = meta.Session.query(model.Resource).autoflush(autoflush).get(id) if res: index_to_res[i] = res else: @@ -145,7 +144,7 @@ def get_resource_identity(resource_obj_or_dict): for key in set(res_dict.keys()) & set(('id', 'position')): del res_dict[key] res = model.Resource(**res_dict) - model.Session.add(res) + meta.Session.add(res) new_res_list.append(res) self.resource_groups[0].resources = new_res_list @@ -168,7 +167,7 @@ def add_tag(self, tag): return else: package_tag = model.PackageTag(self, tag) - model.Session.add(package_tag) + meta.Session.add(package_tag) def add_tags(self, tags): for tag in tags: @@ -209,7 +208,7 @@ def get_tags(self, vocab=None): """ import ckan.model as model - query = model.Session.query(model.Tag) + query = meta.Session.query(model.Tag) query = query.join(model.PackageTagRevision) query = query.filter(model.PackageTagRevision.tag_id == model.Tag.id) query = query.filter(model.PackageTagRevision.package_id == self.id) @@ -226,12 +225,12 @@ def get_tags(self, vocab=None): def remove_tag(self, tag): import ckan.model as model - query = model.Session.query(model.PackageTag) + query = meta.Session.query(model.PackageTag) query = query.filter(model.PackageTag.package_id == self.id) query = query.filter(model.PackageTag.tag_id == tag.id) package_tag = query.one() package_tag.delete() - model.Session.commit() + meta.Session.commit() def isopen(self): if self.license and self.license.isopen(): @@ -282,7 +281,6 @@ def add_relationship(self, type_, related_package, comment=u''): Raises KeyError if the type_ is invalid. ''' import package_relationship - from ckan import model if type_ in package_relationship.PackageRelationship.get_forward_types(): subject = self object_ = related_package @@ -300,7 +298,7 @@ def add_relationship(self, type_, related_package, comment=u''): rel = rels[0] if comment: rel.comment=comment - if rel.state == model.State.DELETED: + if rel.state == core.State.DELETED: rel.undelete() else: rel = package_relationship.PackageRelationship( @@ -308,7 +306,7 @@ def add_relationship(self, type_, related_package, comment=u''): object=object_, type=type_, comment=comment) - Session.add(rel) + meta.Session.add(rel) return rel def get_relationships(self, with_package=None, type=None, active=True, @@ -325,13 +323,13 @@ def get_relationships(self, with_package=None, type=None, active=True, forward_filters.append(PackageRelationship.object==with_package) reverse_filters.append(PackageRelationship.subject==with_package) if active: - forward_filters.append(PackageRelationship.state==State.ACTIVE) - reverse_filters.append(PackageRelationship.state==State.ACTIVE) + forward_filters.append(PackageRelationship.state==core.State.ACTIVE) + reverse_filters.append(PackageRelationship.state==core.State.ACTIVE) if type: forward_filters.append(PackageRelationship.type==type) reverse_type = PackageRelationship.reverse_type(type) reverse_filters.append(PackageRelationship.type==reverse_type) - q = Session.query(PackageRelationship) + q = meta.Session.query(PackageRelationship) if direction == 'both': q = q.filter(or_( and_(*forward_filters), @@ -369,19 +367,19 @@ def get_relationships_printable(self): # e.g. 'gary' is a child of 'mum', looking for 'bert' is a child of 'mum' # i.e. for each 'child_of' type relationship ... for rel_as_subject in self.get_relationships(direction='forward'): - if rel_as_subject.state != State.ACTIVE: + if rel_as_subject.state != core.State.ACTIVE: continue # ... parent is the object parent_pkg = rel_as_subject.object # Now look for the parent's other relationships as object ... for parent_rel_as_object in parent_pkg.get_relationships(direction='reverse'): - if parent_rel_as_object.state != State.ACTIVE: + if parent_rel_as_object.state != core.State.ACTIVE: continue # and check children child_pkg = parent_rel_as_object.subject if (child_pkg != self and parent_rel_as_object.type == rel_as_subject.type and - child_pkg.state == State.ACTIVE): + child_pkg.state == core.State.ACTIVE): type_printable = PackageRelationship.inferred_types_printable['sibling'] rel_list.append((child_pkg, type_printable, None)) return sorted(list(set(rel_list))) @@ -391,7 +389,7 @@ def get_relationships_printable(self): @classmethod def get_license_register(cls): if not hasattr(cls, '_license_register'): - cls._license_register = LicenseRegister() + cls._license_register = _license.LicenseRegister() return cls._license_register @classmethod @@ -410,7 +408,7 @@ def get_license(self): return license def set_license(self, license): - if type(license) == License: + if type(license) == _license.License: self.license_id = license.id elif type(license) == dict: self.license_id = license['id'] @@ -441,11 +439,11 @@ def all_related_revisions(self): for class_ in [ResourceGroup, Resource, PackageExtra, PackageTag]: rev_class = class_.__revision_class__ if class_ == Resource: - q = Session.query(rev_class).join('continuity', + q = meta.Session.query(rev_class).join('continuity', 'resource_group') obj_revisions = q.filter(ResourceGroup.package_id == self.id).all() else: - obj_revisions = Session.query(rev_class).filter_by(package_id=self.id).all() + obj_revisions = meta.Session.query(rev_class).filter_by(package_id=self.id).all() for obj_rev in obj_revisions: if not results.has_key(obj_rev.revision): results[obj_rev.revision] = [] @@ -476,16 +474,16 @@ def diff(self, to_revision=None, from_revision=None): obj_rev_class = obj_class.__revision_class__ # Query for object revisions related to this package if obj_class == Resource: - obj_rev_query = Session.query(obj_rev_class).\ + obj_rev_query = meta.Session.query(obj_rev_class).\ join('continuity', 'resource_group').\ join('revision').\ filter(ResourceGroup.package_id == self.id).\ - order_by(Revision.timestamp.desc()) + order_by(core.Revision.timestamp.desc()) else: - obj_rev_query = Session.query(obj_rev_class).\ + obj_rev_query = meta.Session.query(obj_rev_class).\ filter_by(package_id=self.id).\ join('revision').\ - order_by(Revision.timestamp.desc()) + order_by(core.Revision.timestamp.desc()) # Columns to include in the diff cols_to_diff = obj_class.revisioned_fields() cols_to_diff.remove('id') @@ -550,7 +548,7 @@ def metadata_modified(self): # Use current connection because we might be in a 'before_commit' of # a SessionExtension - only by using the current connection can we get # at the newly created revision etc. objects. - conn = model.Session.connection() + conn = meta.Session.connection() result = conn.execute(query).fetchone() if result: @@ -567,7 +565,7 @@ def is_in_group(self, group): def get_groups(self, group_type=None, capacity=None): import ckan.model as model if '_groups' not in self.__dict__: - self._groups = model.Session.query(model.Group).\ + self._groups = meta.Session.query(model.Group).\ join(model.Member, model.Member.group_id == model.Group.id and \ model.Member.table_name == 'package' ).\ join(model.Package, model.Package.id == model.Member.table_id).\ @@ -584,7 +582,7 @@ def get_groups(self, group_type=None, capacity=None): @property def metadata_created(self): import ckan.model as model - q = model.Session.query(model.PackageRevision.revision_timestamp)\ + q = meta.Session.query(model.PackageRevision.revision_timestamp)\ .filter(model.PackageRevision.id == self.id)\ .order_by(model.PackageRevision.revision_timestamp.asc()) ts = q.first() @@ -612,7 +610,6 @@ def get_fields(core_only=False, fields_to_ignore=None): def activity_stream_item(self, activity_type, revision, user_id): import ckan.model - import ckan.lib.dictization import ckan.logic assert activity_type in ("new", "changed"), ( str(activity_type)) @@ -622,7 +619,7 @@ def activity_stream_item(self, activity_type, revision, user_id): # a 'changed' package activity. We detect this and change it to a # 'deleted' activity. if activity_type == 'changed' and self.state == u'deleted': - if ckan.model.Session.query(ckan.model.Activity).filter_by( + if meta.Session.query(activity.Activity).filter_by( object_id=self.id, activity_type='deleted').all(): # A 'deleted' activity for this object has already been emitted # FIXME: What if the object was deleted and then activated @@ -635,7 +632,7 @@ def activity_stream_item(self, activity_type, revision, user_id): try: d = {'package': ckan.lib.dictization.table_dictize(self, context={'model': ckan.model})} - return Activity(user_id, self.id, revision.id, + return activity.Activity(user_id, self.id, revision.id, "%s package" % activity_type, d) except ckan.logic.NotFound: # This happens if this package is being purged and therefore has no @@ -646,7 +643,6 @@ def activity_stream_item(self, activity_type, revision, user_id): def activity_stream_detail(self, activity_id, activity_type): import ckan.model - import ckan.lib.dictization # Handle 'deleted' objects. # When the user marks a package as deleted this comes through here as @@ -657,5 +653,5 @@ def activity_stream_detail(self, activity_id, activity_type): package_dict = ckan.lib.dictization.table_dictize(self, context={'model':ckan.model}) - return ActivityDetail(activity_id, self.id, u"Package", activity_type, + return activity.ActivityDetail(activity_id, self.id, u"Package", activity_type, {'package': package_dict }) From 3e242ea9ec7f2326272e7b0e49befd80544fed66 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:41:27 +0100 Subject: [PATCH 019/109] more cleans for model/package_extras --- ckan/model/package_extra.py | 39 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/ckan/model/package_extra.py b/ckan/model/package_extra.py index 7b37a0ce3cb..7ec1fa6d921 100644 --- a/ckan/model/package_extra.py +++ b/ckan/model/package_extra.py @@ -1,25 +1,29 @@ -from meta import * import vdm.sqlalchemy +import vdm.sqlalchemy.stateful +from sqlalchemy import orm, types, Column, Table, ForeignKey -from core import * -from package import * -from ckan.model import extension +import meta +import core +import package as _package +import extension import domain_object import types as _types +import ckan.lib.dictization +import activity __all__ = ['PackageExtra', 'package_extra_table', 'PackageExtraRevision', 'extra_revision_table'] -package_extra_table = Table('package_extra', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), +package_extra_table = Table('package_extra', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), # NB: only (package, key) pair is unique - Column('package_id', UnicodeText, ForeignKey('package.id')), - Column('key', UnicodeText), + Column('package_id', types.UnicodeText, ForeignKey('package.id')), + Column('key', types.UnicodeText), Column('value', _types.JsonType), ) vdm.sqlalchemy.make_table_stateful(package_extra_table) -extra_revision_table= make_revisioned_table(package_extra_table) +extra_revision_table= core.make_revisioned_table(package_extra_table) class PackageExtra(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, @@ -30,8 +34,6 @@ def related_packages(self): def activity_stream_detail(self, activity_id, activity_type): import ckan.model as model - import ckan.model.activity as activity - import ckan.lib.dictization # Handle 'deleted' extras. # When the user marks an extra as deleted this comes through here as a @@ -45,14 +47,14 @@ def activity_stream_detail(self, activity_id, activity_type): return activity.ActivityDetail(activity_id, self.id, u"PackageExtra", activity_type, {'package_extra': data_dict}) -mapper(PackageExtra, package_extra_table, properties={ - 'package': orm.relation(Package, +meta.mapper(PackageExtra, package_extra_table, properties={ + 'package': orm.relation(_package.Package, backref=orm.backref('_extras', collection_class=orm.collections.attribute_mapped_collection(u'key'), cascade='all, delete, delete-orphan', ), ), - 'package_no_state': orm.relation(Package, + 'package_no_state': orm.relation(_package.Package, backref=orm.backref('extras_list', cascade='all, delete, delete-orphan', ), @@ -64,8 +66,8 @@ def activity_stream_detail(self, activity_id, activity_type): ], ) -vdm.sqlalchemy.modify_base_object_mapper(PackageExtra, Revision, State) -PackageExtraRevision= vdm.sqlalchemy.create_object_version(mapper, PackageExtra, +vdm.sqlalchemy.modify_base_object_mapper(PackageExtra, core.Revision, core.State) +PackageExtraRevision= vdm.sqlalchemy.create_object_version(meta.mapper, PackageExtra, extra_revision_table) PackageExtraRevision.related_packages = lambda self: [self.continuity.package] @@ -73,10 +75,9 @@ def activity_stream_detail(self, activity_id, activity_type): def _create_extra(key, value): return PackageExtra(key=unicode(key), value=value) -import vdm.sqlalchemy.stateful _extras_active = vdm.sqlalchemy.stateful.DeferredProperty('_extras', vdm.sqlalchemy.stateful.StatefulDict, base_modifier=lambda x: x.get_as_of()) -setattr(Package, 'extras_active', _extras_active) -Package.extras = vdm.sqlalchemy.stateful.OurAssociationProxy('extras_active', 'value', +setattr(_package.Package, 'extras_active', _extras_active) +_package.Package.extras = vdm.sqlalchemy.stateful.OurAssociationProxy('extras_active', 'value', creator=_create_extra) From 7274549108ec75ab7a60ffaf3fd94f890577b8c0 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 14:45:47 +0100 Subject: [PATCH 020/109] more cleans for model/package_mapping --- ckan/model/package_mapping.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ckan/model/package_mapping.py b/ckan/model/package_mapping.py index ad98e490492..8ddfd2c04fe 100644 --- a/ckan/model/package_mapping.py +++ b/ckan/model/package_mapping.py @@ -1,13 +1,15 @@ -from meta import * import vdm.sqlalchemy +from sqlalchemy.orm import relation + import tag -from core import * -from package import * -from ckan.model import extension +import meta +import core +import package as _package +import extension __all__ = ['PackageRevision'] -mapper(Package, package_table, properties={ +meta.mapper(_package.Package, _package.package_table, properties={ # delete-orphan on cascade does NOT work! # Why? Answer: because of way SQLAlchemy/our code works there are points # where PackageTag object is created *and* flushed but does not yet have @@ -19,15 +21,15 @@ cascade='all, delete', #, delete-orphan', ), }, - order_by=package_table.c.name, - extension=[vdm.sqlalchemy.Revisioner(package_revision_table), + order_by=_package.package_table.c.name, + extension=[vdm.sqlalchemy.Revisioner(_package.package_revision_table), extension.PluginMapperExtension(), ], ) -vdm.sqlalchemy.modify_base_object_mapper(Package, Revision, State) -PackageRevision = vdm.sqlalchemy.create_object_version(mapper, Package, - package_revision_table) +vdm.sqlalchemy.modify_base_object_mapper(_package.Package, core.Revision, core.State) +PackageRevision = vdm.sqlalchemy.create_object_version(meta.mapper, _package.Package, + _package.package_revision_table) def related_packages(self): return [self.continuity] From 478058d52ad5b25f3faec213a63d58f3682e2afd Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:09:41 +0100 Subject: [PATCH 021/109] more cleans for model/package_relationship plus __init__ --- ckan/model/__init__.py | 30 ++++++++++--------- ckan/model/package_relationship.py | 46 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index 1e14b8d4ca2..ac5295a5b86 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -32,6 +32,10 @@ log = logging.getLogger(__name__) +## CLEANUP related stuff to stop breakages +Session = meta.Session +engine_is_sqlite = meta.engine_is_sqlite + # set up in init_model after metadata is bound version_table = None @@ -45,7 +49,7 @@ def init_model(engine): # sqlalchemy migrate version table import sqlalchemy.exc try: - version_table = Table('migrate_version', metadata, autoload=True) + version_table = Table('migrate_version', meta.metadata, autoload=True) except sqlalchemy.exc.NoSuchTableError: pass @@ -81,12 +85,12 @@ def init_db(self): self.tables_created_and_initialised = True def clean_db(self): - metadata = MetaData(self.metadata.bind) + meta.metadata = MetaData(self.metadata.bind) with warnings.catch_warnings(): warnings.filterwarnings('ignore', '.*(reflection|tsvector).*') - metadata.reflect() + meta.metadata.reflect() - metadata.drop_all() + meta.metadata.drop_all() self.tables_created_and_initialised = False def init_const_data(self): @@ -96,8 +100,8 @@ def init_const_data(self): PSEUDO_USER__VISITOR): if not User.by_name(username): user = User(name=username) - Session.add(user) - Session.flush() # so that these objects can be used + meta.Session.add(user) + meta.Session.flush() # so that these objects can be used # straight away init_authz_const_data() @@ -105,11 +109,11 @@ def init_configuration_data(self): '''Default configuration, for when CKAN is first used out of the box. This state may be subsequently configured by the user.''' init_authz_configuration_data() - if Session.query(Revision).count() == 0: + if meta.Session.query(Revision).count() == 0: rev = Revision() rev.author = 'system' rev.message = u'Initialising the Repository' - Session.add(rev) + meta.Session.add(rev) self.commit_and_remove() def create_db(self): @@ -185,9 +189,9 @@ def upgrade_db(self, version=None): ##pprint.pprint(getDiffOfModelAgainstDatabase(self.metadata, self.metadata.bind).colDiffs) def are_tables_created(self): - metadata = MetaData(self.metadata.bind) - metadata.reflect() - return bool(metadata.tables) + meta.metadata = MetaData(self.metadata.bind) + meta.metadata.reflect() + return bool(meta.metadata.tables) def purge_revision(self, revision, leave_record=False): '''Purge all changes associated with a revision. @@ -249,7 +253,7 @@ def purge_revision(self, revision, leave_record=False): self.commit_and_remove() -repo = Repository(metadata, Session, +repo = Repository(meta.metadata, meta.Session, versioned_objects=[Package, PackageTag, Resource, ResourceGroup, PackageExtra, Member, Group] ) @@ -280,7 +284,7 @@ def _get_groups(self): # could set this up directly on the mapper? def _get_revision_user(self): username = unicode(self.author) - user = Session.query(User).filter_by(name=username).first() + user = meta.Session.query(User).filter_by(name=username).first() return user Revision.packages = property(_get_packages) diff --git a/ckan/model/package_relationship.py b/ckan/model/package_relationship.py index e7a024dbaa3..5f1e2edb4a5 100644 --- a/ckan/model/package_relationship.py +++ b/ckan/model/package_relationship.py @@ -1,8 +1,9 @@ import vdm.sqlalchemy +from sqlalchemy import orm, types, Column, Table, ForeignKey -from meta import * -from core import * -from package import * +import meta +import core +import package as _package import types as _types import domain_object @@ -15,17 +16,16 @@ def _(txt): return txt - -package_relationship_table = Table('package_relationship', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('subject_package_id', UnicodeText, ForeignKey('package.id')), - Column('object_package_id', UnicodeText, ForeignKey('package.id')), - Column('type', UnicodeText), - Column('comment', UnicodeText), +package_relationship_table = Table('package_relationship', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('subject_package_id', types.UnicodeText, ForeignKey('package.id')), + Column('object_package_id', types.UnicodeText, ForeignKey('package.id')), + Column('type', types.UnicodeText), + Column('comment', types.UnicodeText), ) vdm.sqlalchemy.make_table_stateful(package_relationship_table) -package_relationship_revision_table = make_revisioned_table(package_relationship_table) +package_relationship_revision_table = core.make_revisioned_table(package_relationship_table) class PackageRelationship(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, @@ -56,8 +56,7 @@ class PackageRelationship(vdm.sqlalchemy.RevisionedObjectMixin, {'sibling':_('has sibling %s')} def __str__(self): - from ckan import model - return '<%sPackageRelationship %s %s %s>' % ("*" if self.active != model.State.ACTIVE else "", + return '<%sPackageRelationship %s %s %s>' % ("*" if self.active != core.State.ACTIVE else "", self.subject.name, self.type, self.object.name) def __repr__(self): @@ -89,7 +88,7 @@ def as_tuple(self, package): of the given package with the object package object. e.g. rel.as_tuple(warandpeace) gives (u'depends_on', annakarenina) meaning warandpeace depends_on annakarenina.''' - assert isinstance(package, Package), package + assert isinstance(package, _package.Package), package if self.subject == package: type_str = self.type other_package = self.object @@ -97,17 +96,18 @@ def as_tuple(self, package): type_str = self.forward_to_reverse_type(self.type) other_package = self.subject else: - raise InputError('Package %s is not in this relationship: %s' % \ + # FIXME do we want a more specific error + raise Exception('Package %s is not in this relationship: %s' % \ (package, self)) return (type_str, other_package) @classmethod def by_subject(cls, package): - return Session.query(cls).filter(cls.subject_package_id==package.id) + return meta.Session.query(cls).filter(cls.subject_package_id==package.id) @classmethod def by_object(cls, package): - return Session.query(cls).filter(cls.object_package_id==package.id) + return meta.Session.query(cls).filter(cls.object_package_id==package.id) @classmethod def get_forward_types(cls): @@ -158,16 +158,16 @@ def make_type_printable(cls, type_): return cls.types_printable[i][j] raise TypeError, type_ -mapper(PackageRelationship, package_relationship_table, properties={ - 'subject':relation(Package, primaryjoin=\ - package_relationship_table.c.subject_package_id==Package.id, +meta.mapper(PackageRelationship, package_relationship_table, properties={ + 'subject':orm.relation(_package.Package, primaryjoin=\ + package_relationship_table.c.subject_package_id==_package.Package.id, backref='relationships_as_subject'), - 'object':relation(Package, primaryjoin=package_relationship_table.c.object_package_id==Package.id, + 'object':orm.relation(_package.Package, primaryjoin=package_relationship_table.c.object_package_id==_package.Package.id, backref='relationships_as_object'), }, extension = [vdm.sqlalchemy.Revisioner(package_relationship_revision_table)] ) -vdm.sqlalchemy.modify_base_object_mapper(PackageRelationship, Revision, State) +vdm.sqlalchemy.modify_base_object_mapper(PackageRelationship, core.Revision, core.State) PackageRelationshipRevision = vdm.sqlalchemy.create_object_version( - mapper, PackageRelationship, package_relationship_revision_table) + meta.mapper, PackageRelationship, package_relationship_revision_table) From caccaea2d7f265c7663475a60226d0b7e05cb921 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:11:40 +0100 Subject: [PATCH 022/109] more cleans for model/rating --- ckan/model/rating.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ckan/model/rating.py b/ckan/model/rating.py index 44fb027d712..fda91b41dd9 100644 --- a/ckan/model/rating.py +++ b/ckan/model/rating.py @@ -1,33 +1,34 @@ import datetime -from meta import * -from core import * -from package import * +from sqlalchemy import orm, types, Column, Table, ForeignKey + +import meta +import package as _package import user import domain_object import types as _types __all__ = ['Rating'] -rating_table = Table('rating', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('user_id', UnicodeText, ForeignKey('user.id')), - Column('user_ip_address', UnicodeText), # alternative to user_id if not logged in - Column('package_id', UnicodeText, ForeignKey('package.id')), - Column('rating', Float), - Column('created', DateTime, default=datetime.datetime.now), +rating_table = Table('rating', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('user_id', types.UnicodeText, ForeignKey('user.id')), + Column('user_ip_address', types.UnicodeText), # alternative to user_id if not logged in + Column('package_id', types.UnicodeText, ForeignKey('package.id')), + Column('rating', types.Float), + Column('created', types.DateTime, default=datetime.datetime.now), ) class Rating(domain_object.DomainObject): pass -mapper(Rating, rating_table, +meta.mapper(Rating, rating_table, properties={ 'user': orm.relation(user.User, backref=orm.backref('ratings', cascade='all, delete, delete-orphan' )), - 'package': orm.relation(Package, + 'package': orm.relation(_package.Package, backref=orm.backref('ratings', cascade='all, delete, delete-orphan' )), From 1fa31fe8e564c35203df22cda7d7408eb296b8d5 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:17:04 +0100 Subject: [PATCH 023/109] more cleans for model/resource --- ckan/model/resource.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/ckan/model/resource.py b/ckan/model/resource.py index 3abbf5bff0b..f20673ef9d0 100644 --- a/ckan/model/resource.py +++ b/ckan/model/resource.py @@ -1,13 +1,15 @@ +import datetime from sqlalchemy.util import OrderedDict from sqlalchemy.ext.orderinglist import ordering_list from sqlalchemy import orm from pylons import config import vdm.sqlalchemy +from sqlalchemy import types, Column, Table, ForeignKey, and_ -from meta import * +import meta +import core +import package as _package import types as _types -from core import * -from package import * from ckan.model import extension from ckan.model.activity import ActivityDetail import domain_object @@ -27,7 +29,7 @@ ##formally package_resource resource_table = Table( - 'resource', metadata, + 'resource', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('resource_group_id', types.UnicodeText, ForeignKey('resource_group.id')), Column('url', types.UnicodeText, nullable=False), @@ -51,7 +53,7 @@ ) resource_group_table = Table( - 'resource_group', metadata, + 'resource_group', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('package_id', types.UnicodeText, ForeignKey('package.id')), Column('label', types.UnicodeText), @@ -60,10 +62,10 @@ ) vdm.sqlalchemy.make_table_stateful(resource_table) -resource_revision_table = make_revisioned_table(resource_table) +resource_revision_table = core.make_revisioned_table(resource_table) vdm.sqlalchemy.make_table_stateful(resource_group_table) -resource_group_revision_table = make_revisioned_table(resource_group_table) +resource_group_revision_table = core.make_revisioned_table(resource_group_table) class Resource(vdm.sqlalchemy.RevisionedObjectMixin, vdm.sqlalchemy.StatefulObjectMixin, @@ -113,7 +115,7 @@ def as_dict(self, core_columns_only=False): @classmethod def get(cls, reference): '''Returns a resource object referenced by its name or id.''' - query = Session.query(ResourceRevision).filter(ResourceRevision.id==reference) + query = meta.Session.query(ResourceRevision).filter(ResourceRevision.id==reference) query = query.filter(and_( ResourceRevision.state == u'active', ResourceRevision.current == True )) @@ -206,7 +208,7 @@ def get_extra_columns(cls): ## Mappers -mapper(Resource, resource_table, properties={ +meta.mapper(Resource, resource_table, properties={ 'resource_group':orm.relation(ResourceGroup, # all resources including deleted # formally package_resources_all @@ -224,8 +226,8 @@ def get_extra_columns(cls): ) -mapper(ResourceGroup, resource_group_table, properties={ - 'package':orm.relation(Package, +meta.mapper(ResourceGroup, resource_group_table, properties={ + 'package':orm.relation(_package.Package, # all resources including deleted backref=orm.backref('resource_groups_all', cascade='all, delete, delete-orphan', @@ -241,13 +243,13 @@ def get_extra_columns(cls): ## VDM -vdm.sqlalchemy.modify_base_object_mapper(Resource, Revision, State) +vdm.sqlalchemy.modify_base_object_mapper(Resource, core.Revision, core.State) ResourceRevision = vdm.sqlalchemy.create_object_version( - mapper, Resource, resource_revision_table) + meta.mapper, Resource, resource_revision_table) -vdm.sqlalchemy.modify_base_object_mapper(ResourceGroup, Revision, State) +vdm.sqlalchemy.modify_base_object_mapper(ResourceGroup, core.Revision, core.State) ResourceGroupRevision = vdm.sqlalchemy.create_object_version( - mapper, ResourceGroup, resource_group_revision_table) + meta.mapper, ResourceGroup, resource_group_revision_table) ResourceGroupRevision.related_packages = lambda self: [self.continuity.package] ResourceRevision.related_packages = lambda self: [self.continuity.resouce_group.package] @@ -277,7 +279,7 @@ def resource_identifier(obj): return obj.id -add_stateful_m21(Package, 'resource_groups', 'resource_groups_all', +add_stateful_m21(_package.Package, 'resource_groups', 'resource_groups_all', resource_identifier) add_stateful_m21(ResourceGroup, 'resources', 'resources_all', resource_identifier) From f6ac49adaddd86450382af0212bbb71d13ff2abb Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:20:16 +0100 Subject: [PATCH 024/109] more cleans for model/task_status --- ckan/model/task_status.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ckan/model/task_status.py b/ckan/model/task_status.py index 1fbc410226b..84126fb685b 100644 --- a/ckan/model/task_status.py +++ b/ckan/model/task_status.py @@ -1,6 +1,6 @@ -import sqlalchemy as sa -from meta import * -from core import * +from sqlalchemy import types, Column, Table, UniqueConstraint + +import meta import types as _types import domain_object # se overwrite datetime somewhere in our importing @@ -8,24 +8,24 @@ __all__ = ['TaskStatus', 'task_status_table'] -task_status_table = Table('task_status', metadata, - Column('id', UnicodeText, primary_key=True, default=_types.make_uuid), - Column('entity_id', UnicodeText, nullable=False), - Column('entity_type', UnicodeText, nullable=False), - Column('task_type', UnicodeText, nullable=False), - Column('key', UnicodeText, nullable=False), - Column('value', UnicodeText, nullable=False), - Column('state', UnicodeText), - Column('error', UnicodeText), - Column('last_updated', DateTime, default=datetime.now), - sa.UniqueConstraint('entity_id', 'task_type', 'key') +task_status_table = Table('task_status', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('entity_id', types.UnicodeText, nullable=False), + Column('entity_type', types.UnicodeText, nullable=False), + Column('task_type', types.UnicodeText, nullable=False), + Column('key', types.UnicodeText, nullable=False), + Column('value', types.UnicodeText, nullable=False), + Column('state', types.UnicodeText), + Column('error', types.UnicodeText), + Column('last_updated', types.DateTime, default=datetime.now), + UniqueConstraint('entity_id', 'task_type', 'key') ) class TaskStatus(domain_object.DomainObject): @classmethod def get(cls, reference): '''Returns a task status object referenced by its id.''' - query = Session.query(cls).filter(cls.id==reference) + query = meta.Session.query(cls).filter(cls.id==reference) return query.first() -mapper(TaskStatus, task_status_table) +meta.mapper(TaskStatus, task_status_table) From 345255f2138d6e2c6b0b91717e4f138fdee18b78 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:23:43 +0100 Subject: [PATCH 025/109] more cleans for model/vocabulary --- ckan/model/vocabulary.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ckan/model/vocabulary.py b/ckan/model/vocabulary.py index c853fd638e2..f7f48676978 100644 --- a/ckan/model/vocabulary.py +++ b/ckan/model/vocabulary.py @@ -1,25 +1,24 @@ -## IMPORTS FIXED -import sqlalchemy as sa +from sqlalchemy import types, Column, Table import meta -import types +import types as _types import tag import domain_object VOCABULARY_NAME_MIN_LENGTH = 2 VOCABULARY_NAME_MAX_LENGTH = 100 -vocabulary_table = meta.Table( +vocabulary_table = Table( 'vocabulary', meta.metadata, - sa.Column('id', sa.types.UnicodeText, primary_key=True, default=types.make_uuid), - sa.Column('name', sa.types.Unicode(VOCABULARY_NAME_MAX_LENGTH), nullable=False, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('name', types.Unicode(VOCABULARY_NAME_MAX_LENGTH), nullable=False, unique=True), ) class Vocabulary(domain_object.DomainObject): def __init__(self, name): - self.id = types.make_uuid() + self.id = _types.make_uuid() self.name = name @classmethod From 55d0decbb4ff8400311d9508dbf6326d14b13dec Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 29 Mar 2012 15:31:59 +0100 Subject: [PATCH 026/109] more cleans for model/meta --- ckan/model/meta.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ckan/model/meta.py b/ckan/model/meta.py index 38f8ec24d64..909efb032e9 100644 --- a/ckan/model/meta.py +++ b/ckan/model/meta.py @@ -2,22 +2,14 @@ from paste.deploy.converters import asbool from pylons import config """SQLAlchemy Metadata and Session object""" -from sqlalchemy import MetaData, __version__ as sqav +from sqlalchemy import MetaData, and_ from sqlalchemy.orm import class_mapper from sqlalchemy.orm import scoped_session, sessionmaker import sqlalchemy.orm as orm from sqlalchemy.orm.session import SessionExtension -# TODO: remove these imports from here and put them in client model modules -from sqlalchemy import Column, MetaData, Table, types, ForeignKey -from sqlalchemy import or_, and_ -from sqlalchemy.types import * -from sqlalchemy.orm import scoped_session, sessionmaker, create_session -from sqlalchemy.orm import relation, backref - -from ckan.model import extension - -from ckan.lib.activity import DatasetActivitySessionExtension +import extension +import ckan.lib.activity class CkanCacheExtension(SessionExtension): ''' This extension checks what tables have been affected by @@ -139,7 +131,7 @@ def after_rollback(self, session): extension=[CkanCacheExtension(), CkanSessionExtension(), extension.PluginSessionExtension(), - DatasetActivitySessionExtension()], + ckan.lib.activity.DatasetActivitySessionExtension()], )) create_local_session = sessionmaker( @@ -149,7 +141,7 @@ def after_rollback(self, session): extension=[CkanCacheExtension(), CkanSessionExtension(), extension.PluginSessionExtension(), - DatasetActivitySessionExtension()], + ckan.lib.activity.DatasetActivitySessionExtension()], ) #mapper = Session.mapper From 9de3cb89077304043f39b3148d36addfa280931d Mon Sep 17 00:00:00 2001 From: Toby Date: Fri, 30 Mar 2012 10:31:33 +0100 Subject: [PATCH 027/109] cleanups to model/__init__ --- ckan/model/__init__.py | 143 +++++++++++++++++++++++++++++++++-------- 1 file changed, 117 insertions(+), 26 deletions(-) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index ac5295a5b86..351067ba5b5 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -2,33 +2,31 @@ import warnings import logging -from pylons import config -from sqlalchemy import MetaData, __version__ as sqav -from sqlalchemy.schema import Index -from paste.deploy.converters import asbool +import vdm.sqlalchemy +from vdm.sqlalchemy.base import SQLAlchemySession +from sqlalchemy import MetaData, __version__ as sqav, Table import meta #from domain_object import DomainObjectOperation -from core import * -from package import * -from tag import * -from package_mapping import * -from user import user_table, User -from authorization_group import * -from group import * -from group_extra import * -from authz import * -from package_extra import * -from resource import * -from rating import * -from package_relationship import * -from task_status import * -from vocabulary import * -from activity import * -from term_translation import * +import core +import package +import tag +import package_mapping +import user +import authorization_group +import group +import group_extra +import authz +import package_extra +import resource +import rating +import package_relationship +import task_status +import vocabulary +import activity +import term_translation import ckan.migration -from ckan.lib.helpers import OrderedDict, datetime_to_date_str -from vdm.sqlalchemy.base import SQLAlchemySession +import ckan.lib.helpers as h log = logging.getLogger(__name__) @@ -36,6 +34,99 @@ Session = meta.Session engine_is_sqlite = meta.engine_is_sqlite +System = core.System +Revision = core.Revision +State = core.State +revision_table = core.revision_table + +AuthorizationGroup = authorization_group.AuthorizationGroup +AuthorizationGroupUser = authorization_group.AuthorizationGroupUser +add_user_to_authorization_group = authorization_group.add_user_to_authorization_group + +Activity = activity.Activity +ActivityDetail = activity.ActivityDetail + +NotRealUserException = authz.NotRealUserException +Enum = authz.Enum +Action = authz.Action +Role = authz.Role +RoleAction = authz.RoleAction +UserObjectRole = authz.UserObjectRole +PackageRole = authz.PackageRole +GroupRole = authz.GroupRole +AuthorizationGroupRole = authz.AuthorizationGroupRole +SystemRole = authz.SystemRole +PSEUDO_USER__VISITOR = authz.PSEUDO_USER__VISITOR +PSEUDO_USER__LOGGED_IN = authz.PSEUDO_USER__LOGGED_IN +init_authz_const_data = authz.init_authz_const_data +init_authz_configuration_data = authz.init_authz_configuration_data +add_user_to_role = authz.add_user_to_role +add_authorization_group_to_role = authz.add_authorization_group_to_role +setup_user_roles = authz.setup_user_roles +setup_default_user_roles = authz.setup_default_user_roles +give_all_packages_default_user_roles = authz.give_all_packages_default_user_roles +user_has_role = authz.user_has_role +remove_user_from_role = authz.remove_user_from_role +remove_authorization_group_from_role = authz.remove_authorization_group_from_role +clear_user_roles = authz.clear_user_roles + +Member = group.Member +Group = group.Group +member_revision_table = group.member_revision_table +group_table = group.group_table +GroupRevision = group.GroupRevision + +GroupExtra = group_extra.GroupExtra + +Package = package.Package +PACKAGE_NAME_MIN_LENGTH = package.PACKAGE_NAME_MIN_LENGTH +PACKAGE_NAME_MAX_LENGTH = package.PACKAGE_NAME_MAX_LENGTH +PACKAGE_VERSION_MAX_LENGTH = package.PACKAGE_VERSION_MAX_LENGTH +package_table = package.package_table +package_revision_table = package.package_revision_table + +PackageExtra = package_extra.PackageExtra +PackageExtraRevision = package_extra.PackageExtraRevision +package_extra_table = package_extra.package_extra_table +extra_revision_table = package_extra.extra_revision_table + +PackageRelationship = package_relationship.PackageRelationship +package_relationship_table = package_relationship.package_relationship_table +package_relationship_revision_table = package_relationship.package_relationship_revision_table + +PackageRevision = package_mapping.PackageRevision + +Rating = rating.Rating + +Resource = resource.Resource +ResourceGroup = resource.ResourceGroup +ResourceRevision = resource.ResourceRevision +DictProxy = resource.DictProxy +resource_group_table = resource.resource_group_table +resource_table = resource.resource_table +resource_revision_table = resource.resource_revision_table + +Tag = tag.Tag +PackageTag = tag.PackageTag +PackageTagRevision = tag.PackageTagRevision +MAX_TAG_LENGTH = tag.MAX_TAG_LENGTH +MIN_TAG_LENGTH = tag.MIN_TAG_LENGTH +tag_table = tag.tag_table +package_tag_table = tag.package_tag_table +package_tag_revision_table = tag.package_tag_revision_table + +TaskStatus = task_status.TaskStatus + +User = user.User +user_table = user.user_table + +Vocabulary = vocabulary.Vocabulary +VOCABULARY_NAME_MAX_LENGTH = vocabulary.VOCABULARY_NAME_MAX_LENGTH +VOCABULARY_NAME_MIN_LENGTH = vocabulary.VOCABULARY_NAME_MIN_LENGTH + +term_translation_table = term_translation.term_translation_table + + # set up in init_model after metadata is bound version_table = None @@ -292,13 +383,13 @@ def _get_revision_user(self): Revision.user = property(_get_revision_user) def revision_as_dict(revision, include_packages=True, include_groups=True,ref_package_by='name'): - revision_dict = OrderedDict(( + revision_dict = h.OrderedDict(( ('id', revision.id), - ('timestamp', datetime_to_date_str(revision.timestamp)), + ('timestamp', h.datetime_to_date_str(revision.timestamp)), ('message', revision.message), ('author', revision.author), ('approved_timestamp', - datetime_to_date_str(revision.approved_timestamp) \ + h.datetime_to_date_str(revision.approved_timestamp) \ if revision.approved_timestamp else None), )) if include_packages: From 8bdff050fb867335c39780be4c1cf33a2263d113 Mon Sep 17 00:00:00 2001 From: Toby Date: Fri, 20 Apr 2012 19:50:29 +0100 Subject: [PATCH 028/109] add fns to model to fix failing tests --- ckan/model/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index 2c1b71ad247..8f891cdc5db 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -41,7 +41,9 @@ AuthorizationGroup = authorization_group.AuthorizationGroup AuthorizationGroupUser = authorization_group.AuthorizationGroupUser +user_in_authorization_group = authorization_group.user_in_authorization_group add_user_to_authorization_group = authorization_group.add_user_to_authorization_group +remove_user_from_authorization_group =authorization_group.remove_user_from_authorization_group Activity = activity.Activity ActivityDetail = activity.ActivityDetail From 1487690df9cf154d1e7437be764f7702e7f5cca3 Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 25 Apr 2012 17:58:41 +0100 Subject: [PATCH 029/109] merge fix --- ckan/model/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index a3431fcdb10..f339db18fa0 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -221,13 +221,8 @@ def init_configuration_data(self): rev = Revision() rev.author = 'system' rev.message = u'Initialising the Repository' -<<<<<<< HEAD - meta.Session.add(rev) - self.commit_and_remove() -======= Session.add(rev) self.commit_and_remove() ->>>>>>> master def create_db(self): '''Ensures tables, const data and some default config is created. From c78a6d3df705e9e47c3104d2132e269405f44a8d Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 25 Apr 2012 17:59:18 +0100 Subject: [PATCH 030/109] cleanup model/tracking.py --- ckan/model/tracking.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/ckan/model/tracking.py b/ckan/model/tracking.py index 384f84bb299..b2871b317aa 100644 --- a/ckan/model/tracking.py +++ b/ckan/model/tracking.py @@ -1,21 +1,23 @@ -from meta import * -from domain_object import DomainObject - -tracking_summary_table = Table('tracking_summary', metadata, - Column('url', UnicodeText, primary_key=True, nullable=False), - Column('package_id', UnicodeText), - Column('tracking_type', Unicode(10), nullable=False), - Column('count', Integer, nullable=False), - Column('running_total', Integer, nullable=False), - Column('recent_views', Integer, nullable=False), - Column('tracking_date', DateTime), +from sqlalchemy import types, Column, Table + +import meta +import domain_object + +tracking_summary_table = Table('tracking_summary', meta.metadata, + Column('url', types.UnicodeText, primary_key=True, nullable=False), + Column('package_id', types.UnicodeText), + Column('tracking_type', types.Unicode(10), nullable=False), + Column('count', types.Integer, nullable=False), + Column('running_total', types.Integer, nullable=False), + Column('recent_views', types.Integer, nullable=False), + Column('tracking_date', types.DateTime), ) -class TrackingSummary(DomainObject): +class TrackingSummary(domain_object.DomainObject): @classmethod def get_for_package(cls, package_id): - obj = Session.query(cls).autoflush(False) + obj = meta.Session.query(cls).autoflush(False) obj = obj.filter_by(package_id=package_id) data = obj.order_by('tracking_date desc').first() if data: @@ -27,7 +29,7 @@ def get_for_package(cls, package_id): @classmethod def get_for_resource(cls, url): - obj = Session.query(cls).autoflush(False) + obj = meta.Session.query(cls).autoflush(False) data = obj.filter_by(url=url).order_by('tracking_date desc').first() if data: return {'total' : data.running_total, @@ -35,4 +37,4 @@ def get_for_resource(cls, url): return {'total' : 0, 'recent' : 0} -mapper(TrackingSummary, tracking_summary_table) +meta.mapper(TrackingSummary, tracking_summary_table) From 6a728d6334ef4a1fa03e1307fb0f73b280c1bdc6 Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 25 Apr 2012 18:52:42 +0100 Subject: [PATCH 031/109] fixup related model --- ckan/model/__init__.py | 6 +++++ ckan/model/related.py | 52 +++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index f339db18fa0..f32096e904a 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -21,6 +21,7 @@ import resource import tracking import rating +import related import package_relationship import task_status import vocabulary @@ -133,6 +134,11 @@ tracking_summary_table = tracking.tracking_summary_table TrackingSummary = tracking.TrackingSummary +Related = related.Related +RelatedDataset= related.RelatedDataset +related_dataset_table = related.related_dataset_table +related_table = related.related_table + # set up in init_model after metadata is bound version_table = None diff --git a/ckan/model/related.py b/ckan/model/related.py index df2d5890317..60967ad2cb0 100644 --- a/ckan/model/related.py +++ b/ckan/model/related.py @@ -1,35 +1,35 @@ -import os import datetime import meta -import sqlalchemy as sa -from core import DomainObject -from types import make_uuid +from sqlalchemy import orm +from sqlalchemy import types, Column, Table, ForeignKey, and_ +import domain_object +import types as _types from package import Package -related_table = meta.Table('related',meta.metadata, - meta.Column('id', meta.UnicodeText, primary_key=True, default=make_uuid), - meta.Column('type', meta.UnicodeText, default=u'idea'), - meta.Column('title', meta.UnicodeText), - meta.Column('description', meta.UnicodeText), - meta.Column('image_url', meta.UnicodeText), - meta.Column('url', meta.UnicodeText), - meta.Column('created', meta.DateTime, default=datetime.datetime.now), - meta.Column('owner_id', meta.UnicodeText), +related_table = Table('related',meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('type', types.UnicodeText, default=u'idea'), + Column('title', types.UnicodeText), + Column('description', types.UnicodeText), + Column('image_url', types.UnicodeText), + Column('url', types.UnicodeText), + Column('created', types.DateTime, default=datetime.datetime.now), + Column('owner_id', types.UnicodeText), ) -related_dataset_table = meta.Table('related_dataset', meta.metadata, - meta.Column('id', meta.UnicodeText, primary_key=True, default=make_uuid), - meta.Column('dataset_id', meta.UnicodeText, meta.ForeignKey('package.id'), - nullable=False), - meta.Column('related_id', meta.UnicodeText, meta.ForeignKey('related.id'), nullable=False), - meta.Column('status', meta.UnicodeText, default=u'active'), +related_dataset_table = Table('related_dataset', meta.metadata, + Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), + Column('dataset_id', types.UnicodeText, ForeignKey('package.id'), + nullable=False), + Column('related_id', types.UnicodeText, ForeignKey('related.id'), nullable=False), + Column('status', types.UnicodeText, default=u'active'), ) -class RelatedDataset(DomainObject): +class RelatedDataset(domain_object.DomainObject): pass -class Related(DomainObject): +class Related(domain_object.DomainObject): @classmethod def get(cls, id): @@ -60,13 +60,13 @@ def deactivate(self, package): # relation be for 'active' related objects. For non-active states # the caller will have to use get_for_dataset() in Related. meta.mapper(RelatedDataset, related_dataset_table, properties={ - 'related': meta.relation(Related), - 'dataset': meta.relation(Package) + 'related': orm.relation(Related), + 'dataset': orm.relation(Package) }) meta.mapper(Related, related_table, properties={ -'datasets': meta.relation(Package, - backref=meta.backref('related'), +'datasets': orm.relation(Package, + backref=orm.backref('related'), secondary=related_dataset_table, - secondaryjoin=sa.and_(related_dataset_table.c.dataset_id==Package.id, + secondaryjoin=and_(related_dataset_table.c.dataset_id==Package.id, RelatedDataset.status=='active')) }) From eedae4f6cc4b2b16af227d338bc5b0aeb600377b Mon Sep 17 00:00:00 2001 From: amercader Date: Wed, 25 Apr 2012 19:40:24 +0100 Subject: [PATCH 032/109] [release-v1.7] Update version numbers --- ckan/__init__.py | 2 +- pip-requirements.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ckan/__init__.py b/ckan/__init__.py index b4333195546..36c8f372104 100644 --- a/ckan/__init__.py +++ b/ckan/__init__.py @@ -1,4 +1,4 @@ -__version__ = '1.6.1b' +__version__ = '1.7b' __description__ = 'Comprehensive Knowledge Archive Network (CKAN) Software' __long_description__ = \ '''CKAN software provides a hub for datasets. The flagship site running CKAN diff --git a/pip-requirements.txt b/pip-requirements.txt index 4460f149f3e..be8a66ca393 100644 --- a/pip-requirements.txt +++ b/pip-requirements.txt @@ -5,11 +5,11 @@ # # pip install --ignore-installed -r pip-requirements.txt --e git+https://github.com/okfn/ckan@release-v1.6.1#egg=ckan +-e git+https://github.com/okfn/ckan@release-v1.7#egg=ckan # CKAN dependencies --r https://github.com/okfn/ckan/raw/release-v1.6.1/requires/lucid_conflict.txt --r https://github.com/okfn/ckan/raw/release-v1.6.1/requires/lucid_present.txt --r https://github.com/okfn/ckan/raw/release-v1.6.1/requires/lucid_missing.txt +-r https://github.com/okfn/ckan/raw/release-v1.7/requires/lucid_conflict.txt +-r https://github.com/okfn/ckan/raw/release-v1.7/requires/lucid_present.txt +-r https://github.com/okfn/ckan/raw/release-v1.7/requires/lucid_missing.txt # NOTE: Developers, please do not edit this file. Changes should go in the # appropriate files in the `requires' directory. From fc58cb03376954cb16d350c43665c625f2270346 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 26 Apr 2012 10:26:55 +0100 Subject: [PATCH 033/109] minor import cleanup meta.py --- ckan/model/meta.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ckan/model/meta.py b/ckan/model/meta.py index 909efb032e9..a3939fee158 100644 --- a/ckan/model/meta.py +++ b/ckan/model/meta.py @@ -1,10 +1,9 @@ import datetime + from paste.deploy.converters import asbool from pylons import config """SQLAlchemy Metadata and Session object""" from sqlalchemy import MetaData, and_ -from sqlalchemy.orm import class_mapper -from sqlalchemy.orm import scoped_session, sessionmaker import sqlalchemy.orm as orm from sqlalchemy.orm.session import SessionExtension @@ -81,7 +80,7 @@ def before_commit(self, session): if not hasattr(obj, '__revision_class__'): continue revision_cls = obj.__revision_class__ - revision_table = class_mapper(revision_cls).mapped_table + revision_table = orm.class_mapper(revision_cls).mapped_table ## when a normal active transaction happens if 'pending' not in obj.state: ### this is asql statement as we do not want it in object cache @@ -124,7 +123,7 @@ def after_rollback(self, session): # SQLAlchemy database engine. Updated by model.init_model() engine = None -Session = scoped_session(sessionmaker( +Session = orm.scoped_session(orm.sessionmaker( autoflush=False, autocommit=False, expire_on_commit=False, @@ -134,7 +133,7 @@ def after_rollback(self, session): ckan.lib.activity.DatasetActivitySessionExtension()], )) -create_local_session = sessionmaker( +create_local_session = orm.sessionmaker( autoflush=False, autocommit=False, expire_on_commit=False, From b73e1ccd963a6e3d425168d0bc7704c92731fb74 Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 26 Apr 2012 12:00:20 +0100 Subject: [PATCH 034/109] more model cleanups --- ckan/model/__init__.py | 11 ++++++++++- ckan/model/authorization_group.py | 4 ++++ ckan/model/authz.py | 15 +++++++++++++-- ckan/model/core.py | 3 +++ ckan/model/domain_object.py | 2 ++ ckan/model/group.py | 8 +++----- ckan/model/group_extra.py | 2 +- ckan/model/license.py | 4 ++-- ckan/model/meta.py | 3 +++ ckan/model/modification.py | 2 ++ ckan/model/package_relationship.py | 3 +++ ckan/model/related.py | 14 +++++++++----- ckan/model/resource.py | 18 +++++++++--------- ckan/model/tag.py | 6 +++--- ckan/model/task_status.py | 3 +-- ckan/model/tracking.py | 2 ++ ckan/model/types.py | 11 +++++++---- 17 files changed, 77 insertions(+), 34 deletions(-) diff --git a/ckan/model/__init__.py b/ckan/model/__init__.py index f32096e904a..b8d6fbe9dcb 100644 --- a/ckan/model/__init__.py +++ b/ckan/model/__init__.py @@ -50,6 +50,8 @@ Activity = activity.Activity ActivityDetail = activity.ActivityDetail +#activity_table +#activity_detail_table NotRealUserException = authz.NotRealUserException Enum = authz.Enum @@ -80,8 +82,12 @@ member_revision_table = group.member_revision_table group_table = group.group_table GroupRevision = group.GroupRevision +#MemberRevision +#member_table GroupExtra = group_extra.GroupExtra +#group_extra_table +#GroupExtraRevision Package = package.Package PACKAGE_NAME_MIN_LENGTH = package.PACKAGE_NAME_MIN_LENGTH @@ -106,10 +112,12 @@ Resource = resource.Resource ResourceGroup = resource.ResourceGroup ResourceRevision = resource.ResourceRevision -DictProxy = resource.DictProxy +#DictProxy = resource.DictProxy resource_group_table = resource.resource_group_table resource_table = resource.resource_table resource_revision_table = resource.resource_revision_table +#ResourceGroupRevision +#resource_group_revision_table Tag = tag.Tag PackageTag = tag.PackageTag @@ -121,6 +129,7 @@ package_tag_revision_table = tag.package_tag_revision_table TaskStatus = task_status.TaskStatus +#task_status_table User = user.User user_table = user.user_table diff --git a/ckan/model/authorization_group.py b/ckan/model/authorization_group.py index 2933570652e..460f3dfd25c 100644 --- a/ckan/model/authorization_group.py +++ b/ckan/model/authorization_group.py @@ -7,6 +7,10 @@ import types as _types import domain_object +__all__ = ['AuthorizationGroup', 'AuthorizationGroupUser', + 'user_in_authorization_group', 'add_user_to_authorization_group', + 'remove_user_from_authorization_group'] + authorization_group_table = Table('authorization_group', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('name', types.UnicodeText), diff --git a/ckan/model/authz.py b/ckan/model/authz.py index 5ceb544f6d6..e7afb9ffaec 100644 --- a/ckan/model/authz.py +++ b/ckan/model/authz.py @@ -2,6 +2,8 @@ doc/authorization.rst. ''' +import simplejson as json + from sqlalchemy import orm, types, Column, Table, ForeignKey from pylons import config @@ -13,7 +15,16 @@ import authorization_group as auth_group import domain_object import types as _types -import ckan.lib.helpers as h + +__all__ = ['NotRealUserException', 'Enum', 'Action', 'Role', 'RoleAction', + 'UserObjectRole', 'PackageRole', 'GroupRole', + 'AuthorizationGroupRole', 'SystemRole', 'PSEUDO_USER__VISITOR', + 'PSEUDO_USER__LOGGED_IN', 'init_authz_const_data', + 'init_authz_configuration_data', 'add_user_to_role', + 'add_authorization_group_to_role', 'setup_user_roles', + 'setup_default_user_roles', 'give_all_packages_default_user_roles', + 'user_has_role', 'remove_user_from_role', + 'remove_authorization_group_from_role', 'clear_user_roles'] PSEUDO_USER__LOGGED_IN = u'logged_in' PSEUDO_USER__VISITOR = u'visitor' @@ -412,7 +423,7 @@ def _get_default_user_roles(_domain_object): if user_roles_json is None: user_roles_str = default_default_user_roles[obj_type] else: - user_roles_str = h.json.loads(user_roles_json) if user_roles_json else {} + user_roles_str = json.loads(user_roles_json) if user_roles_json else {} unknown_keys = set(user_roles_str.keys()) - set(('visitor', 'logged_in')) assert not unknown_keys, 'Auth config for %r has unknown key %r' % \ (_domain_object, unknown_keys) diff --git a/ckan/model/core.py b/ckan/model/core.py index a0ece1ae088..ec861da1a6c 100644 --- a/ckan/model/core.py +++ b/ckan/model/core.py @@ -6,6 +6,9 @@ import meta import domain_object + +__all__= ['System', 'Revision', 'State', 'revision_table'] + ## VDM-specific tables revision_table = vdm.sqlalchemy.make_revision_table(meta.metadata) revision_table.append_column(Column('approved_timestamp', DateTime)) diff --git a/ckan/model/domain_object.py b/ckan/model/domain_object.py index 890be94710d..ae47d81341a 100644 --- a/ckan/model/domain_object.py +++ b/ckan/model/domain_object.py @@ -7,6 +7,8 @@ import meta import core +__all__ = ['DomainObject'] + class Enum(set): '''Simple enumeration e.g. Animal = Enum("dog", "cat", "horse") diff --git a/ckan/model/group.py b/ckan/model/group.py index b1f13bf246b..b7df7fa54d1 100644 --- a/ckan/model/group.py +++ b/ckan/model/group.py @@ -1,18 +1,16 @@ import datetime from sqlalchemy import orm, types, Column, Table, ForeignKey +import vdm.sqlalchemy + import meta import core import package as _package import types as _types import domain_object -import vdm.sqlalchemy import user as _user -# FIXME why are we passing this around here? -package_revision_table = _package.package_revision_table - -__all__ = ['group_table', 'Group', 'package_revision_table', +__all__ = ['group_table', 'Group', 'Member', 'GroupRevision', 'MemberRevision', 'member_revision_table', 'member_table'] diff --git a/ckan/model/group_extra.py b/ckan/model/group_extra.py index 138b94f1ea4..23d3e38865c 100644 --- a/ckan/model/group_extra.py +++ b/ckan/model/group_extra.py @@ -1,4 +1,5 @@ import vdm.sqlalchemy +import vdm.sqlalchemy.stateful from sqlalchemy import orm, types, Column, Table, ForeignKey import group @@ -45,7 +46,6 @@ class GroupExtra(vdm.sqlalchemy.RevisionedObjectMixin, def _create_extra(key, value): return GroupExtra(key=unicode(key), value=value) -import vdm.sqlalchemy.stateful _extras_active = vdm.sqlalchemy.stateful.DeferredProperty('_extras', vdm.sqlalchemy.stateful.StatefulDict, base_modifier=lambda x: x.get_as_of()) setattr(group.Group, 'extras_active', _extras_active) diff --git a/ckan/model/license.py b/ckan/model/license.py index 9c297bf257b..dd0a9d3d4a7 100644 --- a/ckan/model/license.py +++ b/ckan/model/license.py @@ -1,11 +1,11 @@ import datetime import urllib2 import re +import simplejson as json from pylons import config from pylons.i18n import _ -import ckan.lib.helpers as h class License(object): """Domain object for a license.""" @@ -261,7 +261,7 @@ def load_licenses(self, license_url): msg = "Couldn't connect to licenses service %r: %s" % (license_url, inst) raise Exception, msg try: - license_data = h.json.loads(response_body) + license_data = json.loads(response_body) except Exception, inst: msg = "Couldn't read response from licenses service %r: %s" % (response_body, inst) raise Exception, inst diff --git a/ckan/model/meta.py b/ckan/model/meta.py index a3939fee158..df6eef84061 100644 --- a/ckan/model/meta.py +++ b/ckan/model/meta.py @@ -10,6 +10,9 @@ import extension import ckan.lib.activity +__all__ = ['Session', 'engine_is_sqlite'] + + class CkanCacheExtension(SessionExtension): ''' This extension checks what tables have been affected by database access and allows us to act on them. Currently this is diff --git a/ckan/model/modification.py b/ckan/model/modification.py index ad48b4f023e..3511ce51310 100644 --- a/ckan/model/modification.py +++ b/ckan/model/modification.py @@ -8,6 +8,8 @@ log = logging.getLogger(__name__) +__all__ = ['DomainObjectModificationExtension'] + class DomainObjectModificationExtension(plugins.SingletonPlugin, extension.ObserverNotifier): """ A domain object level interface to change notifications diff --git a/ckan/model/package_relationship.py b/ckan/model/package_relationship.py index 5f1e2edb4a5..503fc45b654 100644 --- a/ckan/model/package_relationship.py +++ b/ckan/model/package_relationship.py @@ -16,6 +16,9 @@ def _(txt): return txt +__all__ = ['PackageRelationship', 'package_relationship_table', + 'package_relationship_revision_table'] + package_relationship_table = Table('package_relationship', meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), Column('subject_package_id', types.UnicodeText, ForeignKey('package.id')), diff --git a/ckan/model/related.py b/ckan/model/related.py index 60967ad2cb0..e0287d5fb85 100644 --- a/ckan/model/related.py +++ b/ckan/model/related.py @@ -1,11 +1,15 @@ import datetime -import meta + from sqlalchemy import orm from sqlalchemy import types, Column, Table, ForeignKey, and_ + +import meta import domain_object import types as _types -from package import Package +import package as _package +__all__ = ['Related', 'RelatedDataset', 'related_dataset_table', + 'related_table'] related_table = Table('related',meta.metadata, Column('id', types.UnicodeText, primary_key=True, default=_types.make_uuid), @@ -61,12 +65,12 @@ def deactivate(self, package): # the caller will have to use get_for_dataset() in Related. meta.mapper(RelatedDataset, related_dataset_table, properties={ 'related': orm.relation(Related), - 'dataset': orm.relation(Package) + 'dataset': orm.relation(_package.Package) }) meta.mapper(Related, related_table, properties={ -'datasets': orm.relation(Package, +'datasets': orm.relation(_package.Package, backref=orm.backref('related'), secondary=related_dataset_table, - secondaryjoin=and_(related_dataset_table.c.dataset_id==Package.id, + secondaryjoin=and_(related_dataset_table.c.dataset_id==_package.Package.id, RelatedDataset.status=='active')) }) diff --git a/ckan/model/resource.py b/ckan/model/resource.py index 95df2cbe9ef..297e74136de 100644 --- a/ckan/model/resource.py +++ b/ckan/model/resource.py @@ -1,18 +1,22 @@ import datetime + from sqlalchemy.util import OrderedDict from sqlalchemy.ext.orderinglist import ordering_list from sqlalchemy import orm from pylons import config import vdm.sqlalchemy +import vdm.sqlalchemy.stateful from sqlalchemy import types, Column, Table, ForeignKey, and_ import meta import core import package as _package import types as _types -from ckan.model import extension -from ckan.model.activity import ActivityDetail +import extension +import activity import domain_object +import tracking as _tracking +import ckan.lib.dictization __all__ = ['Resource', 'resource_table', 'ResourceGroup', 'resource_group_table', @@ -111,8 +115,7 @@ def as_dict(self, core_columns_only=False): _dict[k] = v if self.resource_group and not core_columns_only: _dict["package_id"] = self.resource_group.package_id - import ckan.model as model - tracking = model.TrackingSummary.get_for_resource(self.url) + tracking = _tracking.TrackingSummary.get_for_resource(self.url) _dict['tracking_summary'] = tracking return _dict @@ -149,7 +152,6 @@ def related_packages(self): def activity_stream_detail(self, activity_id, activity_type): import ckan.model as model - import ckan.lib.dictization # Handle 'deleted' resources. # When the user marks a resource as deleted this comes through here as @@ -160,7 +162,7 @@ def activity_stream_detail(self, activity_id, activity_type): res_dict = ckan.lib.dictization.table_dictize(self, context={'model':model}) - return ActivityDetail(activity_id, self.id, u"Resource", activity_type, + return activity.ActivityDetail(activity_id, self.id, u"Resource", activity_type, {'resource': res_dict}) class ResourceGroup(vdm.sqlalchemy.RevisionedObjectMixin, @@ -258,13 +260,11 @@ def get_extra_columns(cls): ResourceGroupRevision.related_packages = lambda self: [self.continuity.package] ResourceRevision.related_packages = lambda self: [self.continuity.resouce_group.package] -import vdm.sqlalchemy.stateful # TODO: move this into vdm def add_stateful_m21(object_to_alter, m21_property_name, underlying_m21_attrname, identifier, **kwargs): - from sqlalchemy.orm import object_session def _f(obj_to_delete): - sess = object_session(obj_to_delete) + sess = orm.object_session(obj_to_delete) if sess: # for tests at least must support obj not being sqlalchemy sess.expunge(obj_to_delete) diff --git a/ckan/model/tag.py b/ckan/model/tag.py index 804ec393b48..c253dbde417 100644 --- a/ckan/model/tag.py +++ b/ckan/model/tag.py @@ -10,7 +10,7 @@ import domain_object import vocabulary import activity -import ckan +import ckan # this import is needed import ckan.lib.dictization __all__ = ['tag_table', 'package_tag_table', 'Tag', 'PackageTag', @@ -216,8 +216,8 @@ def activity_stream_detail(self, activity_id, activity_type): return None # Return an 'added tag' or 'removed tag' activity. - import ckan.model - c = {'model': ckan.model} + import ckan.model as model + c = {'model': model} d = {'tag': ckan.lib.dictization.table_dictize(self.tag, c), 'package': ckan.lib.dictization.table_dictize(self.package, c)} return activity.ActivityDetail( diff --git a/ckan/model/task_status.py b/ckan/model/task_status.py index 84126fb685b..2daad424f71 100644 --- a/ckan/model/task_status.py +++ b/ckan/model/task_status.py @@ -1,10 +1,9 @@ +from datetime import datetime from sqlalchemy import types, Column, Table, UniqueConstraint import meta import types as _types import domain_object -# se overwrite datetime somewhere in our importing -from datetime import datetime __all__ = ['TaskStatus', 'task_status_table'] diff --git a/ckan/model/tracking.py b/ckan/model/tracking.py index b2871b317aa..c10684960ea 100644 --- a/ckan/model/tracking.py +++ b/ckan/model/tracking.py @@ -3,6 +3,8 @@ import meta import domain_object +__all__ = ['tracking_summary_table', 'TrackingSummary'] + tracking_summary_table = Table('tracking_summary', meta.metadata, Column('url', types.UnicodeText, primary_key=True, nullable=False), Column('package_id', types.UnicodeText), diff --git a/ckan/model/types.py b/ckan/model/types.py index 54873e6f376..b6249633edf 100644 --- a/ckan/model/types.py +++ b/ckan/model/types.py @@ -2,11 +2,14 @@ import datetime import copy import uuid +import simplejson as json from sqlalchemy import types import meta -import ckan.lib.helpers as h + +__all__ = ['iso_date_to_datetime_for_sqlite', 'make_uuid', 'UuidType', + 'JsonType', 'JsonDictType'] def make_uuid(): return unicode(uuid.uuid4()) @@ -44,13 +47,13 @@ def process_bind_param(self, value, engine): return None else: # ensure_ascii=False => allow unicode but still need to convert - return unicode(h.json.dumps(value, ensure_ascii=False)) + return unicode(json.dumps(value, ensure_ascii=False)) def process_result_value(self, value, engine): if value is None: return {} else: - return h.json.loads(value) + return json.loads(value) def copy(self): return JsonType(self.impl.length) @@ -72,7 +75,7 @@ def process_bind_param(self, value, engine): if isinstance(value, basestring): return unicode(value) else: - return unicode(h.json.dumps(value, ensure_ascii=False)) + return unicode(json.dumps(value, ensure_ascii=False)) def copy(self): return JsonDictType(self.impl.length) From 70876ee31356a44d322d2af4afc053ad2fe13cd9 Mon Sep 17 00:00:00 2001 From: Ian Murray Date: Thu, 26 Apr 2012 11:49:28 +0100 Subject: [PATCH 035/109] [docs] A doc page for the data-viewer. --- doc/data-viewer.rst | 40 ++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 1 + 2 files changed, 41 insertions(+) create mode 100644 doc/data-viewer.rst diff --git a/doc/data-viewer.rst b/doc/data-viewer.rst new file mode 100644 index 00000000000..64f88171c83 --- /dev/null +++ b/doc/data-viewer.rst @@ -0,0 +1,40 @@ +=========== +Data Viewer +=========== + +CKAN's resource page can provide a preview of the resource's data if it is of +an appropriate format. If the data is available through the CKAN `DataStore +`_ API, or if the data is a ``csv`` or ``xls`` file; then `Recline's +`_ `Data Explorer`_ is used. If the data is +another webpage; a google doc; or an image; then it is embedded in an iframe +for viewing. Or if the data is text-like, then it's raw contents are +displayed. + +Data Explorer +============= + +The `Recline `_ +Data Explorer provides a rich, queryable view of the data. The data can be filtered, +faceted, graphed and mapped. Furthermore, the grid, graph or map can then be +embedded into your own site using the **Embed** button, and copying the provided +html snippet into your webpage. + +How It Works (Technically) +========================== + +The relevant code for setting up the data viewer is found in ``application.js``. + +All resources available through the `DataStore `_ API are +available for viewing through the `Data Explorer`_. using recline's +``elasticsearch`` backend. If the datastore is not available, and the filetype +is normalized to ``csv`` or ``xls``, then a dataproxy is used to attempt to view +the data (using recline's ``dataproxy`` backend). + +Embedding +--------- + +If a resource is viewable through the Data Explorer, then it is also embeddable +in third-party web pages. ``/dataset/{name}/resource/{resource_id}/embed`` +provides a stripped-down page containing the data explorer. The data +explorer's state is passed through using the url's query parameters. + diff --git a/doc/index.rst b/doc/index.rst index 601d4c7a5ff..735a64eee93 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -56,6 +56,7 @@ Publishing Datasets authorization publisher-profile geospatial + data-viewer The CKAN API ============ From 70a96a37d7d4d5bb0f7349bec088c70f7eda8577 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Thu, 26 Apr 2012 13:55:06 +0200 Subject: [PATCH 036/109] Fix a couple of strings that are causing a problem with Transifex --- ckan/templates/home/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ckan/templates/home/index.html b/ckan/templates/home/index.html index b2da98e6321..2bcc5f1a018 100644 --- a/ckan/templates/home/index.html +++ b/ckan/templates/home/index.html @@ -31,8 +31,8 @@

Find data

\ -
\ +
\ +
\ +

Hey there!

\ +

There\'s no graph here yet because we don\'t know what fields you\'d like to see plotted.

\ +

Please tell us by using the menu on the right and a graph will automatically appear.

\ +
\ +
\ \ ', + templateSeriesEditor: ' \ +
\ + \ +
\ + \ +
\ +
\ + ', events: { 'change form select': 'onEditorSubmit', - 'click .editor-add': 'addSeries', + 'click .editor-add': '_onAddSeries', 'click .action-remove-series': 'removeSeries', 'click .action-toggle-help': 'toggleHelp' }, @@ -807,7 +819,8 @@ my.Graph = Backbone.View.extend({ this.model.currentDocuments.bind('reset', this.redraw); var stateData = _.extend({ group: null, - series: [], + // so that at least one series chooser box shows up + series: [""], graphType: 'lines-and-points' }, options.state @@ -817,21 +830,45 @@ my.Graph = Backbone.View.extend({ }, render: function() { - htmls = $.mustache(this.template, this.model.toTemplateJSON()); + var self = this; + var tmplData = this.model.toTemplateJSON(); + var htmls = $.mustache(this.template, tmplData); $(this.el).html(htmls); - // now set a load of stuff up this.$graph = this.el.find('.panel.graph'); - // for use later when adding additional series - // could be simpler just to have a common template! - this.$seriesClone = this.el.find('.editor-series').clone(); - this._updateSeries(); + + // set up editor from state + if (this.state.get('graphType')) { + this._selectOption('.editor-type', this.state.get('graphType')); + } + if (this.state.get('group')) { + this._selectOption('.editor-group', this.state.get('group')); + } + _.each(this.state.get('series'), function(series, idx) { + self.addSeries(idx); + self._selectOption('.editor-series.js-series-' + idx, series); + }); return this; }, + // Private: Helper function to select an option from a select list + // + _selectOption: function(id,value){ + var options = this.el.find(id + ' select > option'); + if (options) { + options.each(function(opt){ + if (this.value == value) { + $(this).attr('selected','selected'); + return false; + } + }); + } + }, + onEditorSubmit: function(e) { var select = this.el.find('.editor-group select'); - $editor = this; - var series = this.$series.map(function () { + var $editor = this; + var $series = this.el.find('.editor-series select'); + var series = $series.map(function () { return $(this).val(); }); var updatedState = { @@ -870,10 +907,20 @@ my.Graph = Backbone.View.extend({ // } }, + // ### getGraphOptions + // + // Get options for Flot Graph + // // needs to be function as can depend on state + // + // @param typeId graphType id (lines, lines-and-points etc) getGraphOptions: function(typeId) { var self = this; // special tickformatter to show labels rather than numbers + // TODO: we should really use tickFormatter and 1 interval ticks if (and + // only if) x-axis values are non-numeric + // However, that is non-trivial to work out from a dataset (datasets may + // have no field type info). Thus at present we only do this for bars. var tickFormatter = function (val) { if (self.model.currentDocuments.models[val]) { var out = self.model.currentDocuments.models[val].get(self.state.attributes.group); @@ -886,20 +933,25 @@ my.Graph = Backbone.View.extend({ } return val; }; - // TODO: we should really use tickFormatter and 1 interval ticks if (and - // only if) x-axis values are non-numeric - // However, that is non-trivial to work out from a dataset (datasets may - // have no field type info). Thus at present we only do this for bars. - var options = { + + var xaxis = {}; + // check for time series on x-axis + if (this.model.fields.get(this.state.get('group')).get('type') === 'date') { + xaxis.mode = 'time'; + xaxis.timeformat = '%y-%b'; + } + var optionsPerGraphType = { lines: { - series: { - lines: { show: true } - } + series: { + lines: { show: true } + }, + xaxis: xaxis }, points: { series: { points: { show: true } }, + xaxis: xaxis, grid: { hoverable: true, clickable: true } }, 'lines-and-points': { @@ -907,6 +959,7 @@ my.Graph = Backbone.View.extend({ points: { show: true }, lines: { show: true } }, + xaxis: xaxis, grid: { hoverable: true, clickable: true } }, bars: { @@ -930,7 +983,7 @@ my.Graph = Backbone.View.extend({ } } }; - return options[typeId]; + return optionsPerGraphType[typeId]; }, setupTooltips: function() { @@ -987,8 +1040,15 @@ my.Graph = Backbone.View.extend({ _.each(this.state.attributes.series, function(field) { var points = []; _.each(self.model.currentDocuments.models, function(doc, index) { - var x = doc.get(self.state.attributes.group); - var y = doc.get(field); + var xfield = self.model.fields.get(self.state.attributes.group); + var x = doc.getFieldValue(xfield); + // time series + var isDateTime = xfield.get('type') === 'date'; + if (isDateTime) { + x = new Date(x); + } + var yfield = self.model.fields.get(field); + var y = doc.getFieldValue(yfield); if (typeof x === 'string') { x = index; } @@ -1006,23 +1066,25 @@ my.Graph = Backbone.View.extend({ // Public: Adds a new empty series select box to the editor. // - // All but the first select box will have a remove button that allows them - // to be removed. + // @param [int] idx index of this series in the list of series // // Returns itself. - addSeries: function (e) { - e.preventDefault(); - var element = this.$seriesClone.clone(), - label = element.find('label'), - index = this.$series.length; - - this.el.find('.editor-series-group').append(element); - this._updateSeries(); - label.append(' [Remove]'); - label.find('span').text(String.fromCharCode(this.$series.length + 64)); + addSeries: function (idx) { + var data = _.extend({ + seriesIndex: idx, + seriesName: String.fromCharCode(idx + 64 + 1), + }, this.model.toTemplateJSON()); + + var htmls = $.mustache(this.templateSeriesEditor, data); + this.el.find('.editor-series-group').append(htmls); return this; }, + _onAddSeries: function(e) { + e.preventDefault(); + this.addSeries(this.state.get('series').length); + }, + // Public: Removes a series list item from the editor. // // Also updates the labels of the remaining series elements. @@ -1030,26 +1092,12 @@ my.Graph = Backbone.View.extend({ e.preventDefault(); var $el = $(e.target); $el.parent().parent().remove(); - this._updateSeries(); - this.$series.each(function (index) { - if (index > 0) { - var labelSpan = $(this).prev().find('span'); - labelSpan.text(String.fromCharCode(index + 65)); - } - }); this.onEditorSubmit(); }, toggleHelp: function() { this.el.find('.editor-info').toggleClass('editor-hide-info'); }, - - // Private: Resets the series property to reference the select elements. - // - // Returns itself. - _updateSeries: function () { - this.$series = this.el.find('.editor-series select'); - } }); })(jQuery, recline.View); From 9a15502e2f036751efa0b49e27e25e7517dbb880 Mon Sep 17 00:00:00 2001 From: Toby Date: Mon, 30 Apr 2012 13:03:46 +0100 Subject: [PATCH 060/109] facets.html make comments template only --- ckan/templates/facets.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ckan/templates/facets.html b/ckan/templates/facets.html index f8c104bf5c2..001be8c79c3 100644 --- a/ckan/templates/facets.html +++ b/ckan/templates/facets.html @@ -5,7 +5,7 @@ py:strip="" > - From 02ee2939821dfd323ca683e92cbdba086790f85f Mon Sep 17 00:00:00 2001 From: Aron Carroll Date: Mon, 30 Apr 2012 18:19:48 +0100 Subject: [PATCH 070/109] [2332] Normalise the margins on the homepage heading --- ckan/public/css/style.css | 3 +-- ckan/templates/home/index.html | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ckan/public/css/style.css b/ckan/public/css/style.css index 9d28ae5a0a1..29d0b8515fb 100644 --- a/ckan/public/css/style.css +++ b/ckan/public/css/style.css @@ -445,8 +445,7 @@ body.index.home .front-page .action-box { background: #FFF7C0; } body.index.home .front-page .action-box-inner { - margin: 20px; - margin-bottom: 5px; + margin: 0 20px 5px; min-height: 15em; } body.index.home .front-page .action-box-inner.collaborate { diff --git a/ckan/templates/home/index.html b/ckan/templates/home/index.html index 2bcc5f1a018..7ef7cf45c2b 100644 --- a/ckan/templates/home/index.html +++ b/ckan/templates/home/index.html @@ -10,7 +10,7 @@
-

Welcome to ${g.site_title}!

+

Welcome to ${g.site_title}!

From 3b189b037cf06be009a47f2301b32a3f340fd27b Mon Sep 17 00:00:00 2001 From: Aron Carroll Date: Mon, 30 Apr 2012 18:22:56 +0100 Subject: [PATCH 071/109] [2332] Tweak the spacing in the header Gave the login text a little more space between it and the line height and added a bit more padding to the bottom. --- ckan/public/css/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ckan/public/css/style.css b/ckan/public/css/style.css index 29d0b8515fb..d0d261cf8a8 100644 --- a/ckan/public/css/style.css +++ b/ckan/public/css/style.css @@ -22,7 +22,7 @@ body.no-sidebar .content-outer { } header { - padding: 5px 0px 2px 0px; + padding: 5px 0px 5px 0px; } header #logo { @@ -38,6 +38,7 @@ header #site-name { /*font-weight: bold;*/ color: #333; text-shadow: 1px 1px 3px #ccc; + line-height: 1.3; } header #site-name a { From 81db6bb54a9e67e9d515074ecc0c29d019faa93b Mon Sep 17 00:00:00 2001 From: amercader Date: Tue, 1 May 2012 18:13:36 +0100 Subject: [PATCH 072/109] [2366] Removed Auth groups link from footer and added deprecation notice --- ckan/templates/authorization_group/authz.html | 6 ++++++ ckan/templates/authorization_group/edit.html | 6 ++++++ ckan/templates/authorization_group/index.html | 6 ++++++ ckan/templates/authorization_group/new.html | 6 ++++++ ckan/templates/authorization_group/read.html | 6 ++++++ ckan/templates/layout_base.html | 5 ----- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/ckan/templates/authorization_group/authz.html b/ckan/templates/authorization_group/authz.html index 12643d25792..1c5378cbdee 100644 --- a/ckan/templates/authorization_group/authz.html +++ b/ckan/templates/authorization_group/authz.html @@ -6,6 +6,12 @@ Authorization: ${c.authorization_group_name}
+ +
+ Warning: Authorization groups are deprecated and no longer supported. They will be removed + completely on the next CKAN release. +
+

Update Existing Roles

diff --git a/ckan/templates/authorization_group/edit.html b/ckan/templates/authorization_group/edit.html index ade0f548c04..a404ce2318e 100644 --- a/ckan/templates/authorization_group/edit.html +++ b/ckan/templates/authorization_group/edit.html @@ -6,6 +6,12 @@ Edit: ${c.authorization_group.name if c.authorization_group else ''}
+ +
+ Warning: Authorization groups are deprecated and no longer supported. They will be removed + completely on the next CKAN release. +
+ ${Markup(c.form)}
diff --git a/ckan/templates/authorization_group/index.html b/ckan/templates/authorization_group/index.html index a135ac9fcaf..281f3d1772b 100644 --- a/ckan/templates/authorization_group/index.html +++ b/ckan/templates/authorization_group/index.html @@ -7,6 +7,12 @@ Authorization Groups
+ +
+ Warning: Authorization groups are deprecated and no longer supported. They will be removed + completely on the next CKAN release. +
+

There are ${c.page.item_count} authorization groups.

${c.page.pager()} diff --git a/ckan/templates/authorization_group/new.html b/ckan/templates/authorization_group/new.html index 0dbcc2a527a..1eb973b9282 100644 --- a/ckan/templates/authorization_group/new.html +++ b/ckan/templates/authorization_group/new.html @@ -6,6 +6,12 @@ New Authorization Group
+ +
+ Warning: Authorization groups are deprecated and no longer supported. They will be removed + completely on the next CKAN release. +
+ ${Markup(c.form)}
diff --git a/ckan/templates/authorization_group/read.html b/ckan/templates/authorization_group/read.html index 01ecec03843..3c2c7bad233 100644 --- a/ckan/templates/authorization_group/read.html +++ b/ckan/templates/authorization_group/read.html @@ -7,6 +7,12 @@ ${c.authorization_group.name}
+ +
+ Warning: Authorization groups are deprecated and no longer supported. They will be removed + completely on the next CKAN release. +
+

Members

There are ${c.page.item_count} users in this authorization group.

${c.page.pager()} diff --git a/ckan/templates/layout_base.html b/ckan/templates/layout_base.html index ca36c86e456..dedd7b784cb 100644 --- a/ckan/templates/layout_base.html +++ b/ckan/templates/layout_base.html @@ -176,11 +176,6 @@

Sections

Revisions -
  • - - Authorization Groups - -
  • Site Admin From 4f809ba573a72feff7af6161f5e21f31eb98c462 Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 2 May 2012 11:10:19 +0100 Subject: [PATCH 073/109] allow unselected_facet_items() in helpers --- ckan/lib/helpers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 408b9120785..541c36735ec 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -799,6 +799,7 @@ def process_names(items): 'snippet', 'convert_to_dict', 'activity_div', + 'unselected_facet_items', # imported into ckan.lib.helpers 'literal', 'link_to', From 01ba1e70c5580e3506682e8a25f42293c6ac6d30 Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 2 May 2012 11:48:29 +0100 Subject: [PATCH 074/109] [xs] fix tracking js error --- ckan/templates/layout_base.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ckan/templates/layout_base.html b/ckan/templates/layout_base.html index dedd7b784cb..b6b4f46d7d2 100644 --- a/ckan/templates/layout_base.html +++ b/ckan/templates/layout_base.html @@ -269,7 +269,9 @@

    Meta

    // Tracking var url = location.pathname; // remove any site root from url - url = url.substring(CKAN.SITE_URL.length, url.length - 1); + url = url.substring(CKAN.SITE_URL.length, url.length); + // trim any trailing / + url = url.replace(/\/*$/, ''); $.ajax({url : CKAN.SITE_URL_NO_LOCALE + '/_tracking', type : 'POST', data : {url:url, type:'page'}, From db95e2f615300fc38e84d58d89e2ff753e54c923 Mon Sep 17 00:00:00 2001 From: amercader Date: Wed, 2 May 2012 12:28:48 +0100 Subject: [PATCH 075/109] [doc] Bump 1.6.1 mentions --- doc/commenting.rst | 2 +- doc/deployment.rst | 2 +- doc/forms.rst | 2 +- doc/linked-data-and-rdf.rst | 4 ++-- doc/publisher-profile.rst | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/commenting.rst b/doc/commenting.rst index 5db444f19a9..0f8d1b3193b 100644 --- a/doc/commenting.rst +++ b/doc/commenting.rst @@ -17,7 +17,7 @@ Once installed and enabled, the presence of comments on a given page is configured by your theme (see the documentation in the disqus extension for details). -In the default CKAN theme (as of v1.6.1), comments will be shown only on dataset +In the default CKAN theme (as of v1.7), comments will be shown only on dataset and resource pages (and recent comments only on the :doc:`administrative-dashboard`). diff --git a/doc/deployment.rst b/doc/deployment.rst index 2ee41dd3eb9..e144085a097 100644 --- a/doc/deployment.rst +++ b/doc/deployment.rst @@ -28,7 +28,7 @@ deployment configurations including: Deploying CKAN on an Ubuntu Server using Apache and modwsgi =========================================================== -These instructions have been tested on Ubuntu 10.04 with CKAN 1.6.1. +These instructions have been tested on Ubuntu 10.04 with CKAN 1.7. This is the standard way to deploy CKAN. diff --git a/doc/forms.rst b/doc/forms.rst index 22180feac58..0355e170394 100644 --- a/doc/forms.rst +++ b/doc/forms.rst @@ -130,7 +130,7 @@ Custom Schemas -------------- .. note:: - As of CKAN 1.6.1 custom schema functions apply to both the web user interface + As of CKAN 1.7 custom schema functions apply to both the web user interface and the API. An example of the use of these methods can be found in the ``ckanext-example`` extension. diff --git a/doc/linked-data-and-rdf.rst b/doc/linked-data-and-rdf.rst index 7fa4c6855b1..4ab0bab5d5c 100644 --- a/doc/linked-data-and-rdf.rst +++ b/doc/linked-data-and-rdf.rst @@ -12,12 +12,12 @@ Enabling and Configuring Linked Data Support In CKAN <= 1.6 please install the RDF extension: https://github.com/okfn/ckanext-rdf -In CKAN >= 1.6.1, basic RDF support will be available directly in core. +In CKAN >= 1.7, basic RDF support will be available directly in core. Configuration ------------- -When using the built-in RDF support (CKAN >= 1.6.1) there is no configuration required. By default requests for RDF data will return the RDF generated from the built-in 'packages/read.rdf' template, which can be overridden using the extra-templates directive. +When using the built-in RDF support (CKAN >= 1.7) there is no configuration required. By default requests for RDF data will return the RDF generated from the built-in 'packages/read.rdf' template, which can be overridden using the extra-templates directive. Accessing Linked Data ===================== diff --git a/doc/publisher-profile.rst b/doc/publisher-profile.rst index 820ea568c21..a75728a3d54 100644 --- a/doc/publisher-profile.rst +++ b/doc/publisher-profile.rst @@ -2,7 +2,7 @@ Publisher Profile and Workflow ============================== -.. versionadded:: 1.6.1 +.. versionadded:: 1.7 The Publisher/Organization workflow in CKAN is designed to support a setup in which datasets are managed by a "Publisher" organization. Users can become members of one (or From 9a83d86c673200ef79eb097acdcc71c75e74dda6 Mon Sep 17 00:00:00 2001 From: amercader Date: Wed, 2 May 2012 13:25:31 +0100 Subject: [PATCH 076/109] [doc] Move and update tag vocabularies docs from the wiki --- doc/forms.rst | 6 +++- doc/index.rst | 1 + doc/tag-vocabularies.rst | 71 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 doc/tag-vocabularies.rst diff --git a/doc/forms.rst b/doc/forms.rst index 0355e170394..1b9ca209b21 100644 --- a/doc/forms.rst +++ b/doc/forms.rst @@ -166,6 +166,9 @@ Like ``_form_to_db_schema_options()``, this allows different schemas to be used for different purposes. It is optional, and if it is not available then ``form_to_db_schema`` is used. + +.. _example-geospatial-tags: + Example: Geospatial Tags ------------------------ @@ -174,7 +177,8 @@ This field allows the user to specify one or more country-code tags in order to countries are covered by the dataset. Additionally, the tags must be part of a fixed CKAN tag vocabularly called ``country_codes``. -.. todo:: add reference to tag vocabulary documentation +More information about tag vocabularies can be found in :doc:`tag-vocabularies`. + 1. Creating the Tag Vocabulary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/index.rst b/doc/index.rst index 735a64eee93..0b6d91ecf7a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -37,6 +37,7 @@ Customizing and Extending extensions writing-extensions forms + tag-vocabularies form-integration linked-data-and-rdf filestore diff --git a/doc/tag-vocabularies.rst b/doc/tag-vocabularies.rst new file mode 100644 index 00000000000..677db9dfb63 --- /dev/null +++ b/doc/tag-vocabularies.rst @@ -0,0 +1,71 @@ +================ +Tag vocabularies +================ + +.. versionadded:: 1.7 + +CKAN tags can belong to a vocabulary, which is a way of grouping related tags together. + +Properties +---------- + +* A CKAN instance can have any number of vocabularies. +* Each vocabulary consists of an ID, name and description. +* Each tag can be assigned to a single vocabulary (or have no vocabulary). +* A dataset can have more than one tag from the same vocabulary, and can have tags from more than one vocabulary. +* Vocabularies can be of two types: + * Controlled: the list of possible tags is pre-defined + * Free: users enter their own terms + +Using Vocabularies +------------------ + +A CKAN developer/sysadmin user will have to do a number of things to add some custom vocabs to their CKAN instance: + +1. Call CKAN API functions to add the vocabularies and terms to the db. +2. Implement a CKAN extension (with a custom form), including the tag vocabularies in the schema. +3. Provide dataset view, edit and create templates with the new schemas in them. + +1. Adding Vocabularies +~~~~~~~~~~~~~~~~~~~~~~ + +This needs to be done via the action API (:doc:`apiv3`). Please check the examples section to see which calls are needed. + +2. Custom Form Schema +~~~~~~~~~~~~~~~~~~~~~ + +* Make a plugin that implements ``IDatasetForm`` (for example, see ``ExampleDatasetForm`` in https://github.com/okfn/ckanext-example/blob/master/ckanext/example/forms.py). +* Override ``form_to_db_schema``. Add a new field for your vocabulary tags, making sure that it uses the ``convert_to_tags`` converter with the name of the vocabulary. For example, the following will add a new field called ``vocab_tags``, with each tag assigned to the vocabulary ``EXAMPLE_VOCAB``:: + + def form_to_db_schema(self): + schema = package_form_schema() + schema.update({'vocab_tags': [ignore_missing, convert_to_tags('EXAMPLE_VOCAB')]}) + return schema + +* Override ``db_to_form_schema``. Add your new field to the schema, making sure that it uses the ``convert_from_tags`` validator. If you don't want the tags with vocabularies to be listed along with normal tags (on the web page or via API calls), then make sure that the normal tags field has the ``free_tags_only`` converter applied. For example:: + + def db_to_form_schema(self): + schema = package_form_schema() + schema.update({ + 'tags': {'__extras': [keep_extras, free_tags_only]}, + 'vocab_tags': [convert_from_tags('EXAMPLE_VOCAB'), ignore_missing] + }) + return schema + +3. Adding To Templates +~~~~~~~~~~~~~~~~~~~~~~ + +* If the vocabulary is restricted, you may want to pass a list of all tags in the vocabulary to the template so that they can be displayed as options in a select (or multi-select) box. This should be done by overriding the ``setup_template_variables`` method in your class that implements ``IDatasetForm``. For example:: + + def setup_template_variables(self, context, data_dict=None): + c.vocab_tags = get_action('tag_list')(context, {'vocabulary_id': 'EXAMPLE_VOCAB'}) + +* The custom tags must be added to the template in order to be displayed or edited. For fixed vocabularies, we recommend adding them as a multi-select tag and using the JQuery ``Chosen`` plugin (included in CKAN core). + + +Examples +-------- + +* An example of how to implement it can be found in the section `Customizing Forms` :ref:`example-geospatial-tags`. + +* A complete, working example of a custom form that uses tag vocabularies can be found in the CKAN Example extension (http://github.com/okfn/ckanext-example). From 11e0b50f5bb258da58dea18b391fcbbed8a93a89 Mon Sep 17 00:00:00 2001 From: Ian Murray Date: Wed, 2 May 2012 12:47:02 +0100 Subject: [PATCH 077/109] [2314] Fix broken parse_rfc_2822 helper function. --- ckan/lib/helpers.py | 63 ++++++++++++++++++++++++++++------ ckan/tests/lib/test_helpers.py | 28 ++++++++------- 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 541c36735ec..92c40a69621 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -596,26 +596,69 @@ def date_str_to_datetime(date_str): # a strptime. Also avoids problem with Python 2.5 not having %f. return datetime.datetime(*map(int, re.split('[^\d]', date_str))) -def parse_rfc_2822_date(date_str, tz_aware=True): +def parse_rfc_2822_date(date_str, assume_utc=True): """ Parse a date string of the form specified in RFC 2822, and return a datetime. - RFC 2822 is the date format used in HTTP headers. - - If the date string contains a timezone indication, and tz_aware is True, - then the associated tzinfo is attached to the returned datetime object. - - Returns None if the string cannot be parse as a valid datetime. + RFC 2822 is the date format used in HTTP headers. It should contain timezone + information, but that cannot be relied upon. + + If date_str doesn't contain timezone information, then the 'assume_utc' flag + determines whether we assume this string is local (with respect to the + server running this code), or UTC. In practice, what this means is that if + assume_utc is True, then the returned datetime is 'aware', with an associated + tzinfo of offset zero. Otherwise, the returned datetime is 'naive'. + + If timezone information is available in date_str, then the returned datetime + is 'aware', ie - it has an associated tz_info object. + + Returns None if the string cannot be parsed as a valid datetime. """ time_tuple = email.utils.parsedate_tz(date_str) + # Not parsable if not time_tuple: return None - if not tz_aware: - time_tuple = time_tuple[:-1] + (None,) + # No timezone information available in the string + if time_tuple[-1] is None and not assume_utc: + return datetime.datetime.fromtimestamp(email.utils.mktime_tz(time_tuple)) + else: + offset = 0 if time_tuple[-1] is None else time_tuple[-1] + tz_info = _RFC2282TzInfo(offset) + return datetime.datetime(*time_tuple[:6], microsecond=0, tzinfo=tz_info) + +class _RFC2282TzInfo(datetime.tzinfo): + """ + A datetime.tzinfo implementation used by parse_rfc_2822_date() function. + + In order to return timezone information, a concrete implementation of + datetime.tzinfo is required. This class represents tzinfo that knows + about it's offset from UTC, has no knowledge of daylight savings time, and + no knowledge of the timezone name. + + """ + + def __init__(self, offset): + """ + offset from UTC in seconds. + """ + self.offset = datetime.timedelta(seconds=offset) + + def utcoffset(self, dt): + return self.offset + + def dst(self, dt): + """ + Dates parsed from an RFC 2822 string conflate timezone and dst, and so + it's not possible to determine whether we're in DST or not, hence + returning None. + """ + return None + + def tzname(self, dt): + return None - return datetime.datetime.fromtimestamp(email.utils.mktime_tz(time_tuple)) def time_ago_in_words_from_str(date_str, granularity='month'): if date_str: diff --git a/ckan/tests/lib/test_helpers.py b/ckan/tests/lib/test_helpers.py index b7eeacbf02b..5233d853e37 100644 --- a/ckan/tests/lib/test_helpers.py +++ b/ckan/tests/lib/test_helpers.py @@ -92,15 +92,25 @@ def test_gravatar_encodes_url_correctly(self): for e in expected: assert e in res, (e,res) - def test_parse_rfc_2822_simple_case(self): + def test_parse_rfc_2822_no_timezone_specified(self): """ Parse "Tue, 15 Nov 1994 12:45:26" successfully. - No zone info. + Assuming it's UTC. """ dt = h.parse_rfc_2822_date('Tue, 15 Nov 1994 12:45:26') - assert_equal(dt.isoformat(), '1994-11-15T12:45:26') + assert_equal(dt.isoformat(), '1994-11-15T12:45:26+00:00') + def test_parse_rfc_2822_no_timezone_specified_assuming_local(self): + """ + Parse "Tue, 15 Nov 1994 12:45:26" successfully. + + Assuming it's local. + """ + dt = h.parse_rfc_2822_date('Tue, 15 Nov 1994 12:45:26', assume_utc=False) + assert_equal(dt.isoformat(), '1994-11-15T12:45:26') + assert_equal(dt.tzinfo, None) + def test_parse_rfc_2822_gmt_case(self): """ Parse "Tue, 15 Nov 1994 12:45:26 GMT" successfully. @@ -108,20 +118,12 @@ def test_parse_rfc_2822_gmt_case(self): GMT obs-zone specified """ dt = h.parse_rfc_2822_date('Tue, 15 Nov 1994 12:45:26 GMT') - assert_equal(dt.isoformat(), '1994-11-15T12:45:26') + assert_equal(dt.isoformat(), '1994-11-15T12:45:26+00:00') def test_parse_rfc_2822_with_offset(self): """ Parse "Tue, 15 Nov 1994 12:45:26 +0700" successfully. """ dt = h.parse_rfc_2822_date('Tue, 15 Nov 1994 12:45:26 +0700') - assert_equal(dt.isoformat(), '1994-11-15T05:45:26') - - def test_parse_rfc_2822_ignoring_offset(self): - """ - Parse "Tue, 15 Nov 1994 12:45:26 +0700" successfully. - """ - dt = h.parse_rfc_2822_date('Tue, 15 Nov 1994 12:45:26 +0700', tz_aware=False) - assert_equal(dt.isoformat(), '1994-11-15T12:45:26') - + assert_equal(dt.isoformat(), '1994-11-15T12:45:26+07:00') From b9d6d42cc200452fedd482cd450c7625c3379bca Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 2 May 2012 18:04:01 +0200 Subject: [PATCH 078/109] [i18n] Pull translations from Transifex `tx pull --all --force` and `python setup.py compile_catalog` --- ckan/i18n/ca/LC_MESSAGES/ckan.mo | Bin 63373 -> 64031 bytes ckan/i18n/ca/LC_MESSAGES/ckan.po | 285 ++++++++++++++++--------------- ckan/i18n/es/LC_MESSAGES/ckan.mo | Bin 64606 -> 64606 bytes ckan/i18n/es/LC_MESSAGES/ckan.po | 4 +- ckan/i18n/sk/LC_MESSAGES/ckan.mo | Bin 62576 -> 62591 bytes ckan/i18n/sk/LC_MESSAGES/ckan.po | 8 +- 6 files changed, 149 insertions(+), 148 deletions(-) diff --git a/ckan/i18n/ca/LC_MESSAGES/ckan.mo b/ckan/i18n/ca/LC_MESSAGES/ckan.mo index 12a1ee46c48458859f7ebe768120fc0091dc816c..1e48ee19b4ab5682a31da3a4984a02c7d657e5cb 100644 GIT binary patch delta 9940 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 delta 7018 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 diff --git a/ckan/i18n/ca/LC_MESSAGES/ckan.po b/ckan/i18n/ca/LC_MESSAGES/ckan.po index 18846737258..273846640a7 100644 --- a/ckan/i18n/ca/LC_MESSAGES/ckan.po +++ b/ckan/i18n/ca/LC_MESSAGES/ckan.po @@ -5,6 +5,7 @@ # Translators: # amercader , 2011. # , 2011, 2012. +# , 2012. # ilabastida , 2011. # , 2011. # , 2012. @@ -13,8 +14,8 @@ msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-27 08:35+0000\n" -"Last-Translator: ilabastida \n" +"PO-Revision-Date: 2012-05-01 21:58+0000\n" +"Last-Translator: amercader \n" "Language-Team: Catalan (http://www.transifex.net/projects/p/ckan/language/ca/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -478,7 +479,7 @@ msgstr "Captcha incorrecte. Si us plau, torneu-ho a provar." msgid "" "User \"%s\" is now registered but you are still logged in as \"%s\" from " "before" -msgstr "" +msgstr "L'usuari \"%s\" ha estat registrat, pero encara teniu la sessió iniciada com a \"%s\"" #: ckan/controllers/user.py:187 msgid "No user specified" @@ -506,11 +507,11 @@ msgstr "%s ha iniciat sessió" #: ckan/controllers/user.py:279 msgid "Login failed. Bad username or password." -msgstr "" +msgstr "No s'ha pogut iniciar sessió. Nom d'usuari o contrasenya incorrectes." #: ckan/controllers/user.py:281 msgid " (Or if using OpenID, it hasn't been associated with a user account.)" -msgstr "" +msgstr "(O si useu OpenID, no ha sigut associat amb cap compte d'usuari)" #: ckan/controllers/user.py:334 #, python-format @@ -871,7 +872,7 @@ msgstr "Si us plau, indiqueu un nom d'usuari" #: ckan/lib/helpers.py:504 msgid "Update your avatar at gravatar.com" -msgstr "" +msgstr "Actualitzeu el vostre avatar a gravatar.com" #: ckan/lib/helpers.py:624 ckan/templates/js_strings.html:64 msgid "Unknown" @@ -936,7 +937,7 @@ msgstr "No s'ha facilitat cap autor." #: ckan/lib/package_saver.py:44 msgid "Maintainer not given" -msgstr "" +msgstr "Mantenidor no especificat" #: ckan/lib/package_saver.py:101 ckan/logic/validators.py:51 msgid "No links are allowed in the log_message." @@ -958,7 +959,7 @@ msgstr "Manca el valor" #: ckan/lib/navl/validators.py:54 #, python-format msgid "The input field %(name)s was not expected." -msgstr "" +msgstr "El camp %(name)s no s'esperava." #: ckan/lib/navl/validators.py:93 msgid "Please enter an integer value" @@ -971,7 +972,7 @@ msgstr "No s'ha proporcionat una clau API vàlida." #: ckan/logic/converters.py:59 ckan/logic/converters.py:74 #, python-format msgid "Tag vocabulary \"%s\" does not exist" -msgstr "" +msgstr "El vocabulari d'etiquetes \"%s\" no existeix" #: ckan/logic/validators.py:32 msgid "Invalid integer" @@ -988,7 +989,7 @@ msgstr "Usuari" #: ckan/logic/validators.py:124 msgid "That group name or ID does not exist." -msgstr "" +msgstr "Aquest nom o identificador de grup no existeix." #: ckan/logic/validators.py:136 msgid "Activity type" @@ -996,7 +997,7 @@ msgstr "Tipus d'activitat" #: ckan/logic/validators.py:182 msgid "That name cannot be used" -msgstr "" +msgstr "Aquest nom no es pot fer servir" #: ckan/logic/validators.py:187 ckan/logic/validators.py:423 #, python-format @@ -1067,30 +1068,30 @@ msgstr "Actualització no permesa, ja que s'assembla a spam. Si us plau, eviteu #: ckan/logic/validators.py:428 msgid "That vocabulary name is already in use." -msgstr "" +msgstr "Aquest nom de vocabulari ja existeix." #: ckan/logic/validators.py:434 #, python-format msgid "Cannot change value of key from %s to %s. This key is read-only" -msgstr "" +msgstr "No es pot canviar el valor de la clau de %s a %s. Aquesta clau és de només lectura." #: ckan/logic/validators.py:443 msgid "Tag vocabulary was not found." -msgstr "" +msgstr "Vocabulari d'etiquetes no trobat." #: ckan/logic/validators.py:456 #, python-format msgid "Tag %s does not belong to vocabulary %s" -msgstr "" +msgstr "L'etiqueta %s no pertany al vocabulari %s" #: ckan/logic/validators.py:462 msgid "No tag name" -msgstr "" +msgstr "Falta el nom de l'etiqueta" #: ckan/logic/validators.py:475 #, python-format msgid "Tag %s already belongs to vocabulary %s" -msgstr "" +msgstr "L'etiqueta %s ja pertany al vocabulari %s" #: ckan/logic/action/__init__.py:56 msgid "Package resource(s) invalid" @@ -1113,7 +1114,7 @@ msgstr "API REST: Creada relació entre paquets: %s %s %s" #: ckan/logic/action/create.py:214 #, python-format msgid "REST API: Create member object %s" -msgstr "" +msgstr "API REST: Crear objecte membre %s" #: ckan/logic/action/create.py:324 msgid "You must supply a package id or name (parameter \"package\")." @@ -1145,22 +1146,22 @@ msgstr "API REST: Esborrat %s" #: ckan/logic/action/delete.py:165 ckan/logic/action/delete.py:180 #: ckan/logic/action/get.py:1159 ckan/logic/action/update.py:594 msgid "id not in data" -msgstr "" +msgstr "id no present a les dades" #: ckan/logic/action/delete.py:169 ckan/logic/action/get.py:1162 #: ckan/logic/action/update.py:598 #, python-format msgid "Could not find vocabulary \"%s\"" -msgstr "" +msgstr "No s'ha trobat el vocabulari \"%s\"" #: ckan/logic/action/delete.py:188 #, python-format msgid "Could not find tag \"%s\"" -msgstr "" +msgstr "No s'ha trobat l'etiqueta \"%s\"" #: ckan/logic/action/update.py:114 msgid "Related was not found." -msgstr "" +msgstr "Element relacionat no trobat" #: ckan/logic/action/update.py:142 msgid "Resource was not found." @@ -1197,7 +1198,7 @@ msgstr "L'usuari %s no està autoritzat a editar aquests grups" #: ckan/logic/auth/create.py:28 ckan/logic/auth/publisher/create.py:31 msgid "You must be logged in to add a related item" -msgstr "" +msgstr "Heu d'haver iniciat sessió per afegir un element relacionat" #: ckan/logic/auth/create.py:48 ckan/logic/auth/publisher/create.py:60 #, python-format @@ -1241,7 +1242,7 @@ msgstr "L'usuari %s no està autoritzat a esborrar el conjunt de dades %s" #: ckan/logic/auth/publisher/delete.py:36 #: ckan/logic/auth/publisher/delete.py:44 msgid "Only the owner can delete a related item" -msgstr "" +msgstr "Només el propietari pot eliminar un element relacionat" #: ckan/logic/auth/delete.py:47 #, python-format @@ -1312,7 +1313,7 @@ msgstr "L'usuari %s no està autoritzat a editar el grup %s" #: ckan/logic/auth/publisher/update.py:95 #: ckan/logic/auth/publisher/update.py:100 msgid "Only the owner can update a related item" -msgstr "" +msgstr "Només el propietari pot editar un element relacionat" #: ckan/logic/auth/update.py:106 #, python-format @@ -1347,7 +1348,7 @@ msgstr "L'usuari %s no està autoritzat a actualitzar la taula de l'estat de tas #: ckan/logic/auth/update.py:191 ckan/logic/auth/publisher/update.py:161 #, python-format msgid "User %s not authorized to update term_translation table" -msgstr "" +msgstr "L'usuari %s no està autoritzat a actualitzar la taula term_translation" #: ckan/logic/auth/update.py:201 ckan/logic/auth/publisher/update.py:174 msgid "Valid API key needed to edit a package" @@ -1359,97 +1360,97 @@ msgstr "Es necessita una clau API vàlida per editar un grup" #: ckan/logic/auth/publisher/create.py:52 msgid "Two package IDs are required" -msgstr "" +msgstr "Es requereixen dos identificadors de conjunts de dades" #: ckan/logic/auth/publisher/create.py:74 msgid "User is not authorized to create groups" -msgstr "" +msgstr "Usuari no autorizat a crear grups" #: ckan/logic/auth/publisher/create.py:97 msgid "Authorization groups not implemented in this profile" -msgstr "" +msgstr "Grups d'autorització no implementats en aquest perfil" #: ckan/logic/auth/publisher/delete.py:26 #, python-format msgid "User %s not authorized to delete packages in these group" -msgstr "" +msgstr "L'usuari %s no està autoritzat a eliminar conjunts de dades d'aquest grup" #: ckan/logic/auth/publisher/delete.py:58 #: ckan/logic/auth/publisher/delete.py:63 msgid "Only members of this group are authorized to delete this group" -msgstr "" +msgstr "Només membres d'aquest grup estan autoritzats a eliminar-lo" #: ckan/logic/auth/publisher/get.py:82 #, python-format msgid "User not authorized to read package %s" -msgstr "" +msgstr "L'usuari no està autoritzat a llegir el conjunt de dades %s" #: ckan/logic/auth/publisher/get.py:137 #, python-format msgid "User %s not authorized to show group %s" -msgstr "" +msgstr "L'usuari %s no està autoritzat a mostrar el grup %s" #: ckan/logic/auth/publisher/update.py:29 #, python-format msgid "User %s not authorized to edit packages in these groups" -msgstr "" +msgstr "L'usuari %s no està autoritzat a editar conjunts de dades en aquests grups" #: ckan/logic/auth/publisher/update.py:47 #: ckan/logic/auth/publisher/update.py:50 #, python-format msgid "User %s not authorized to edit resources in this package" -msgstr "" +msgstr "L'usuari %s no està autoritzat a editar recursos d'aquest conjunt de dades" #: ckan/logic/auth/publisher/update.py:62 msgid "Package edit permissions is not available" -msgstr "" +msgstr "Edició dels permisos del conjunt de dades no disponible" #: ckan/logic/auth/publisher/update.py:74 msgid "Only members of this group are authorized to edit this group" -msgstr "" +msgstr "Només membres d'aquest grup estan autoritzats a editar-lo" #: ckan/logic/auth/publisher/update.py:83 #, python-format msgid "Could not find user %s" -msgstr "" +msgstr "No s'ha trobat l'usuari %s" #: ckan/logic/auth/publisher/update.py:87 #, python-format msgid "User %s not authorized to edit this group" -msgstr "" +msgstr "L'usuari %s no està autoritzat a editar aquest grup" #: ckan/logic/auth/publisher/update.py:108 msgid "Group edit permissions is not implemented" -msgstr "" +msgstr "Edició dels permisos del grup no implementada" #: ckan/logic/auth/publisher/update.py:111 #: ckan/logic/auth/publisher/update.py:115 msgid "Authorization group update not implemented" -msgstr "" +msgstr "Edició del grup d'autorització no implementada" #: ckan/model/license.py:61 msgid "License Not Specified" -msgstr "" +msgstr "Llicència no especificada" #: ckan/model/license.py:166 msgid "Other (Open)" -msgstr "" +msgstr "Altres (Oberta)" #: ckan/model/license.py:180 msgid "Other (Public Domain)" -msgstr "" +msgstr "Altres (Public Domain)" #: ckan/model/license.py:194 msgid "Other (Attribution)" -msgstr "" +msgstr "Altres (Atribució)" #: ckan/model/license.py:234 msgid "Other (Non-Commercial)" -msgstr "" +msgstr "Altres (No comercial)" #: ckan/model/license.py:248 msgid "Other (Not Open)" -msgstr "" +msgstr "Altres (No oberta)" #: ckan/model/package_relationship.py:48 #, python-format @@ -1545,11 +1546,11 @@ msgstr "No hi ha recursos per a descarregar" #: ckan/templates/_util.html:138 msgid "No description for this item" -msgstr "" +msgstr "No hi ha descripció per a aquest element" #: ckan/templates/_util.html:139 msgid "View this related item" -msgstr "" +msgstr "Veure element relacionat" #: ckan/templates/_util.html:161 msgid "no ratings yet" @@ -1571,7 +1572,7 @@ msgstr "Error" #: ckan/templates/facets.html:162 msgid "(facet_item['count'])" -msgstr "" +msgstr "(facet_item['count'])" #: ckan/templates/js_strings.html:16 msgid "Checking..." @@ -1583,7 +1584,7 @@ msgstr "Escriviu al menys dos caràcters..." #: ckan/templates/js_strings.html:18 msgid "This is the current URL." -msgstr "" +msgstr "Aquesta és la URL actual." #: ckan/templates/js_strings.html:19 msgid "This URL is available!" @@ -1625,23 +1626,23 @@ msgstr "Voleu esborrar el recurs '%name%'?" #: ckan/templates/js_strings.html:28 msgid "Preview not available for data type: " -msgstr "" +msgstr "Previsualització no disponible per al tipus de dades:" #: ckan/templates/js_strings.html:29 msgid "Failed to get credentials for storage upload. Upload cannot proceed" -msgstr "" +msgstr "No s'han pogut obtenir les credencials per a la pujada d'emmagatzemament. La pujada no pot continuar." #: ckan/templates/js_strings.html:30 msgid "Checking upload permissions ..." -msgstr "" +msgstr "Comprovant permisos de pujada..." #: ckan/templates/js_strings.html:31 msgid "Uploading file ..." -msgstr "" +msgstr "Pujant arxiu..." #: ckan/templates/js_strings.html:32 msgid "Data File" -msgstr "" +msgstr "Arxiu de dades" #: ckan/templates/js_strings.html:33 ckan/templates/layout_base.html:144 #: ckan/templates/package/search.html:37 @@ -1650,27 +1651,27 @@ msgstr "API" #: ckan/templates/js_strings.html:34 msgid "Visualization" -msgstr "" +msgstr "Visualització" #: ckan/templates/js_strings.html:35 msgid "Image" -msgstr "" +msgstr "Imatge" #: ckan/templates/js_strings.html:36 msgid "Metadata" -msgstr "" +msgstr "Metadades" #: ckan/templates/js_strings.html:37 msgid "Documentation" -msgstr "" +msgstr "Documentació" #: ckan/templates/js_strings.html:38 msgid "Code" -msgstr "" +msgstr "Codi" #: ckan/templates/js_strings.html:39 msgid "Example" -msgstr "" +msgstr "Exemple" #: ckan/templates/js_strings.html:44 ckan/templates/storage/index.html:6 #: ckan/templates/storage/index.html:15 ckan/templates/storage/success.html:6 @@ -1701,7 +1702,7 @@ msgstr "Tipus de recurs" #: ckan/templates/js_strings.html:51 msgid "DataStore enabled" -msgstr "" +msgstr "DataStore habilitada" #: ckan/templates/js_strings.html:52 msgid "Size (Bytes)" @@ -1713,7 +1714,7 @@ msgstr "Mimetype" #: ckan/templates/js_strings.html:54 msgid "Created" -msgstr "" +msgstr "Creat" #: ckan/templates/js_strings.html:55 msgid "Last Modified" @@ -1741,38 +1742,38 @@ msgstr "Aquest recurs té canvis sense desar." #: ckan/templates/js_strings.html:63 msgid "e.g. csv, html, xls, rdf, ..." -msgstr "" +msgstr "p.ex. csv, html, xls, rdf, ..." #: ckan/templates/js_strings.html:65 msgid "Extra Fields" -msgstr "" +msgstr "Camps extra" #: ckan/templates/js_strings.html:66 msgid "Add Extra Field" -msgstr "" +msgstr "Afegir camp extra" #: ckan/templates/js_strings.html:67 msgid "Delete Resource" -msgstr "" +msgstr "Eliminar recurs" #: ckan/templates/js_strings.html:68 msgid "You can use %aMarkdown formatting%b here." -msgstr "" +msgstr "Podeu usar %aformat Markdown%b." #: ckan/templates/js_strings.html:69 msgid "" "Should a %aDataStore table and Data API%b be enabled for this resource?" -msgstr "" +msgstr "Voleu habilitar una %ataula DataStore i la API de dades%b per a aquest recurs?" #: ckan/templates/js_strings.html:70 #, python-format msgid "" "Dates are in %aISO Format%b — eg. %c2012-12-25%d or %c2010-05-31T14:30%d." -msgstr "" +msgstr "Les dates estan en %aformat ISO%b - p.ex. %c2012-12-25%d or %c2010-05-31T14:30%d." #: ckan/templates/js_strings.html:71 msgid "Data File (Uploaded)" -msgstr "" +msgstr "Arxiu de dades (Pujat)" #: ckan/templates/layout_base.html:56 ckan/templates/user/logout.html:7 msgid "Logout" @@ -1810,7 +1811,7 @@ msgstr "Quant a" #: ckan/templates/layout_base.html:94 msgid "Page Logo" -msgstr "" +msgstr "Logotip de la pàgina" #: ckan/templates/layout_base.html:112 msgid "Master content template placeholder … please replace me." @@ -1902,7 +1903,7 @@ msgstr "{actor} ha afegit l'etiqueta {object} al conjunt de dades {target}" #: ckan/templates/activity_streams/changed_group.html:8 msgid "{actor} updated the group {object}" -msgstr "" +msgstr "{actor} ha actualitzat el grup {object}" #: ckan/templates/activity_streams/changed_package.html:8 msgid "{actor} updated the dataset {object}" @@ -1918,11 +1919,11 @@ msgstr "{actor} ha actualitzar el recurs {object} en el conjunt de dades {target #: ckan/templates/activity_streams/changed_user.html:8 msgid "{actor} updated their profile" -msgstr "" +msgstr "{actor} ha actualitzat el seu perfil" #: ckan/templates/activity_streams/deleted_group.html:8 msgid "{actor} deleted the group {object}" -msgstr "" +msgstr "{actor} ha esborrat el grup {object}" #: ckan/templates/activity_streams/deleted_package.html:8 msgid "{actor} deleted the dataset {object}" @@ -1938,7 +1939,7 @@ msgstr "{actor} ha esborrat el recurs {object} del conjunt de dades {target}" #: ckan/templates/activity_streams/new_group.html:8 msgid "{actor} created the group {object}" -msgstr "" +msgstr "{actor} ha creat el grup {object}" #: ckan/templates/activity_streams/new_package.html:8 msgid "{actor} created the dataset {object}" @@ -1954,7 +1955,7 @@ msgstr "{actor} ha afegit el recurs {object} al conjunt de dades {target}" #: ckan/templates/activity_streams/new_user.html:8 msgid "{actor} signed up" -msgstr "" +msgstr "{actor} s'ha registrat" #: ckan/templates/activity_streams/removed_tag.html:8 msgid "{actor} removed the tag {object} from the dataset {target}" @@ -2089,7 +2090,7 @@ msgstr "Hi ha [1:%(item_count)s] grups d'autorització." #: ckan/templates/authorization_group/layout.html:11 #: ckan/templates/revision/layout.html:9 msgid "List" -msgstr "" +msgstr "Llista" #: ckan/templates/authorization_group/layout.html:14 #: ckan/templates/group/layout.html:12 ckan/templates/package/layout.html:10 @@ -2146,7 +2147,7 @@ msgstr "Actualitzar rols existents per als grups d'autorització" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 @@ -2228,7 +2229,7 @@ msgstr "Llistat de grups" #: ckan/templates/group/layout.html:35 msgid "Add a Group" -msgstr "" +msgstr "Afegir un grup" #: ckan/templates/group/layout.html:38 msgid "Login to Add a Group" @@ -2257,7 +2258,7 @@ msgstr "El formulari conté camps incorrectes:" #: ckan/templates/group/new_group_form.html:35 #: ckan/templates/package/new_package_form.html:56 msgid "Warning: URL is very long. Consider changing it to something shorter." -msgstr "" +msgstr "Atenció: la URL és molt llarga. Penseu si cal escurçar-la." #: ckan/templates/group/new_group_form.html:43 #: ckan/templates/package/new_package_form.html:88 @@ -2266,11 +2267,11 @@ msgstr "Comenceu amb una frase resum ..." #: ckan/templates/group/new_group_form.html:47 msgid "Image URL:" -msgstr "" +msgstr "URL de l'imatge:" #: ckan/templates/group/new_group_form.html:50 msgid "The URL for the image that is associated with this group." -msgstr "" +msgstr "La URL de l'imatge associada amb aquest grup." #: ckan/templates/group/new_group_form.html:57 #: ckan/templates/package/new_package_form.html:275 @@ -2295,17 +2296,17 @@ msgstr "Esborrar" #: ckan/templates/group/new_group_form.html:83 #: ckan/templates/package/new_package_form.html:251 msgid "Add..." -msgstr "" +msgstr "Afegir..." #: ckan/templates/group/new_group_form.html:86 #: ckan/templates/package/new_package_form.html:254 msgid "Key =" -msgstr "" +msgstr "Clau =" #: ckan/templates/group/new_group_form.html:90 #: ckan/templates/package/new_package_form.html:258 msgid "Value =" -msgstr "" +msgstr "Valor =" #: ckan/templates/group/new_group_form.html:116 msgid "Add datasets" @@ -2419,7 +2420,7 @@ msgstr "conjunts de dades" msgid "" "that you can \n" " browse, learn about and download." -msgstr "" +msgstr "que podeu navegar, descobrir i descarregar." #: ckan/templates/home/index.html:32 msgid "Share data" @@ -2527,7 +2528,7 @@ msgstr "- Edició de Recursos - Conjunt de Dades" #: ckan/templates/package/editresources.html:7 msgid "Edit Resources:" -msgstr "" +msgstr "Editar recursos:" #: ckan/templates/package/form_extra_fields.html:12 msgid "New key" @@ -2549,19 +2550,19 @@ msgstr "Historial del conjunt de dades" #: ckan/templates/package/layout.html:14 msgid "Resources (0)" -msgstr "" +msgstr "Recursos (0)" #: ckan/templates/package/layout.html:23 msgid "Add / Edit resources" -msgstr "" +msgstr "Afegir / Editar recursos" #: ckan/templates/package/layout.html:39 msgid "Related" -msgstr "" +msgstr "Relacionats" #: ckan/templates/package/layout.html:44 msgid "Settings" -msgstr "" +msgstr "Opcions" #: ckan/templates/package/new.html:6 msgid "Add - Datasets" @@ -2587,15 +2588,15 @@ msgstr "Inici" msgid "" "(Don't worry if you don't know which license the data has been released " "under)." -msgstr "" +msgstr "(No us preocupeu si no sabeu amb quina llicència s'han alliberat les dades)" #: ckan/templates/package/new_package_form.html:96 msgid "Member of:" -msgstr "" +msgstr "Membre de:" #: ckan/templates/package/new_package_form.html:109 msgid "Add to:" -msgstr "" +msgstr "Afegir a:" #: ckan/templates/package/new_package_form.html:126 msgid "" @@ -2605,7 +2606,7 @@ msgstr "Termes separats per comes que poden enllaçar aquest conjunt de dades a #: ckan/templates/package/new_package_form.html:134 msgid "Add Resources" -msgstr "" +msgstr "Afegir recursos" #: ckan/templates/package/new_package_form.html:136 msgid "" @@ -2614,7 +2615,7 @@ msgstr "Pugeu o enllaceu arxius de dades, APIs o altres materials relacionats am #: ckan/templates/package/new_package_form.html:143 msgid "New resource..." -msgstr "" +msgstr "Nou recurs..." #: ckan/templates/package/new_package_form.html:148 msgid "x" @@ -2638,7 +2639,7 @@ msgstr "URL de l'arxiu" #: ckan/templates/package/new_package_form.html:165 msgid "API URL" -msgstr "" +msgstr "URL de l'API" #: ckan/templates/package/new_package_form.html:228 msgid "e.g. 1.2.0" @@ -2674,11 +2675,11 @@ msgstr "El conjunt de dades és" #: ckan/templates/package/new_package_form.html:285 msgid "Summary" -msgstr "" +msgstr "Resum" #: ckan/templates/package/new_package_form.html:287 msgid "Briefly describe the changes you have made..." -msgstr "" +msgstr "Descriviu breument el canvis realitzats..." #: ckan/templates/package/new_package_form.html:298 msgid "" @@ -2688,32 +2689,32 @@ msgstr "Com que no heu iniciat sessió, s'usarà la vostra adreça IP. [1:Feu cl #: ckan/templates/package/new_package_form.html:309 msgid "Important:" -msgstr "" +msgstr "Important:" #: ckan/templates/package/new_package_form.html:309 msgid "" "By submitting content, you agree to release your contributions under the" -msgstr "" +msgstr "Enviant aquest contingut, accepteu publicar les vostres contribucions sota la" #: ckan/templates/package/new_package_form.html:309 msgid ". Please" -msgstr "" +msgstr ". Si us plau" #: ckan/templates/package/new_package_form.html:309 msgid "refrain" -msgstr "" +msgstr "eviteu" #: ckan/templates/package/new_package_form.html:309 msgid "from editing this page if you are" -msgstr "" +msgstr "editar aquesta página si" #: ckan/templates/package/new_package_form.html:309 msgid "not" -msgstr "" +msgstr "no" #: ckan/templates/package/new_package_form.html:309 msgid "happy to do this." -msgstr "" +msgstr "hi esteu d'acord." #: ckan/templates/package/read.html:14 msgid "- Datasets" @@ -2779,7 +2780,7 @@ msgstr "(cap)" #: ckan/templates/package/read_core.html:51 msgid "(settings)" -msgstr "" +msgstr "(opcions)" #: ckan/templates/package/read_core.html:57 #: ckan/templates/package/resource_read.html:186 @@ -2814,27 +2815,27 @@ msgstr "[1:Pàgina del conjunt de dades] a\n[2:%(harvest_catalogue_name)s]" #: ckan/templates/package/related_list.html:17 #: ckan/templates/package/related_list.html:21 msgid "- Related" -msgstr "" +msgstr "- Relacionats" #: ckan/templates/package/related_list.html:26 msgid "Related items" -msgstr "" +msgstr "Elements relacionats" #: ckan/templates/package/related_list.html:26 msgid "Add related item" -msgstr "" +msgstr "Afegir element relacionat" #: ckan/templates/package/related_list.html:28 msgid "There are no related items here yet" -msgstr "" +msgstr "Encara no hi ha elements relacionats" #: ckan/templates/package/related_list.html:29 msgid ", why not" -msgstr "" +msgstr ", perquè no" #: ckan/templates/package/related_list.html:29 msgid "add one" -msgstr "" +msgstr "afegir-ne un?" #: ckan/templates/package/resource_embedded_dataviewer.html:78 #: ckan/templates/package/resource_read.html:85 @@ -2852,11 +2853,11 @@ msgstr "Descarregar" #: ckan/templates/package/resource_read.html:111 #: ckan/templates/package/resource_read.html:114 msgid "Data API" -msgstr "" +msgstr "API de dades" #: ckan/templates/package/resource_read.html:114 msgid "Data API is unavailable for this resource as DataStore is disabled" -msgstr "" +msgstr "La API de dades no es troba disponible per a aquest recurs, ja que la DataStore no està habilitada" #: ckan/templates/package/resource_read.html:127 msgid "Last updated" @@ -2864,7 +2865,7 @@ msgstr "Última actualització" #: ckan/templates/package/resource_read.html:140 msgid "License unknown" -msgstr "" +msgstr "Llicència desconeguda" #: ckan/templates/package/resource_read.html:164 msgid "From the [1:Dataset]:" @@ -2872,12 +2873,12 @@ msgstr "Del [1:conjunt de dades]" #: ckan/templates/package/resource_read.html:174 msgid "Cannot embed as resource is private." -msgstr "" +msgstr "No es pot incrustar el recurs, ja que és privat." #: ckan/templates/package/resource_read.html:174 #: ckan/templates/package/resource_read.html:175 msgid "Embed" -msgstr "" +msgstr "Incrustar" #: ckan/templates/package/resources.html:2 msgid "Someresources" @@ -3013,27 +3014,27 @@ msgstr ",\n Etiqueta -" #: ckan/templates/snippets/data-viewer-embed-dialog.html:13 msgid "Embed Data Viewer" -msgstr "" +msgstr "Incrustar visor de dades" #: ckan/templates/snippets/data-viewer-embed-dialog.html:19 msgid "Embed this view" -msgstr "" +msgstr "Incrusteu aquesta vista" #: ckan/templates/snippets/data-viewer-embed-dialog.html:19 msgid "by copying this into your webpage:" -msgstr "" +msgstr "copiant aquest codi a la vostra pàgina web:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:21 msgid "Choose width and height in pixels:" -msgstr "" +msgstr "Escolliu l'amplada i l'alçada en píxels:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:22 msgid "Width:" -msgstr "" +msgstr "Amplada:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:24 msgid "Height:" -msgstr "" +msgstr "Alçada:" #: ckan/templates/snippets/package_list.html:39 msgid "Not Openly Licensed" @@ -3108,15 +3109,15 @@ msgstr "Editar Usuari:" #: ckan/templates/user/edit_user_form.html:21 msgid "Full name" -msgstr "" +msgstr "Nom complet" #: ckan/templates/user/edit_user_form.html:27 msgid "E-mail" -msgstr "" +msgstr "Correu electrònic" #: ckan/templates/user/edit_user_form.html:33 msgid "OpenId" -msgstr "" +msgstr "OpenID" #: ckan/templates/user/edit_user_form.html:41 msgid "A little about you..." @@ -3129,12 +3130,12 @@ msgstr "Canviar la vostra contrasenya" #: ckan/templates/user/edit_user_form.html:48 #: ckan/templates/user/new_user_form.html:40 msgid "Password" -msgstr "" +msgstr "Contrasenya" #: ckan/templates/user/edit_user_form.html:54 #: ckan/templates/user/new_user_form.html:47 msgid "Password (repeat)" -msgstr "" +msgstr "Contrasenya (repetir)" #: ckan/templates/user/edit_user_form.html:61 msgid "Change your username" @@ -3142,7 +3143,7 @@ msgstr "Canvieu el nom d'usuari" #: ckan/templates/user/edit_user_form.html:63 msgid "Username" -msgstr "" +msgstr "Nom d'usuari" #: ckan/templates/user/layout.html:11 msgid "My Profile" @@ -3199,7 +3200,7 @@ msgstr "Contrasenya:" #: ckan/templates/user/login.html:37 msgid "Sign In" -msgstr "" +msgstr "Iniciar sessió" #: ckan/templates/user/login.html:39 msgid "Forgot your password?" @@ -3238,7 +3239,7 @@ msgstr "OpenID és un servei que permet iniciar sessió en molts llocs diferents #: ckan/templates/user/login.html:69 msgid "Sign in with OpenID" -msgstr "" +msgstr "Iniciar sessió amb OpenID" #: ckan/templates/user/logout.html:5 msgid "Logout - User" @@ -3254,27 +3255,27 @@ msgstr "Heu tancat la sessió satisfactòriament." #: ckan/templates/user/logout_first.html:6 msgid "Logged in - User" -msgstr "" +msgstr "Sessió iniciada - Usuari" #: ckan/templates/user/logout_first.html:7 msgid "Logged into" -msgstr "" +msgstr "Sessió iniciada a" #: ckan/templates/user/logout_first.html:12 msgid "is currently logged in" -msgstr "" +msgstr "ha iniciat sessió" #: ckan/templates/user/logout_first.html:15 msgid "To register or log in as another user, you need to" -msgstr "" +msgstr "Per registrar-vos o iniciar sessió com un altre usuari, heu de" #: ckan/templates/user/logout_first.html:17 msgid "logout" -msgstr "" +msgstr "tancar sessió" #: ckan/templates/user/logout_first.html:17 msgid "first." -msgstr "" +msgstr "primer." #: ckan/templates/user/new.html:5 msgid "Register - User" @@ -3290,7 +3291,7 @@ msgstr "Més de 3 caràcters, usant només 'a-z0-9' i '-_'" #: ckan/templates/user/new_user_form.html:27 msgid "Full name (optional)" -msgstr "" +msgstr "Nom complet (opcional)" #: ckan/templates/user/new_user_form.html:34 msgid "E-Mail" @@ -3298,7 +3299,7 @@ msgstr "Adreça electrònica" #: ckan/templates/user/new_user_form.html:65 msgid "Register now" -msgstr "" +msgstr "Registreu-vos ara" #: ckan/templates/user/perform_reset.html:18 msgid "Password (repeat):" diff --git a/ckan/i18n/es/LC_MESSAGES/ckan.mo b/ckan/i18n/es/LC_MESSAGES/ckan.mo index 7427d8879639d5041310adaf0b8d4ea9428e5009..d0fd00f452ebe7e1b605c112001fe1121e92f4e9 100644 GIT binary patch delta 75 zcmccjgZbVM<_+zgT&B7Ph6+Z8Rwf3UCw96!>8K`_<|QhWBqrq~Dx{<;xFnV&2AAX) cr7Bb^07V=FJVBx6GRrDwHH9Skq$;Q;x+In)2AAX) cr7Bb^0L2^wJXMoGGAW5A`Nf-A&O{ji03v4^uK)l5 diff --git a/ckan/i18n/es/LC_MESSAGES/ckan.po b/ckan/i18n/es/LC_MESSAGES/ckan.po index c07bdf4ed72..be5243755d9 100644 --- a/ckan/i18n/es/LC_MESSAGES/ckan.po +++ b/ckan/i18n/es/LC_MESSAGES/ckan.po @@ -15,7 +15,7 @@ msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-29 18:47+0000\n" +"PO-Revision-Date: 2012-05-01 21:40+0000\n" "Last-Translator: amercader \n" "Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/ckan/language/es/)\n" "MIME-Version: 1.0\n" @@ -1764,7 +1764,7 @@ msgstr "Aquí puedes usar %aformato Markdown%b." #: ckan/templates/js_strings.html:69 msgid "" "Should a %aDataStore table and Data API%b be enabled for this resource?" -msgstr "¿Quieres habilitar una tabla de %aDataStore y la API%b de datos para este recurso?" +msgstr "¿Quieres habilitar %auna tabla de DataStore y la API de datos%b para este recurso?" #: ckan/templates/js_strings.html:70 #, python-format diff --git a/ckan/i18n/sk/LC_MESSAGES/ckan.mo b/ckan/i18n/sk/LC_MESSAGES/ckan.mo index b0434bd8edb6c6d849bc03a6e406b3cd8c5c6093..2d2ce32c355e6d639b638ae02ef922fd33f85037 100644 GIT binary patch delta 5837 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 Q*yDZ^pDTOe;;(^!06roQbpQYW delta 5821 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\n" +"PO-Revision-Date: 2012-04-30 12:07+0000\n" +"Last-Translator: Jakub Kapus \n" "Language-Team: Slovak (http://www.transifex.net/projects/p/ckan/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1807,7 +1807,7 @@ msgstr "Hľadať" #: ckan/templates/home/about.html:9 ckan/templates/user/edit_user_form.html:39 #: ckan/templates/user/read.html:28 msgid "About" -msgstr "O" +msgstr "O projekte" #: ckan/templates/layout_base.html:94 msgid "Page Logo" @@ -2414,7 +2414,7 @@ msgstr "obsahuje" #: ckan/templates/home/index.html:24 msgid "datasets" -msgstr "datasety" +msgstr "datasetov" #: ckan/templates/home/index.html:24 msgid "" From 84817a91cf57d94c2612d8d5a188ac53b20ea81f Mon Sep 17 00:00:00 2001 From: kindly Date: Thu, 3 May 2012 11:07:33 +0100 Subject: [PATCH 079/109] [xs] make sure tracking summary does not get shown on edit of resources --- ckan/lib/dictization/model_dictize.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ckan/lib/dictization/model_dictize.py b/ckan/lib/dictization/model_dictize.py index 74aa8b78877..118ebb3e714 100644 --- a/ckan/lib/dictization/model_dictize.py +++ b/ckan/lib/dictization/model_dictize.py @@ -98,9 +98,10 @@ def resource_dictize(res, context): if extras: resource.update(extras) #tracking - model = context['model'] - tracking = model.TrackingSummary.get_for_resource(res.url) - resource['tracking_summary'] = tracking + if not context.get('for_edit'): + model = context['model'] + tracking = model.TrackingSummary.get_for_resource(res.url) + resource['tracking_summary'] = tracking return resource def related_dictize(rel, context): From 916c67f5e98973d6bd164a4aa4105f4550d3f410 Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 3 May 2012 11:14:45 +0100 Subject: [PATCH 080/109] [css][xs] Fix vertical alignment of small logos on footer --- ckan/public/css/style.css | 4 ---- ckan/templates/layout_base.html | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/ckan/public/css/style.css b/ckan/public/css/style.css index d0d261cf8a8..bc31fa287e8 100644 --- a/ckan/public/css/style.css +++ b/ckan/public/css/style.css @@ -126,10 +126,6 @@ footer a { text-decoration: none; } -footer #footer-okf-logo { - margin-bottom: -4px; -} - footer h3 { font-size: 1.2em; } diff --git a/ckan/templates/layout_base.html b/ckan/templates/layout_base.html index b6b4f46d7d2..d59ad94671e 100644 --- a/ckan/templates/layout_base.html +++ b/ckan/templates/layout_base.html @@ -206,7 +206,7 @@

    Meta

    Open Knowledge Foundation Licensed under the Open Database License - This Content and Data is Open + This Content and Data is Open

    Powered by CKAN v${c.__version__}.
    From 9ed0853547f88c90074efed4075f6fccdecb8e3c Mon Sep 17 00:00:00 2001 From: Toby Date: Thu, 3 May 2012 13:19:33 +0100 Subject: [PATCH 081/109] [xs] fix minor issue with sidebar in search results --- ckan/templates/package/search.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan/templates/package/search.html b/ckan/templates/package/search.html index cee817e4571..1414640dd1c 100644 --- a/ckan/templates/package/search.html +++ b/ckan/templates/package/search.html @@ -26,7 +26,7 @@

    Add a dataset

    ${facet_div('groups', 'Groups')}
  • -

    Other access

    +

    Other access

    Date: Thu, 3 May 2012 13:58:16 +0100 Subject: [PATCH 082/109] [xs] pkg_dict should be created from database not repopulated data --- ckan/controllers/package.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ckan/controllers/package.py b/ckan/controllers/package.py index 9e99e0fae3c..346f1e7c548 100644 --- a/ckan/controllers/package.py +++ b/ckan/controllers/package.py @@ -452,16 +452,17 @@ def edit(self, id, data=None, errors=None, error_summary=None): 'user': c.user or c.author, 'extras_as_string': True, 'save': 'save' in request.params, 'moderated': config.get('moderated'), - 'for_edit': True, 'pending': True,} if context['save'] and not data: return self._save_edit(id, context) try: + c.pkg_dict = get_action('package_show')(context, {'id':id}) + context['for_edit'] = True old_data = get_action('package_show')(context, {'id':id}) + # old data is from the database and data is passed from the + # user if there is a validation error. Use users data if there. data = data or old_data - # Merge all elements for the complete package dictionary - c.pkg_dict = dict(old_data.items() + data.items()) except NotAuthorized: abort(401, _('Unauthorized to read package %s') % '') except NotFound: From 07182719c6bb1f0a2fcdbae190d6345ca24f697c Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 3 May 2012 14:06:38 +0100 Subject: [PATCH 083/109] [xs] Change mentions to the Open Data Manual to Handbook --- ckan/templates/home/about.html | 2 +- ckan/templates/home/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ckan/templates/home/about.html b/ckan/templates/home/about.html index 1df29954903..05b5bc99fb3 100644 --- a/ckan/templates/home/about.html +++ b/ckan/templates/home/about.html @@ -29,7 +29,7 @@

    How it works

    Open data and the Open Knowledge Foundation

    -

    Most of the data indexed at ${g.site_title} is openly licensed, meaning anyone is free to use or re-use it however they like. Perhaps someone will take that nice dataset of a city's public art that you found, and add it to a tourist map - or even make a neat app for your phone that'll help you find artworks when you visit the city. Open data means more enterprise, collaborative science and transparent government. You can read more about open data in the Open Data Manual.

    +

    Most of the data indexed at ${g.site_title} is openly licensed, meaning anyone is free to use or re-use it however they like. Perhaps someone will take that nice dataset of a city's public art that you found, and add it to a tourist map - or even make a neat app for your phone that'll help you find artworks when you visit the city. Open data means more enterprise, collaborative science and transparent government. You can read more about open data in the Open Data Handbook.

    The Open Knowledge Foundation is a non-profit organisation promoting open knowledge: writing and improving CKAN is one of the ways we do that. If you want to get involved with its design or code, join the discussion or development mailing lists, or take a look at the OKFN site to find out about our other projects.

    diff --git a/ckan/templates/home/index.html b/ckan/templates/home/index.html index 7ef7cf45c2b..46cbebcef0e 100644 --- a/ckan/templates/home/index.html +++ b/ckan/templates/home/index.html @@ -53,7 +53,7 @@

    Collaborate

  • From 07f78e18bff068d9e9172b686692f8f9bcd89e53 Mon Sep 17 00:00:00 2001 From: Aron Carroll Date: Thu, 3 May 2012 14:50:06 +0100 Subject: [PATCH 084/109] Move the search button inline with input This has restructured the HTML used in the search_form.html which may break extensions. Particularly the spacial extension which uses this hook. --- ckan/public/css/style.css | 19 +++++++++++-------- ckan/templates/package/search_form.html | 4 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ckan/public/css/style.css b/ckan/public/css/style.css index bc31fa287e8..7a3e5e75ef6 100644 --- a/ckan/public/css/style.css +++ b/ckan/public/css/style.css @@ -737,25 +737,28 @@ body.package.search #menusearch { } .dataset-search { margin-bottom: 35px; + padding-right: 100px; } input.search { width: 100%; + float: left; font-size: 1.2em; margin: 0px; border: 1px solid #ccc; - padding: 0.5em; + padding: 0.6em 0.5em 0.6em 5px; font-weight: bold; - -moz-border-radius: 5px; + -moz-border-radius: 5px; -webkit-border-radius: 5px; - border-radius: 5px; - -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; + border-radius: 5px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; } .dataset-search input.button { display: inline-block; - float: right; - margin-top: 5px; - margin-right: 10px !important; - margin-bottom: 1px !important; + float: left; + margin-left: 9px; + margin-right: -100px; } diff --git a/ckan/templates/package/search_form.html b/ckan/templates/package/search_form.html index ba15882d89d..e7812343599 100644 --- a/ckan/templates/package/search_form.html +++ b/ckan/templates/package/search_form.html @@ -5,15 +5,15 @@ py:strip="" > - + +
    - From dfadd64584695415b7961b93ae3690549fbd6faf Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 3 May 2012 15:23:59 +0100 Subject: [PATCH 085/109] [release-v1.7] Update CHANGELOG --- CHANGELOG.txt | 61 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b44511ccafe..e25acb7c888 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,45 @@ CKAN CHANGELOG ++++++++++++++ +v1.7 2012-05-04 +=============== + +Major: + * Updated SOLR schema (#2327). Note: This will require and update of the SOLR schema file and a reindex. + * Support for Organization based workflow, with membership determinig access permissions to datasets (#1669,#2255) + * Related items such as visualizations, applications or ideas can now be added to datasets (#2204) + * Restricted vocabularies for tags, allowing grouping related tags together (#1698) + * Internal analytics that track number of views and downloads for datasets and resources (#2251) + * Consolidated multilingual features in an included extension (#1821,#1820) + * Atom feeds for publishers, tags and search results (#1593,#2277) + * RDF dump paster command (#2303) + * Better integration with the DataStore, based on ElasticSearch, with nice helper docs (#1797) + * Updated the Recline data viewer with new features such as better graphs and a map view (#2236,#2283) + * Improved and redesigned documentation (#2226,#2245,#2248) + +Minor: + * Groups can have an image associated (#2275) + * Basic resource validation (#1711) + * Ability to search without accents for accented words (#906) + * Weight queries so that title is more important than rest of body (#1826) + * Enhancements in the dataset and resource forms (#1506) + * OpenID can now be disabled (#1830) + * API and forms use same validation (#1792) + * More robust bulk search indexing, with options to ignore exceptions and just refresh (#1616i,#2232) + * Modify where the language code is placed in URLs (#2261) + * Simplified licenses list (#1359) + * Add extension point for dataset view (#1741) + +Bug fixes: + * Catch exceptions on the QA archiver (#1809) + * Error when changing language when CKAN is mounted in URL (#1804) + * Naming of a new package/group can clash with a route (#1742) + * Can't delete all of a package's resources over REST API (#2266) + * Group edit form didn't allow adding multiple datasets at once (#2292) + * Fix layout bugs in IE 7 (#1788) + * Bug with Portugese translation and Javascript (#2318) + * Fix broken parse_rfc_2822 helper function (#2314) + v1.6 2012-02-24 =============== @@ -158,7 +197,7 @@ Minor: * Speed up tag reading (98d72) * Cope with new WebOb version 1 (#1267) * Avoid exceptions caused by bots hitting error page directly (#1176) - * Too minor to mention: #1234, + * Too minor to mention: #1234, Bug fixes: * Re-adding tags to a package failed (since 1.4.1 in Web UI, 1.4 in API) (#1239) @@ -197,7 +236,7 @@ Major: * Refactor Web interface to use logic layer rather than model objects directly. Forms now defined in navl schema and designed in HTML template. Forms use of Formalchemy is deprecated. (#1078) Minor: - * Links in user-supplied text made less attractive to spammers (nofollow) #1181 + * Links in user-supplied text made less attractive to spammers (nofollow) #1181 * Package change notifications - remove duplicates (#1149) * Metadata dump linked to (#1169) * Refactor authorization code to be common across Package, Group and Authorization Group (#1074) @@ -223,7 +262,7 @@ Bug fixes: * Visitor can't create packages on new CKAN install - since v1.3.3 (#1090) * OpenID user pages couldn't be accessed - since v1.3.2 (#1056) * Default site_url configured to ckan.net, so pages obtains CSS from ckan.net- since v1.3 (#1085) - + v1.3.3 2011-04-08 ================= @@ -256,7 +295,7 @@ Major: * Resources can have extra fields (although not in web interface yet) (#826) * CSW Harvesting - numerous of fixes & improvements. Ready for deployment. (#738 etc) * Language switcher (82002) - + Minor: * Wordpress integration refactored as a Middleware plugin (#1013) * Unauthorized actions lead to a flash message (#366) @@ -308,7 +347,7 @@ Highlights of changes: * WordPress twentyten compatible theming (#797) * Caching support (ETag) (#693) * Harvesting GEMINI2 metadata records from OGC CSW servers (#566) - + Minor: * New API key header (#466) * Group metadata now revisioned (#231) @@ -326,14 +365,14 @@ Highlights of changes: * Resource search in API (#336) * Visual theming of CKAN now easy (#340, #320) * Greater integration with external Web UIs (#335, #347, #348) - * Plug-ins can be configured to handle web requests from specified URIs and + * Plug-ins can be configured to handle web requests from specified URIs and insert HTML into pages. Minor: * Search engine optimisations e.g. alphabetical browsing (#350) * CSV and JSON dumps improved (#315) - + v1.0.2 2010-08-27 ================= @@ -384,7 +423,7 @@ Highlights of changes: (#247) Bugfixes: - + * Resources were losing their history (#292) * Extra fields now work with spaces in the name (#278, #280) and international characters (#288) @@ -426,7 +465,7 @@ For a full listing of tickets see: . Main highl * Change to UUIDs for revisions and all domain objects * Improved search performance and better pagination - * Significantly improved performance in API and WUI via judicious caching + * Significantly improved performance in API and WUI via judicious caching v0.10 2009-09-30 @@ -446,7 +485,7 @@ v0.10 2009-09-30 * Convert to use formalchemy for all forms (#76) * Use paginate in webhelpers (#118) - * Minor: + * Minor: * Add author and maintainer attributes to package (#91) * Change package state in the WUI (delete and undelete) (#126) @@ -491,7 +530,7 @@ v0.6 2008-07-08 * Autocompletion (+ suggestion) of tags when adding tags to a package. * Paginated lists for packages, tags, and revisions. * RESTful machine API for package access, update, listing and creation. - * API Keys for users who wish to modify information via the REST API. + * API Keys for users who wish to modify information via the REST API. * Update to vdm v0.2 (SQLObject) which fixes ordering of lists. * Better immunity to SQL injection attacks. From 3f97ad65195828bc26e94944ce01deca31e16a88 Mon Sep 17 00:00:00 2001 From: Ross Jones Date: Thu, 3 May 2012 16:27:35 +0100 Subject: [PATCH 086/109] [bug] Fix to extraneous fields in context for member api --- ckan/logic/action/create.py | 5 +++-- ckan/logic/action/delete.py | 5 ++--- ckan/logic/action/get.py | 5 ++--- ckan/tests/logic/test_member.py | 6 ++---- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/ckan/logic/action/create.py b/ckan/logic/action/create.py index aee73a32aa4..e6be5a391eb 100644 --- a/ckan/logic/action/create.py +++ b/ckan/logic/action/create.py @@ -11,6 +11,7 @@ import ckan.lib.dictization.model_dictize as model_dictize import ckan.lib.dictization.model_save as model_save import ckan.lib.navl.dictization_functions +import ckan.logic.auth as auth # FIXME this looks nasty and should be shared better from ckan.logic.action.update import _update_package_relationship @@ -196,7 +197,7 @@ def member_create(context, data_dict=None): user - The name of the current user data_dict: - group - The ID of the group to which we want to add a new object + id - The ID of the group to which we want to add a new object object - The ID of the object being added as a member object_type - The name of the type being added, all lowercase, e.g. package, or user @@ -204,7 +205,6 @@ def member_create(context, data_dict=None): """ model = context['model'] user = context['user'] - group = context['group'] rev = model.repo.new_revision() rev.author = user @@ -213,6 +213,7 @@ def member_create(context, data_dict=None): else: rev.message = _(u'REST API: Create member object %s') % data_dict.get("name", "") + group = model.Group.get(data_dict.get('id', '')) obj_id = data_dict['object'] obj_type = data_dict['object_type'] capacity = data_dict['capacity'] diff --git a/ckan/logic/action/delete.py b/ckan/logic/action/delete.py index c806a5113cd..4dd5c701a4d 100644 --- a/ckan/logic/action/delete.py +++ b/ckan/logic/action/delete.py @@ -90,16 +90,15 @@ def member_delete(context, data_dict=None): user - The name of the current user data_dict: - group - The ID of the group to which we want to remove object + id - The ID of the group from which we want to remove object object - The ID of the object being removed as a member object_type - The name of the type being removed, all lowercase, e.g. package, or user """ model = context['model'] user = context['user'] - group = context['group'] - group_id = data_dict['group'] + group = model.Group.get(data_dict.get('id')) obj_id = data_dict['object'] obj_type = data_dict['object_type'] diff --git a/ckan/logic/action/get.py b/ckan/logic/action/get.py index b2afe947171..b0cb640802c 100644 --- a/ckan/logic/action/get.py +++ b/ckan/logic/action/get.py @@ -179,16 +179,15 @@ def member_list(context, data_dict=None): user - The name of the current user data_dict: - group - The ID of the group to which we want to list members + id - The ID of the group to which we want to list members object_type - The optional name of the type being added, all lowercase, e.g. package, or user capacity - The optional capacity of objects that we want to retrieve """ model = context['model'] user = context['user'] - group = context['group'] - group_id = data_dict['group'] + group = model.Group.get(data_dict.get('id','')) obj_type = data_dict.get('object_type', None) capacity = data_dict.get('capacity', None) diff --git a/ckan/tests/logic/test_member.py b/ckan/tests/logic/test_member.py index 04af59d53c8..3d6294e2913 100644 --- a/ckan/tests/logic/test_member.py +++ b/ckan/tests/logic/test_member.py @@ -21,14 +21,12 @@ def teardown_class(cls): model.repo.rebuild_db() def _build_context( self, obj, obj_type, capacity='public'): - grp = model.Group.by_name(self.groupname) ctx = { 'model': model, 'session': model.Session, - 'user':self.username, - 'group': grp, + 'user':self.username } dd = { - 'group': grp, + 'id': self.groupname, 'object': obj, 'object_type': obj_type, 'capacity': capacity } From bf4735f52c2a7050d038af6d9bc33ab491a1adbd Mon Sep 17 00:00:00 2001 From: amercader Date: Fri, 4 May 2012 12:41:13 +0100 Subject: [PATCH 087/109] [doc][xs] Minor cleaning up of the docs --- doc/api-v2.rst | 1 - doc/background-tasks.rst | 5 ++++- doc/publisher-profile.rst | 1 + doc/writing-extensions.rst | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/api-v2.rst b/doc/api-v2.rst index 80da2e3b1a5..a972f55f343 100644 --- a/doc/api-v2.rst +++ b/doc/api-v2.rst @@ -6,7 +6,6 @@ The CKAN API version 1 & 2 is separated into three parts. * `Model API`_ * `Search API`_ -* `Util API`_ The resources, methods, and data formats of each are described below. diff --git a/doc/background-tasks.rst b/doc/background-tasks.rst index 9f626b0ec84..89483b63414 100644 --- a/doc/background-tasks.rst +++ b/doc/background-tasks.rst @@ -23,11 +23,14 @@ Enabling Background Tasks To manage and run background tasks requires a job queue and CKAN uses celery_ (plus the CKAN database) for this purpose. Thus, to use background tasks you -need to install and run celery_. +need to install and run celery_. As of CKAN 1.7, celery is a required library +and will be already installed after a default CKAN install. Installation of celery_ will normally be taken care of by whichever component or extension utilizes it so we skip that here. +.. _celery: http://celeryproject.org/ + To run the celery daemon you have two options: 1. In development setup you can just use paster. This can be done as simply diff --git a/doc/publisher-profile.rst b/doc/publisher-profile.rst index a75728a3d54..75b201969c9 100644 --- a/doc/publisher-profile.rst +++ b/doc/publisher-profile.rst @@ -35,6 +35,7 @@ This setup is a natural one for many situations. For example: Whilst organizations can currently belong to other organizations the publisher authorization profile currently only checks membership of the current organization. Future versions of this extension may provide a configuration option to apply authorization checks hierarchically. .. _publisher-configuration: + Enabling and Configuring the Publisher Profile ============================================== diff --git a/doc/writing-extensions.rst b/doc/writing-extensions.rst index 5e3aeee6b46..56be5996097 100644 --- a/doc/writing-extensions.rst +++ b/doc/writing-extensions.rst @@ -167,6 +167,8 @@ Alternatively see the `Plugin API documentation`_ below. .. should be renamed in the code to not have the word 'Extension' in their names. +.. _PyUtilib: https://software.sandia.gov/trac/pyutilib + Example CKAN Extension ---------------------- From 9de8f8f4fe293c445fa920bd9b7480b19bf88ac0 Mon Sep 17 00:00:00 2001 From: amercader Date: Fri, 4 May 2012 12:56:58 +0100 Subject: [PATCH 088/109] [i18n] Update Finnish translation --- ckan/i18n/fi/LC_MESSAGES/ckan.mo | Bin 62833 -> 63175 bytes ckan/i18n/fi/LC_MESSAGES/ckan.po | 228 ++++++++++++++++--------------- 2 files changed, 115 insertions(+), 113 deletions(-) diff --git a/ckan/i18n/fi/LC_MESSAGES/ckan.mo b/ckan/i18n/fi/LC_MESSAGES/ckan.mo index e19d09d7b83e053a82b1dc96ea1a5223ca81ccdc..55173bdf657d06d640d4f950ff3c9b3f8adb0a0e 100644 GIT binary patch delta 8930 zcmb8y33wDm-pBEta0CK^fXJbc4iE@PLO{?ppd5lih`>t#MP0QeqjY966Ei)LL2%S{ z^+8{OcUw?=RXpMeDms98p%@js4_p*s)fIF_MFfw1z4!Z@>IB!_XZKwm9zIpo)!kM9 z`d9U^|C1J*_qJFQJ^YaMAN#Ho^`Fxe z^rEiIjm3C4^$FMp&qTc_jEvQqkDB3kxEfnsXF~cAYRNXDp7$rzOut4&rq%UkV%<pcpSxzPFs)*q*%lI2uX2?n1CPS}sNK-(cC!QpsQ$;GUN{4L;OVH{DAcM@4cm>O5G58tB`oNbE;NqWc|YU<2+T{tE2`8uHP> z)A3SN1a@L;{0J4|z1R~^<_@M&mMcTnfe zWoZiSC@e?4;5KZ951>N24i)m3QQK`-aQ$;^P5mn@#P3o43hptHI~J82V^K?S4(j>W z;3&KS_1^Sb6lPJ_g(qOyy=G=9RAes2wzvfKz!j+dy&>>r)VBK|s2{z`Okg6OO#2ip zz~z{$`%uq&3Q5Ma^#TR0+3vtEQ8UX~ZIZ4nYCrcx&2&2IsGWzJ@ztmY---(9J%LYP z8|tqIz7x0$HGt2so%a7X!G)arOp>(296B6<+6}$2B`(A~ybRmnHE4y12x>q#+;6h~ zJ{(N_1ypkX67;MJ&*tqAJt0vl0D z^g1dDzeF80o!6Qi7=jb1Pe2X)YE({KhdQ`cq6W4GwUm#bBC>HU@z+SV(4YsuhZ@LF zsDq;YI#Vx4T|W)aBRMWaE!DdZTUG;pihA(U4d!FB42!8hgQa)?hhpDH*bz7rM`J^p zf@ZQCdtm5MGovF=p&yDG;3!ncDp4~@p!zRB&2TyP!@IB&UqVg9e#{J@1l9j+JPcET z>BSWEk+>bT6q|wzZ=w#MJ=h&XkDImYiJJL1RB}#5-9HQUU=Q`2Mc5T@#Bul#j>oTY z5SBfW{d%UYFa^zU8R~}BsF6O6N|v3d8MfTW3)x0pCG{hpG-rEX>_mM4Y5>QfvU>_D zg1^NsI2Sdc1*phei^H`4Z=+B`!yoYoZ26SA(Z-(Ck3xMsPC|u#7V3p(qh@*mDw!_F zxwsf-;$N{GPuXO0>3Zx>eH-c^`w<85eyi`(X5^DmBR(fEf<@HpgX=3%$+R}8e~60M zcc=&++GtrP;sDfhBB)(ZkNJ2pYAJ6Taj*8&!XNkW;_YDob(0b0Sb#GJ-48bFD z68;9y3$Cw3J!lPT0*$ChycN{b`R^7n7Tbze2Z=1|`|GsI|TW z_26}=HGe+v4J@R-BdCYAmvk2IQgMm!3}{ zkHYWpI9!YaaSMj=04iBdd(r&-e%s!a=C^ay%K6cwva&|2T*Gh*!;Lb_EWg{v4|R=cruh@fts~ za0uG?Kd1pegl+L{JVyKf0}5kl=<⋘Tc#;eJN_Dn^2MY7zbmYH_TBx70al5s3mv+ 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 W`jYbbt&5-M^1lVnEWhX1r~VBljyCWB delta 6604 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 diff --git a/ckan/i18n/fi/LC_MESSAGES/ckan.po b/ckan/i18n/fi/LC_MESSAGES/ckan.po index a9ce4d517db..dde4beb8746 100644 --- a/ckan/i18n/fi/LC_MESSAGES/ckan.po +++ b/ckan/i18n/fi/LC_MESSAGES/ckan.po @@ -3,8 +3,10 @@ # This file is distributed under the same license as the ckan project. # # Translators: +# , 2012. # henkka , 2011. # , 2012. +# , 2012. # , 2011. # , 2012. # okfn , 2011. @@ -13,8 +15,8 @@ msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" -"Last-Translator: Sean Hammond \n" +"PO-Revision-Date: 2012-05-04 11:53+0000\n" +"Last-Translator: amercader \n" "Language-Team: Finnish (http://www.transifex.net/projects/p/ckan/language/fi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -506,11 +508,11 @@ msgstr "%s kirjautuneena sisään" #: ckan/controllers/user.py:279 msgid "Login failed. Bad username or password." -msgstr "" +msgstr "Kirjautuminen epäonnistui. Väärä käyttäjätunnus tai salasana." #: ckan/controllers/user.py:281 msgid " (Or if using OpenID, it hasn't been associated with a user account.)" -msgstr "" +msgstr " (Tai jos käytät OpenID:tä, sitä ei ole liitetty käyttäjätiliisi.)" #: ckan/controllers/user.py:334 #, python-format @@ -559,7 +561,7 @@ msgstr "Nimi" #: ckan/forms/authorization_group.py:46 msgid "Unique identifier for group." -msgstr "" +msgstr "Uniikki tunniste ryhmälle." #: ckan/forms/authorization_group.py:47 ckan/forms/package.py:41 #: ckan/templates/group/new_group_form.html:36 @@ -573,7 +575,7 @@ msgstr "Yksityiskohdat" #: ckan/forms/authorization_group.py:80 msgid "Add users" -msgstr "" +msgstr "Lisää käyttäjiä" #: ckan/forms/common.py:26 ckan/logic/validators.py:185 #: ckan/logic/validators.py:420 @@ -871,15 +873,15 @@ msgstr "Anna käyttäjänimi" #: ckan/lib/helpers.py:504 msgid "Update your avatar at gravatar.com" -msgstr "" +msgstr "Päivitä avatarisi osoitteessa gravatar.com" #: ckan/lib/helpers.py:624 ckan/templates/js_strings.html:64 msgid "Unknown" -msgstr "" +msgstr "Tuntematon" #: ckan/lib/helpers.py:660 msgid "no name" -msgstr "" +msgstr "ei nimeä" #: ckan/lib/helpers.py:693 msgid "Created new dataset." @@ -932,11 +934,11 @@ msgstr "Web sivua ei annettu" #: ckan/lib/package_saver.py:38 msgid "Author not given" -msgstr "" +msgstr "Laatijaa ei ole annettu" #: ckan/lib/package_saver.py:44 msgid "Maintainer not given" -msgstr "" +msgstr "Ylläpitäjää ei ole annettu" #: ckan/lib/package_saver.py:101 ckan/logic/validators.py:51 msgid "No links are allowed in the log_message." @@ -958,11 +960,11 @@ msgstr "Puuttuva arvo" #: ckan/lib/navl/validators.py:54 #, python-format msgid "The input field %(name)s was not expected." -msgstr "" +msgstr "Syöttökenttää %(name)s ei odotettu." #: ckan/lib/navl/validators.py:93 msgid "Please enter an integer value" -msgstr "" +msgstr "Ole hyvä ja syötä kokonaislukuarvo" #: ckan/logic/__init__.py:159 msgid "No valid API key provided." @@ -1160,7 +1162,7 @@ msgstr "Ei löytynyt avainsanaa %s" #: ckan/logic/action/update.py:114 msgid "Related was not found." -msgstr "" +msgstr "Liittyvää ei löydetty." #: ckan/logic/action/update.py:142 msgid "Resource was not found." @@ -1197,7 +1199,7 @@ msgstr "Käyttäjällä %s ei ole oikeuksia muokata näitä ryhmiä" #: ckan/logic/auth/create.py:28 ckan/logic/auth/publisher/create.py:31 msgid "You must be logged in to add a related item" -msgstr "" +msgstr "Sinun täytyy olla kirjautunut lisätäksesi liittyvä asia" #: ckan/logic/auth/create.py:48 ckan/logic/auth/publisher/create.py:60 #, python-format @@ -1241,7 +1243,7 @@ msgstr "Käyttäjällä %s ei ole oikeuksia poistaa tietoaineistoa %s" #: ckan/logic/auth/publisher/delete.py:36 #: ckan/logic/auth/publisher/delete.py:44 msgid "Only the owner can delete a related item" -msgstr "" +msgstr "Vain omistaja voi poistaa liittyvän asian" #: ckan/logic/auth/delete.py:47 #, python-format @@ -1312,7 +1314,7 @@ msgstr "Käyttäjällä %s ei ole oikeuksia muokata ryhmää %s" #: ckan/logic/auth/publisher/update.py:95 #: ckan/logic/auth/publisher/update.py:100 msgid "Only the owner can update a related item" -msgstr "" +msgstr "Vain omistaja voi päivittää liittyvän asian" #: ckan/logic/auth/update.py:106 #, python-format @@ -1347,7 +1349,7 @@ msgstr "Käyttäjällä %s ei ole oikeutta päivittää task_status taulua" #: ckan/logic/auth/update.py:191 ckan/logic/auth/publisher/update.py:161 #, python-format msgid "User %s not authorized to update term_translation table" -msgstr "" +msgstr "Käyttäjällä %s ei ole oikeuksia päivittää term_translation taulua" #: ckan/logic/auth/update.py:201 ckan/logic/auth/publisher/update.py:174 msgid "Valid API key needed to edit a package" @@ -1429,27 +1431,27 @@ msgstr "Käyttöoikeusryhmän päivitystä ei ole toteutettu" #: ckan/model/license.py:61 msgid "License Not Specified" -msgstr "" +msgstr "Lisenssiä ei määritelty" #: ckan/model/license.py:166 msgid "Other (Open)" -msgstr "" +msgstr "Muu (Open)" #: ckan/model/license.py:180 msgid "Other (Public Domain)" -msgstr "" +msgstr "Muu (Public Domain)" #: ckan/model/license.py:194 msgid "Other (Attribution)" -msgstr "" +msgstr "Muu (Attribution)" #: ckan/model/license.py:234 msgid "Other (Non-Commercial)" -msgstr "" +msgstr "Muu (Non-Commercial)" #: ckan/model/license.py:248 msgid "Other (Not Open)" -msgstr "" +msgstr "Muu (Not Open)" #: ckan/model/package_relationship.py:48 #, python-format @@ -1545,11 +1547,11 @@ msgstr "Ei ladattavia resursseja." #: ckan/templates/_util.html:138 msgid "No description for this item" -msgstr "" +msgstr "Tällä asialla ei ole kuvausta" #: ckan/templates/_util.html:139 msgid "View this related item" -msgstr "" +msgstr "Näytä tähän liittyvä asia" #: ckan/templates/_util.html:161 msgid "no ratings yet" @@ -1571,7 +1573,7 @@ msgstr "Virhe" #: ckan/templates/facets.html:162 msgid "(facet_item['count'])" -msgstr "" +msgstr "(facet_item['count'])" #: ckan/templates/js_strings.html:16 msgid "Checking..." @@ -1625,23 +1627,23 @@ msgstr "Poista tietoaineistolinkki '%name%'?" #: ckan/templates/js_strings.html:28 msgid "Preview not available for data type: " -msgstr "" +msgstr "Tälle tietotyypille ei ole esikatselua:" #: ckan/templates/js_strings.html:29 msgid "Failed to get credentials for storage upload. Upload cannot proceed" -msgstr "" +msgstr "Kirjautumistietojen saanti epäonnistui tallennusta varten. Tallenusta ei voida jatkaa" #: ckan/templates/js_strings.html:30 msgid "Checking upload permissions ..." -msgstr "" +msgstr "Tarkistetaan tallennuksen käyttöoikeuksia ..." #: ckan/templates/js_strings.html:31 msgid "Uploading file ..." -msgstr "" +msgstr "Tallennetaan tiedostoa ..." #: ckan/templates/js_strings.html:32 msgid "Data File" -msgstr "" +msgstr "Data tiedosto" #: ckan/templates/js_strings.html:33 ckan/templates/layout_base.html:144 #: ckan/templates/package/search.html:37 @@ -1650,27 +1652,27 @@ msgstr "API" #: ckan/templates/js_strings.html:34 msgid "Visualization" -msgstr "" +msgstr "Visualisointi" #: ckan/templates/js_strings.html:35 msgid "Image" -msgstr "" +msgstr "Kuva" #: ckan/templates/js_strings.html:36 msgid "Metadata" -msgstr "" +msgstr "Metatieto" #: ckan/templates/js_strings.html:37 msgid "Documentation" -msgstr "" +msgstr "Dokumentaatio" #: ckan/templates/js_strings.html:38 msgid "Code" -msgstr "" +msgstr "Koodi" #: ckan/templates/js_strings.html:39 msgid "Example" -msgstr "" +msgstr "Esimerkki" #: ckan/templates/js_strings.html:44 ckan/templates/storage/index.html:6 #: ckan/templates/storage/index.html:15 ckan/templates/storage/success.html:6 @@ -1713,7 +1715,7 @@ msgstr "Sisältötyyppi (Mime)" #: ckan/templates/js_strings.html:54 msgid "Created" -msgstr "" +msgstr "Luotu" #: ckan/templates/js_strings.html:55 msgid "Last Modified" @@ -1741,38 +1743,38 @@ msgstr "Tässä resurssissa on tallentamattomia muutoksia" #: ckan/templates/js_strings.html:63 msgid "e.g. csv, html, xls, rdf, ..." -msgstr "" +msgstr "esimerkiksi csv, html, xls, rdf, ..." #: ckan/templates/js_strings.html:65 msgid "Extra Fields" -msgstr "" +msgstr "Lisäkentät" #: ckan/templates/js_strings.html:66 msgid "Add Extra Field" -msgstr "" +msgstr "Lisää lisäkenttä" #: ckan/templates/js_strings.html:67 msgid "Delete Resource" -msgstr "" +msgstr "Poista resurssi" #: ckan/templates/js_strings.html:68 msgid "You can use %aMarkdown formatting%b here." -msgstr "" +msgstr "Voit käyttää %aMarkdown formatting%b tässä." #: ckan/templates/js_strings.html:69 msgid "" "Should a %aDataStore table and Data API%b be enabled for this resource?" -msgstr "" +msgstr "Onko tarvetta %aDataStore taulu and Data API%b aktivoida tälle resurssille?" #: ckan/templates/js_strings.html:70 #, python-format msgid "" "Dates are in %aISO Format%b — eg. %c2012-12-25%d or %c2010-05-31T14:30%d." -msgstr "" +msgstr "Päiväykset ovat %aISO Format%b — esimerkiksi. %c2012-12-25%d tai %c2010-05-31T14:30%d." #: ckan/templates/js_strings.html:71 msgid "Data File (Uploaded)" -msgstr "" +msgstr "Datatiedosto (Tallennettu)" #: ckan/templates/layout_base.html:56 ckan/templates/user/logout.html:7 msgid "Logout" @@ -1810,7 +1812,7 @@ msgstr "Tietoa" #: ckan/templates/layout_base.html:94 msgid "Page Logo" -msgstr "" +msgstr "Sivun logo" #: ckan/templates/layout_base.html:112 msgid "Master content template placeholder … please replace me." @@ -1898,67 +1900,67 @@ msgstr "v" #: ckan/templates/activity_streams/added_tag.html:8 msgid "{actor} added the tag {object} to the dataset {target}" -msgstr "" +msgstr "{actor} lisäsi {object} tietoaineistoon {target}" #: ckan/templates/activity_streams/changed_group.html:8 msgid "{actor} updated the group {object}" -msgstr "" +msgstr "{actor} päivitti ryhmää {object}" #: ckan/templates/activity_streams/changed_package.html:8 msgid "{actor} updated the dataset {object}" -msgstr "" +msgstr "{actor} päivitti tietoaineistoa {object}" #: ckan/templates/activity_streams/changed_package_extra.html:8 msgid "{actor} changed the extra {object} of the dataset {target}" -msgstr "" +msgstr "{actor} muutti lisäkenttää {object} tästä tietoaineistosta {target}" #: ckan/templates/activity_streams/changed_resource.html:8 msgid "{actor} updated the resource {object} in the dataset {target}" -msgstr "" +msgstr "{actor} päivitti resurssia {object} tietoaineistossa {target}" #: ckan/templates/activity_streams/changed_user.html:8 msgid "{actor} updated their profile" -msgstr "" +msgstr "{actor} päivitti profiiliaan" #: ckan/templates/activity_streams/deleted_group.html:8 msgid "{actor} deleted the group {object}" -msgstr "" +msgstr "{actor} poisti ryhmän {object}" #: ckan/templates/activity_streams/deleted_package.html:8 msgid "{actor} deleted the dataset {object}" -msgstr "" +msgstr "{actor} poisti tietoaineiston {object}" #: ckan/templates/activity_streams/deleted_package_extra.html:8 msgid "{actor} deleted the extra {object} from the dataset {target}" -msgstr "" +msgstr "{actor} poisti lisäkentän {object} tietoaineistosta {target}" #: ckan/templates/activity_streams/deleted_resource.html:8 msgid "{actor} deleted the resource {object} from the dataset {target}" -msgstr "" +msgstr "{actor} poisti resurssin {object} tietoaineistosta {target}" #: ckan/templates/activity_streams/new_group.html:8 msgid "{actor} created the group {object}" -msgstr "" +msgstr "{actor} loi ryhmän {object}" #: ckan/templates/activity_streams/new_package.html:8 msgid "{actor} created the dataset {object}" -msgstr "" +msgstr "{actor} loi tietoaineiston{object}" #: ckan/templates/activity_streams/new_package_extra.html:8 msgid "{actor} added the extra {object} to the dataset {target}" -msgstr "" +msgstr "{actor} lisäsi lisäkentän {object} tietoaineistoon {target}" #: ckan/templates/activity_streams/new_resource.html:8 msgid "{actor} added the resource {object} to the dataset {target}" -msgstr "" +msgstr "{actor} lisäsi resurssin {object} tietoaineistoon {target}" #: ckan/templates/activity_streams/new_user.html:8 msgid "{actor} signed up" -msgstr "" +msgstr "{actor} kirjautui sisään" #: ckan/templates/activity_streams/removed_tag.html:8 msgid "{actor} removed the tag {object} from the dataset {target}" -msgstr "" +msgstr "{actor} poisti avainsanan {object} tietoaineistosta {target}" #: ckan/templates/admin/authz.html:6 ckan/templates/admin/authz.html:7 msgid "Administration - Authorization" @@ -2089,7 +2091,7 @@ msgstr "Yhteensä [1:%(item_count)s] käyttöoikeusryhmää." #: ckan/templates/authorization_group/layout.html:11 #: ckan/templates/revision/layout.html:9 msgid "List" -msgstr "" +msgstr "Lista" #: ckan/templates/authorization_group/layout.html:14 #: ckan/templates/group/layout.html:12 ckan/templates/package/layout.html:10 @@ -2146,7 +2148,7 @@ msgstr "Päivitä olemassolevien pääsyryhmien rooleja" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 @@ -2228,7 +2230,7 @@ msgstr "Listaa ryhmät" #: ckan/templates/group/layout.html:35 msgid "Add a Group" -msgstr "" +msgstr "Lisää ryhmä" #: ckan/templates/group/layout.html:38 msgid "Login to Add a Group" @@ -2266,11 +2268,11 @@ msgstr "Aloita yhteenveto lauseella..." #: ckan/templates/group/new_group_form.html:47 msgid "Image URL:" -msgstr "" +msgstr "Kuvan URL:" #: ckan/templates/group/new_group_form.html:50 msgid "The URL for the image that is associated with this group." -msgstr "" +msgstr "URL kuvalle joka liitetty tälle ryhmälle" #: ckan/templates/group/new_group_form.html:57 #: ckan/templates/package/new_package_form.html:275 @@ -2295,17 +2297,17 @@ msgstr "Poista" #: ckan/templates/group/new_group_form.html:83 #: ckan/templates/package/new_package_form.html:251 msgid "Add..." -msgstr "" +msgstr "Lisää..." #: ckan/templates/group/new_group_form.html:86 #: ckan/templates/package/new_package_form.html:254 msgid "Key =" -msgstr "" +msgstr "Avain =" #: ckan/templates/group/new_group_form.html:90 #: ckan/templates/package/new_package_form.html:258 msgid "Value =" -msgstr "" +msgstr "Arvo =" #: ckan/templates/group/new_group_form.html:116 msgid "Add datasets" @@ -2419,7 +2421,7 @@ msgstr "tietoaineistoa" msgid "" "that you can \n" " browse, learn about and download." -msgstr "" +msgstr "jotta voit \n selata, oppia and ladata." #: ckan/templates/home/index.html:32 msgid "Share data" @@ -2540,7 +2542,7 @@ msgstr "arvolla" #: ckan/templates/package/history.html:37 #, python-format msgid "Read dataset as of %s" -msgstr "" +msgstr "Lue tietoaineisto alkaen %s" #: ckan/templates/package/history.html:48 ckan/templates/package/read.html:104 #: ckan/templates/package/related_list.html:50 @@ -2557,7 +2559,7 @@ msgstr "Lisää / Muokkaa aineistolinkkejä" #: ckan/templates/package/layout.html:39 msgid "Related" -msgstr "" +msgstr "Liittyvä" #: ckan/templates/package/layout.html:44 msgid "Settings" @@ -2591,7 +2593,7 @@ msgstr "(Älä huolehdi, jos et tiedä millä lisenssillä aineisto on julkaistu #: ckan/templates/package/new_package_form.html:96 msgid "Member of:" -msgstr "" +msgstr "Jäsen:" #: ckan/templates/package/new_package_form.html:109 msgid "Add to:" @@ -2605,7 +2607,7 @@ msgstr "Pilkuilla erotetut sanat jotka liittävät tietoaineiston samanlaisiin. #: ckan/templates/package/new_package_form.html:134 msgid "Add Resources" -msgstr "" +msgstr "Lisää resursseja" #: ckan/templates/package/new_package_form.html:136 msgid "" @@ -2638,7 +2640,7 @@ msgstr "Tiedoston URL" #: ckan/templates/package/new_package_form.html:165 msgid "API URL" -msgstr "" +msgstr "API URL" #: ckan/templates/package/new_package_form.html:228 msgid "e.g. 1.2.0" @@ -2674,11 +2676,11 @@ msgstr "Tämä tietoaineisto on" #: ckan/templates/package/new_package_form.html:285 msgid "Summary" -msgstr "" +msgstr "Yhteenveto" #: ckan/templates/package/new_package_form.html:287 msgid "Briefly describe the changes you have made..." -msgstr "" +msgstr "Kuvaa lyhyesti muutokset jotka teit..." #: ckan/templates/package/new_package_form.html:298 msgid "" @@ -2688,32 +2690,32 @@ msgstr "Koska et ole kirjautunut sisään niin IP osoitettasi käytetään\n[1:K #: ckan/templates/package/new_package_form.html:309 msgid "Important:" -msgstr "" +msgstr "Tärkeää:" #: ckan/templates/package/new_package_form.html:309 msgid "" "By submitting content, you agree to release your contributions under the" -msgstr "" +msgstr "Tallentamalla sisältöä, hyväksyt että ne julkaistaa tämän mukaisesti" #: ckan/templates/package/new_package_form.html:309 msgid ". Please" -msgstr "" +msgstr ". Ole hyvä" #: ckan/templates/package/new_package_form.html:309 msgid "refrain" -msgstr "" +msgstr "ja pidättäydy" #: ckan/templates/package/new_package_form.html:309 msgid "from editing this page if you are" -msgstr "" +msgstr "muokkaamasta tätä sivua jos" #: ckan/templates/package/new_package_form.html:309 msgid "not" -msgstr "" +msgstr "et" #: ckan/templates/package/new_package_form.html:309 msgid "happy to do this." -msgstr "" +msgstr "hyväksy tätä." #: ckan/templates/package/read.html:14 msgid "- Datasets" @@ -2814,27 +2816,27 @@ msgstr "[1:Tietoaineiston sivu] sivustolla \n [2:%(harvest_catalogue_ #: ckan/templates/package/related_list.html:17 #: ckan/templates/package/related_list.html:21 msgid "- Related" -msgstr "" +msgstr "- Liittyvät" #: ckan/templates/package/related_list.html:26 msgid "Related items" -msgstr "" +msgstr "Liittyvät asiat" #: ckan/templates/package/related_list.html:26 msgid "Add related item" -msgstr "" +msgstr "Lisää liittyvä asia" #: ckan/templates/package/related_list.html:28 msgid "There are no related items here yet" -msgstr "" +msgstr "Tähän liittyen ei ole vielä asioita" #: ckan/templates/package/related_list.html:29 msgid ", why not" -msgstr "" +msgstr ", mikset et" #: ckan/templates/package/related_list.html:29 msgid "add one" -msgstr "" +msgstr "lisäisi yhtä" #: ckan/templates/package/resource_embedded_dataviewer.html:78 #: ckan/templates/package/resource_read.html:85 @@ -2872,12 +2874,12 @@ msgstr "Lähtöisin [1:tietoaineistosta]:" #: ckan/templates/package/resource_read.html:174 msgid "Cannot embed as resource is private." -msgstr "" +msgstr "Ei voida upottaa koska resurssi on yksityinen." #: ckan/templates/package/resource_read.html:174 #: ckan/templates/package/resource_read.html:175 msgid "Embed" -msgstr "" +msgstr "Upota" #: ckan/templates/package/resources.html:2 msgid "Someresources" @@ -3013,27 +3015,27 @@ msgstr ",\n Avainsana -" #: ckan/templates/snippets/data-viewer-embed-dialog.html:13 msgid "Embed Data Viewer" -msgstr "" +msgstr "Upota datan näyttäjä" #: ckan/templates/snippets/data-viewer-embed-dialog.html:19 msgid "Embed this view" -msgstr "" +msgstr "Upota tämä näkymä" #: ckan/templates/snippets/data-viewer-embed-dialog.html:19 msgid "by copying this into your webpage:" -msgstr "" +msgstr "kopioimall tämän web-sivullesi:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:21 msgid "Choose width and height in pixels:" -msgstr "" +msgstr "Valitse leveys ja korkeus pikseleinä:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:22 msgid "Width:" -msgstr "" +msgstr "Leveys:" #: ckan/templates/snippets/data-viewer-embed-dialog.html:24 msgid "Height:" -msgstr "" +msgstr "Korkeus:" #: ckan/templates/snippets/package_list.html:39 msgid "Not Openly Licensed" @@ -3108,15 +3110,15 @@ msgstr "Muokkaa käyttäjää:" #: ckan/templates/user/edit_user_form.html:21 msgid "Full name" -msgstr "" +msgstr "Koko nimi" #: ckan/templates/user/edit_user_form.html:27 msgid "E-mail" -msgstr "" +msgstr "Sähköposti" #: ckan/templates/user/edit_user_form.html:33 msgid "OpenId" -msgstr "" +msgstr "OpenId" #: ckan/templates/user/edit_user_form.html:41 msgid "A little about you..." @@ -3129,12 +3131,12 @@ msgstr "Vaihda salasana" #: ckan/templates/user/edit_user_form.html:48 #: ckan/templates/user/new_user_form.html:40 msgid "Password" -msgstr "" +msgstr "Salasana" #: ckan/templates/user/edit_user_form.html:54 #: ckan/templates/user/new_user_form.html:47 msgid "Password (repeat)" -msgstr "" +msgstr "Salasana (toista)" #: ckan/templates/user/edit_user_form.html:61 msgid "Change your username" @@ -3142,7 +3144,7 @@ msgstr "Muuta käyttäjätunnustasi" #: ckan/templates/user/edit_user_form.html:63 msgid "Username" -msgstr "" +msgstr "Käyttäjätunnus" #: ckan/templates/user/layout.html:11 msgid "My Profile" @@ -3199,7 +3201,7 @@ msgstr "Salasana:" #: ckan/templates/user/login.html:37 msgid "Sign In" -msgstr "" +msgstr "Kirjaudu" #: ckan/templates/user/login.html:39 msgid "Forgot your password?" @@ -3238,7 +3240,7 @@ msgstr "OpenID palvelu mahdollistaa kirjautumaan moneen web-sivustoon\nyhdellä #: ckan/templates/user/login.html:69 msgid "Sign in with OpenID" -msgstr "" +msgstr "Kirjaudu käyttäen OpenID:tä" #: ckan/templates/user/logout.html:5 msgid "Logout - User" @@ -3254,11 +3256,11 @@ msgstr "Kirjauduit ulos onnistuneesti." #: ckan/templates/user/logout_first.html:6 msgid "Logged in - User" -msgstr "" +msgstr "Kirjautunut - Käyttäjä" #: ckan/templates/user/logout_first.html:7 msgid "Logged into" -msgstr "" +msgstr "Kirjautunut" #: ckan/templates/user/logout_first.html:12 msgid "is currently logged in" @@ -3290,7 +3292,7 @@ msgstr "3+ merkkiä, käyttäen 'a-z0-9' ja '-_'" #: ckan/templates/user/new_user_form.html:27 msgid "Full name (optional)" -msgstr "" +msgstr "Koko nimi (ei pakollinen)" #: ckan/templates/user/new_user_form.html:34 msgid "E-Mail" @@ -3298,7 +3300,7 @@ msgstr "Sähköposti" #: ckan/templates/user/new_user_form.html:65 msgid "Register now" -msgstr "" +msgstr "Rekisteröidy nyt" #: ckan/templates/user/perform_reset.html:18 msgid "Password (repeat):" From e0cb4c72239622fecf35967cff939d6d5b558f37 Mon Sep 17 00:00:00 2001 From: amercader Date: Fri, 4 May 2012 12:59:16 +0100 Subject: [PATCH 089/109] [release]: Version number updated for release --- ckan/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan/__init__.py b/ckan/__init__.py index 36c8f372104..0b3e724fac2 100644 --- a/ckan/__init__.py +++ b/ckan/__init__.py @@ -1,4 +1,4 @@ -__version__ = '1.7b' +__version__ = '1.7' __description__ = 'Comprehensive Knowledge Archive Network (CKAN) Software' __long_description__ = \ '''CKAN software provides a hub for datasets. The flagship site running CKAN From 006c7dce7ae3be78378691208d7ef77b9adbf906 Mon Sep 17 00:00:00 2001 From: amercader Date: Fri, 4 May 2012 15:34:57 +0100 Subject: [PATCH 090/109] [deb] Update schema version on SOLR setup script --- ckan_deb/usr/bin/ckan-setup-solr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ckan_deb/usr/bin/ckan-setup-solr b/ckan_deb/usr/bin/ckan-setup-solr index 3b191c04655..0642a4c16d9 100755 --- a/ckan_deb/usr/bin/ckan-setup-solr +++ b/ckan_deb/usr/bin/ckan-setup-solr @@ -22,7 +22,7 @@ sed \ -e "s,#JETTY_PORT=8080,JETTY_PORT=8983," \ -i /etc/default/jetty mv /usr/share/solr/conf/schema.xml /usr/share/solr/conf/schema.xml.`date --utc "+%Y-%m-%d_%T"`.bak -ln -s /usr/lib/pymodules/python2.6/ckan/config/solr/schema-1.3.xml /usr/share/solr/conf/schema.xml +ln -s /usr/lib/pymodules/python2.6/ckan/config/solr/schema-1.4.xml /usr/share/solr/conf/schema.xml service jetty stop service jetty start echo "done." From 6c59c033af9620e88ea3dbfe98d8aef6d5231c51 Mon Sep 17 00:00:00 2001 From: Sean Hammond Date: Wed, 9 May 2012 13:35:44 +0200 Subject: [PATCH 091/109] [i18n] Remove no "no-sidebar" translations from all languages Change was made on Transifex and pulled into git --- ckan/i18n/bg/LC_MESSAGES/ckan.mo | Bin 78291 -> 78291 bytes ckan/i18n/bg/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/cs_CZ/LC_MESSAGES/ckan.mo | Bin 63441 -> 63436 bytes ckan/i18n/cs_CZ/LC_MESSAGES/ckan.po | 7 ++++--- ckan/i18n/de/LC_MESSAGES/ckan.mo | Bin 62275 -> 62275 bytes ckan/i18n/de/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/el/LC_MESSAGES/ckan.mo | Bin 64306 -> 64306 bytes ckan/i18n/el/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/es/LC_MESSAGES/ckan.mo | Bin 64606 -> 64610 bytes ckan/i18n/es/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/fi/LC_MESSAGES/ckan.mo | Bin 63175 -> 63175 bytes ckan/i18n/fr/LC_MESSAGES/ckan.mo | Bin 65345 -> 65345 bytes ckan/i18n/fr/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/hu/LC_MESSAGES/ckan.mo | Bin 61047 -> 61047 bytes ckan/i18n/hu/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/it/LC_MESSAGES/ckan.mo | Bin 62238 -> 62238 bytes ckan/i18n/it/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/lv/LC_MESSAGES/ckan.mo | Bin 59820 -> 59820 bytes ckan/i18n/lv/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/nl/LC_MESSAGES/ckan.mo | Bin 61611 -> 61609 bytes ckan/i18n/nl/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/no/LC_MESSAGES/ckan.mo | Bin 60528 -> 60528 bytes ckan/i18n/no/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/pl/LC_MESSAGES/ckan.mo | Bin 63005 -> 63005 bytes ckan/i18n/pl/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/pt_BR/LC_MESSAGES/ckan.mo | Bin 64043 -> 64032 bytes ckan/i18n/pt_BR/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/ro/LC_MESSAGES/ckan.mo | Bin 59205 -> 59205 bytes ckan/i18n/ro/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/ru/LC_MESSAGES/ckan.mo | Bin 73536 -> 73536 bytes ckan/i18n/ru/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/sk/LC_MESSAGES/ckan.mo | Bin 62591 -> 62581 bytes ckan/i18n/sk/LC_MESSAGES/ckan.po | 6 +++--- ckan/i18n/sl/LC_MESSAGES/ckan.mo | Bin 59455 -> 59455 bytes ckan/i18n/sl/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/sq/LC_MESSAGES/ckan.mo | Bin 60425 -> 60425 bytes ckan/i18n/sq/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/sr/LC_MESSAGES/ckan.mo | Bin 75397 -> 75397 bytes ckan/i18n/sr/LC_MESSAGES/ckan.po | 5 +++-- ckan/i18n/sr_Latn/LC_MESSAGES/ckan.mo | Bin 62993 -> 62993 bytes ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po | 5 +++-- 41 files changed, 61 insertions(+), 42 deletions(-) diff --git a/ckan/i18n/bg/LC_MESSAGES/ckan.mo b/ckan/i18n/bg/LC_MESSAGES/ckan.mo index 3c00047f558dbdccba9ac94464b0977c71b3c6b7..f198134750a425049f02f0aa29d546f274b0b081 100644 GIT binary patch delta 25 hcmcconC0?gmJRKlT&B7PmI{W3RtA=vCw4lm004|&3FZI* delta 23 fcmcconC0?gmJRKlljA$tSd6R;O*T*LbXoxbhXe{j diff --git a/ckan/i18n/bg/LC_MESSAGES/ckan.po b/ckan/i18n/bg/LC_MESSAGES/ckan.po index 82ff747a29c..cf9066f83b7 100644 --- a/ckan/i18n/bg/LC_MESSAGES/ckan.po +++ b/ckan/i18n/bg/LC_MESSAGES/ckan.po @@ -7,12 +7,13 @@ # , 2011, 2012. # Martin Minkov , 2011, 2012. # Open Knowledge Foundation , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:09+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Bulgarian \n" "MIME-Version: 1.0\n" @@ -2145,7 +2146,7 @@ msgstr "Актуализиране на съществуващите функц #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/cs_CZ/LC_MESSAGES/ckan.mo b/ckan/i18n/cs_CZ/LC_MESSAGES/ckan.mo index 84c4b284a82224e5068d4435ea60ba9e8560d6e7..de3ddeb58e17e325dba401c72781d7c3cece5c37 100644 GIT binary patch delta 5846 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, 2012. # , 2011. # , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-28 19:42+0000\n" -"Last-Translator: kuceraj \n" +"PO-Revision-Date: 2012-05-09 11:01+0000\n" +"Last-Translator: Sean Hammond \n" "Language-Team: Czech (Czech Republic) (http://www.transifex.net/projects/p/ckan/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -2144,7 +2145,7 @@ msgstr "Aktualizovat stávající role Autorizačních skupin" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "bez postranního panelu" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/de/LC_MESSAGES/ckan.mo b/ckan/i18n/de/LC_MESSAGES/ckan.mo index ab0550f98f248910b4f6db3c42289f70ddf543e0..8dd6ea07e6ff5f0a120bfa37607b8c6de6232115 100644 GIT binary patch delta 25 hcmX^7jQQ|0<_+zgT&B7PmI{W3R)z+fCw6Yi1OSRY3G)B| delta 23 fcmX^7jQQ|0<_+zgljA$tSd6R;O*T*L+>{9bg-Hrm diff --git a/ckan/i18n/de/LC_MESSAGES/ckan.po b/ckan/i18n/de/LC_MESSAGES/ckan.po index 6661c797fdf..85cdc382734 100644 --- a/ckan/i18n/de/LC_MESSAGES/ckan.po +++ b/ckan/i18n/de/LC_MESSAGES/ckan.po @@ -8,12 +8,13 @@ # , 2011. # , 2011. # relet , 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:10+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: German (http://www.transifex.net/projects/p/ckan/language/de/)\n" "MIME-Version: 1.0\n" @@ -2146,7 +2147,7 @@ msgstr "Bestehende Rollen für Autorisierungsgruppen bearbeiten" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/el/LC_MESSAGES/ckan.mo b/ckan/i18n/el/LC_MESSAGES/ckan.mo index 263e27563c1535456cc104fc555f8068046ab81c..142cff98a95960539665354f773a7f4086251612 100644 GIT binary patch delta 25 hcmdn=jd{~I<_+zgT&B7PmI{W3R)z+fCw49@1OSQE3FrU- delta 23 fcmdn=jd{~I<_+zgljA$tSd6R;O*T*LTv!MIgyafL diff --git a/ckan/i18n/el/LC_MESSAGES/ckan.po b/ckan/i18n/el/LC_MESSAGES/ckan.po index 5573b57e5a1..8f4143d2e2a 100644 --- a/ckan/i18n/el/LC_MESSAGES/ckan.po +++ b/ckan/i18n/el/LC_MESSAGES/ckan.po @@ -4,13 +4,14 @@ # # Translators: # , 2012. +# Sean Hammond , 2012. # Spiros Alexiou , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:10+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Greek (http://www.transifex.net/projects/p/ckan/language/el/)\n" "MIME-Version: 1.0\n" @@ -2143,7 +2144,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/es/LC_MESSAGES/ckan.mo b/ckan/i18n/es/LC_MESSAGES/ckan.mo index d0fd00f452ebe7e1b605c112001fe1121e92f4e9..d7c9e7dad5134defcce69e43d49adf30dcfb4200 100644 GIT binary patch delta 5827 zcmXZf2~?L=8prXgD2oUvA|fK2xBiv^2@BEHmf(^WJkh=X0O?zW=*C&%Lj7`lipA5msZU*d!^&zMvikJIsYA7jcfgE*qxn3gykyWv>O!X?-P4`CN< zRACH1Gl{4Sq+lz|LQR~DL70!)`QsRZMVNrkcr@D3s6!slWK+>H9&QPg`sxY+xhh9-!7(LTsPO*{y-;&HBjI?g73 z#`Rytoy4~>9N%4PObi~yNW6k7QS)VX$BEdKINQbjv9+Q8_tVghC!%&T9W~HX7=bG> z3E#%<_!aiTu;s=C;|L7H0!+tQF5ZAT%r(w0T>oun=n9pd`gf+0!;252PU&*gKxhibvHu2J`(TVEPDYh@I7Z`x z*a2s6Apg21OX<)DV;vUY7St(izR@1e_NX`uwUZ&J3>2VtT8uIHEb3ZTVjrw^{movs z3rs|PFaC@w+02(cyOIhzbUog|e5^w)DDf4$@+{N>`eJ(=>70%#(IULN0aQk}IIB_D z@k7*MuEm~s4*O%Yx5?ISEb1B+p)&FhXBle8%h4CNpmx07#UG(&#ph<4SSl~VmAFf zP$is+T0kl0;R~o!{~h|E?`Au0GmO;zkEEf2Gf~%QFlqr0p>{q7({KjrTCPJ4Scf_b zS5TP<;R>lg+}RzQ5Z{klP(CWN1=tKHp)d2BSv0hOCovcoVPjl@^Kdn4f_87(_u?^- zI0Jneagb089k|s#AB}^Er=qUeR=k9D_#Wv zhTv4xj^?5Ud=@p}bEpX`u`TXG4P1{y@e=C&tR1#Q15i62ff{cN>P$>PWn`-79?U^4 zWFD#{&*Ly$>*7loOMDA^ayX)@?Ev{T{NY0XSkxIgi~aDTGwEG>J*Qy`{gpTkKf~VW z_2opw(3p#=T{-2UW_Jd+fquQP(yTb=z_PjjkB~k*)PG)D8-;2Nt7J`7-JZ>_RQ@obx8? zj0EntC5%EX=t0yeFT{A9hRW=7n2wwFlYgb`Bpp$B89QR&0XtASYJpR*6E4AMtidF# zNA0A^LHoQ5`V)^tEpRky{An1A9%^GRp%%RDAo99( zoHtST*yj^FaW~Y&*{A`Bq9%F}^}7PsKN&3ai7|fjl@KrPsB7_jLOI!XDuqjCom3w!erh5h$Hsz^FgRX_!K7L zGEByOsM=q_d5w&@_bBNl-u;<<9)8RYcrRwrKLJy5H7a9=Q41SaXU8o?AL1I!VSe*I z4ZU#3nRwj(ahQ)v-HWK_HKGZ;+VfU4Q=I0AjYu%FO;rbC?#9ngSVX*F@^s4FKtRkVLI{OP&=qXW#$wrGk&M- z`JLZk3?l~2R?wiFb!LJ|Few&*pH6csG3#bVEhG#V9wXJe<5}!K7yIp zY2>RnR)bHk?7O)((z+oQj%&n5Fu|kI@3Q^m zj&HCNdZ-%z3w?1X>K5!pE#xW&V#1I1ADJ}N^U>H2ORy9xaVDl;vG=|b^N7!(u3xXK z}=? zqHbF^)O@)&$iF6dk`ASMJ!+uWF%)-VEBq7#@EZ)mA5ba1<@)`9vhRmtH2ob>hi@RN zL{Fo}uf%YC!^L}lqW(%*Egd=o7qAUpMosMdv)xf7>b*GB0{UPW=3+2DhT3T{w#0>~ z60LI2H=)i#wR^tD#dRJHrREHV;MW+1S5XTJxoP9psDZm-R~(2Pun4t~CCE`SuV80< z6_v50uKx?{Py8hg!02DBULg&AAU0qUp2Zk!@vA)xX_!Mi7UOZ9i}#^Ux$iBP2}~n? z3_Idt9E{bd4c$SNH0n3|f6=LEV!Kp*ko?IQzh1HF>Dg%+<%<`z>5w;}uqbv&;q>Xn eMdM@dnN5^3*+%_~r%fzMDV{Z{>cE1fv;Gf1e-vZ@ delta 5823 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 Y|Kj)#BgPIIIVOF`_^~Ai3KvfNAINYE7ytkO diff --git a/ckan/i18n/es/LC_MESSAGES/ckan.po b/ckan/i18n/es/LC_MESSAGES/ckan.po index be5243755d9..b10cb27c0ee 100644 --- a/ckan/i18n/es/LC_MESSAGES/ckan.po +++ b/ckan/i18n/es/LC_MESSAGES/ckan.po @@ -10,13 +10,14 @@ # , 2012. # Jesús García <>, 2012. # okfn , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-05-01 21:40+0000\n" -"Last-Translator: amercader \n" +"PO-Revision-Date: 2012-05-09 11:04+0000\n" +"Last-Translator: Sean Hammond \n" "Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/ckan/language/es/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" diff --git a/ckan/i18n/fi/LC_MESSAGES/ckan.mo b/ckan/i18n/fi/LC_MESSAGES/ckan.mo index 55173bdf657d06d640d4f950ff3c9b3f8adb0a0e..d32d63e4848b413085a886b5d0262a1a3a634979 100644 GIT binary patch delta 29 lcmX^9mihQw<_*1_?1omR#@Yr3o2PUtFfy8L-r6OU0|2>B3o-xz delta 29 lcmX^9mihQw<_*1_>_%3mCfWvuo2PUtFfy8K-r6OU0|2>l3o`%! diff --git a/ckan/i18n/fr/LC_MESSAGES/ckan.mo b/ckan/i18n/fr/LC_MESSAGES/ckan.mo index 2e99b040622870eec7b40f39a3322759e8dbb816..3357f38d7b53300529ece82abe9fd512f4fca407 100644 GIT binary patch delta 25 hcmX^3kNMy~<_+zgT&B7PmI{W3RtA=vCw6Wq1ptmu3NZix delta 23 fcmX^3kNMy~<_+zgljA$tSd6R;O*T*L+)xSth|>y< diff --git a/ckan/i18n/fr/LC_MESSAGES/ckan.po b/ckan/i18n/fr/LC_MESSAGES/ckan.po index d0eb7e9cabf..810d98403ca 100644 --- a/ckan/i18n/fr/LC_MESSAGES/ckan.po +++ b/ckan/i18n/fr/LC_MESSAGES/ckan.po @@ -6,12 +6,13 @@ # , 2011, 2012. # , 2011. # okfn , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:09+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: French (http://www.transifex.net/projects/p/ckan/language/fr/)\n" "MIME-Version: 1.0\n" @@ -2144,7 +2145,7 @@ msgstr "Modifier Les rôles existants pour ces groupes d'autorisation" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/hu/LC_MESSAGES/ckan.mo b/ckan/i18n/hu/LC_MESSAGES/ckan.mo index 4d00c09178f1bf49154c44f5afa7b5465a29c4cf..29c7bbeffaeed589e56791c891dc3e7a0cfa222b 100644 GIT binary patch delta 25 hcmexMe3k+LjMNI- diff --git a/ckan/i18n/hu/LC_MESSAGES/ckan.po b/ckan/i18n/hu/LC_MESSAGES/ckan.po index 4899cbd0cc2..67d73ab3387 100644 --- a/ckan/i18n/hu/LC_MESSAGES/ckan.po +++ b/ckan/i18n/hu/LC_MESSAGES/ckan.po @@ -7,6 +7,7 @@ # Kalman Kemenczy , 2011. # , 2012. # okfn , 2011. +# Sean Hammond , 2012. # , 2011. # stf , 2011. msgid "" @@ -14,7 +15,7 @@ msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:10+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Hungarian (http://www.transifex.net/projects/p/ckan/language/hu/)\n" "MIME-Version: 1.0\n" @@ -2147,7 +2148,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/it/LC_MESSAGES/ckan.mo b/ckan/i18n/it/LC_MESSAGES/ckan.mo index 8767959930f3a736d89f00f1d3e3670ba0d4c17d..fbe17a3ba854fb32ef0004095858fc35220398ab 100644 GIT binary patch delta 25 hcmbRDjCtNO<_+zgT&B7PmI{W3Rt6TECwBH`0sw, 2011. # , 2012. # Maurizio Napolitano , 2011, 2012. +# Sean Hammond , 2012. # Stefano Costa , 2011, 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:08+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Italian (http://www.transifex.net/projects/p/ckan/language/it/)\n" "MIME-Version: 1.0\n" @@ -2145,7 +2146,7 @@ msgstr "Aggiorna i ruoli disponibili per i gruppi di utenti" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/lv/LC_MESSAGES/ckan.mo b/ckan/i18n/lv/LC_MESSAGES/ckan.mo index d02acaf8df78b82c6f225ef71ac44965f0fcce4f..e3cca22a2147cd3b833c72a937648683c79034f3 100644 GIT binary patch delta 25 hcmZ2;nR(4+<_+zgT&B7PmI{W3Rt6TECw59F004oY2?hWF delta 23 fcmZ2;nR(4+<_+zgljA$tSd6R;O*c>MluiHueJ}}R diff --git a/ckan/i18n/lv/LC_MESSAGES/ckan.po b/ckan/i18n/lv/LC_MESSAGES/ckan.po index 8af137a3288..c2f57bbd5c0 100644 --- a/ckan/i18n/lv/LC_MESSAGES/ckan.po +++ b/ckan/i18n/lv/LC_MESSAGES/ckan.po @@ -4,12 +4,13 @@ # # Translators: # Karlis , 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:08+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Latvian (http://www.transifex.net/projects/p/ckan/language/lv/)\n" "MIME-Version: 1.0\n" @@ -2142,7 +2143,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/nl/LC_MESSAGES/ckan.mo b/ckan/i18n/nl/LC_MESSAGES/ckan.mo index aa1768900897541eb013630e247ef99e50c29701..4cd51c4f2d52398cb91ea1393fe965e7075ac1dd 100644 GIT binary patch delta 293 zcmXZUF>Atb5XRxNDM(#JQ5UI*bP!Z%gcO@9u5RM)yi}{5$i0X;T+?*#0>sm6#p=VoACaRALJuu zG3VXyCPv6@EMN!K|53QNutuJu>bss;^2TswVPfSX@`8O-4;Epzu};t=i=iH^x8tE delta 293 zcmXZUJqtl$7{>8i=R`?KVUdyyiV_3zlHDe&Qc7envN_456y*z8Wsx%|DT~#n%*vv? zjYj_`XZk(Yb$30>tG2po>wU~{iHPwK(QtxpoS`2V=)f&{@nGH0m?z&bfT8FAUO*eU zf?=$p6MI%a#4LG)YQKMqA!#08iX0|hA`$GM`e1714Hn23tM|S|O5_ZxT^~KTLA5`k r+TXE=u8&9%%jm;4#&Pg5ckxqgULV`FR4!@G#_xvSYBsy(@DbI2G*(0h diff --git a/ckan/i18n/nl/LC_MESSAGES/ckan.po b/ckan/i18n/nl/LC_MESSAGES/ckan.po index c360fef1c9d..b6b43030387 100644 --- a/ckan/i18n/nl/LC_MESSAGES/ckan.po +++ b/ckan/i18n/nl/LC_MESSAGES/ckan.po @@ -7,13 +7,14 @@ # , 2012. # , 2011. # OpenDataBaas , 2011. +# Sean Hammond , 2012. # TonZijlstra , 2011. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:25+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Dutch (http://www.transifex.net/projects/p/ckan/language/nl/)\n" "MIME-Version: 1.0\n" @@ -2146,7 +2147,7 @@ msgstr "Wijzig bestaande rollen voor autorisatiegroepen" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "geen-sidebar" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/no/LC_MESSAGES/ckan.mo b/ckan/i18n/no/LC_MESSAGES/ckan.mo index 01e1857580770f280f84047191228a553cc8aca1..5134ff32496c028f1a8a524644528b19058963b4 100644 GIT binary patch delta 25 hcmexxgZaY^<_+zgT&B7PmI{W3R)$8KCwAUX0sxR|3RwUE delta 23 fcmexxgZaY^<_+zgljA$tSd6R;O*c>Myq^RBit`G* diff --git a/ckan/i18n/no/LC_MESSAGES/ckan.po b/ckan/i18n/no/LC_MESSAGES/ckan.po index 5f235776173..80daf651410 100644 --- a/ckan/i18n/no/LC_MESSAGES/ckan.po +++ b/ckan/i18n/no/LC_MESSAGES/ckan.po @@ -8,12 +8,13 @@ # , 2011. # oovrebo , 2011. # relet , 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:12+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Norwegian (http://www.transifex.net/projects/p/ckan/language/no/)\n" "MIME-Version: 1.0\n" @@ -2146,7 +2147,7 @@ msgstr "Oppdater eksisterende roller for autoriseringsgrupper" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/pl/LC_MESSAGES/ckan.mo b/ckan/i18n/pl/LC_MESSAGES/ckan.mo index 98838e7869be78fd3ae62974cf27f9692dbfbcd4..ee60fc9e5f9fcbeb461f8a07e8a40eb7ac038e77 100644 GIT binary patch delta 25 hcmbRHhI#HA<_+zgT&B7PmI{W3R)$8KCwBJa004v)36cN+ delta 23 fcmbRHhI#HA<_+zgljA$tSd6TU4L48h?8yNDe~=0D diff --git a/ckan/i18n/pl/LC_MESSAGES/ckan.po b/ckan/i18n/pl/LC_MESSAGES/ckan.po index 25ae53bfecd..440384ddc8b 100644 --- a/ckan/i18n/pl/LC_MESSAGES/ckan.po +++ b/ckan/i18n/pl/LC_MESSAGES/ckan.po @@ -5,12 +5,13 @@ # Translators: # , 2011, 2012. # okfn , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:31+0000\n" +"PO-Revision-Date: 2012-05-09 11:12+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Polish (http://www.transifex.net/projects/p/ckan/language/pl/)\n" "MIME-Version: 1.0\n" @@ -2143,7 +2144,7 @@ msgstr "Zaktualizuj istniejące role dla grup autoryzacyjnych" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/pt_BR/LC_MESSAGES/ckan.mo b/ckan/i18n/pt_BR/LC_MESSAGES/ckan.mo index 4344adf516be720fddeff1f7a263adcebb215cb7..4f7717591c36940fc7487f1cddeb28e5c8dfd625 100644 GIT binary patch delta 301 zcmXZXu}cDR7{>8eP7qHQDH;xf5I0XqL9@#^x90W+6CH#=P{)It8=D-f*(JP1q<!gvL{7yu22DQ$!X!5d&A4#ZNrOEv7L2BVu6=575R7 zY+?aDJi=#8;0*IP#|(b#=igW-Z&CY&NPMaBXhk9pj!_rBqb`W{+4>b}kX_Wdhb}&% z_STp~EB^1>sQ<3<5=W>9P4N(ysJ*W^nA>kRX0>#Beo`(wm9yaC-n~orOT%8L+rAwH Io849N53%S-O8@`> delta 310 zcmXZXze@sf7{~FaPI9nCIvqq8(Mcr|(eMY3g8mB!@f8HYtKq2mMsbw>0clK!;I^z`Vq592TuQvIg5328})pM zO?*b(`@tw?_s9JT>OBh^=%W768=AOA-TU2pula@bcr!W+6{}YzZ#-(+X78^5aH|Sk R, 2011, 2012. # , 2011, 2012. # Pablo Mendes <>, 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:27+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.net/projects/p/ckan/language/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -2144,7 +2145,7 @@ msgstr "Atualiza Papéis Existentes para Grupos de Autorização" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "nenhuma-barra-lateral" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/ro/LC_MESSAGES/ckan.mo b/ckan/i18n/ro/LC_MESSAGES/ckan.mo index f0f8e202831224154ce2a447068844fabfca4c3b..36e82cded17823f3f66f8508b085ed3377cc494b 100644 GIT binary patch delta 25 hcmX?lj``?0<_+zgT&B7PmI{W3R)$8KCw6X$1ptO<3BLdU delta 23 fcmX?lj``?0<_+zgljA$tSd6TU4L48h+!6}_fx8MI diff --git a/ckan/i18n/ro/LC_MESSAGES/ckan.po b/ckan/i18n/ro/LC_MESSAGES/ckan.po index 52ad422efa0..77773c0a755 100644 --- a/ckan/i18n/ro/LC_MESSAGES/ckan.po +++ b/ckan/i18n/ro/LC_MESSAGES/ckan.po @@ -4,12 +4,13 @@ # # Translators: # Nicolaie Constantinescu , 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:31+0000\n" +"PO-Revision-Date: 2012-05-09 11:12+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Romanian (http://www.transifex.net/projects/p/ckan/language/ro/)\n" "MIME-Version: 1.0\n" @@ -2142,7 +2143,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/ru/LC_MESSAGES/ckan.mo b/ckan/i18n/ru/LC_MESSAGES/ckan.mo index 57997687f66fc733fcca28e70e9d8be8e83fcc60..b3cbc772a6ec2256dd8a6439d6168011e772d409 100644 GIT binary patch delta 25 hcmX@GkLAEVmJRKlT&B7PmI{W3R))r#Cw8u%3IKx)3CjQg delta 23 fcmX@GkLAEVmJRKlljA$tSd6R;O*T*LTt5{6eys{D diff --git a/ckan/i18n/ru/LC_MESSAGES/ckan.po b/ckan/i18n/ru/LC_MESSAGES/ckan.po index 5fa03d9e524..2c7e6f0eb07 100644 --- a/ckan/i18n/ru/LC_MESSAGES/ckan.po +++ b/ckan/i18n/ru/LC_MESSAGES/ckan.po @@ -6,12 +6,13 @@ # alexey medvetsky , 2011, 2012. # Alfred Tessman , 2011, 2012. # , 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:14+0000\n" +"PO-Revision-Date: 2012-05-09 11:13+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Russian (http://www.transifex.net/projects/p/ckan/language/ru/)\n" "MIME-Version: 1.0\n" @@ -2144,7 +2145,7 @@ msgstr "Обновить существующие роли для групп а #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/sk/LC_MESSAGES/ckan.mo b/ckan/i18n/sk/LC_MESSAGES/ckan.mo index 2d2ce32c355e6d639b638ae02ef922fd33f85037..08d9b32bfbed57d81815e95e62138adef6b013c0 100644 GIT binary patch delta 5846 zcmXxn3w+P@9>?*o-8XFJvWsQLF6J^e+ZfRi3lUOLgjnuo#5v`Wb$%2nOeJ*aFxQSy ztc7xEG3HL4tYzrpGD8YUs?+Jb-oD@Scz8UX-_Q5=`+YB;@8v&#R{Q>3?Ykv6!aG^R z81t$zJ)wNAG0ib{o-yxI-xC9gZ_YO+27ki=7*SwMHs)e57GVhP#0FS~weXC4ei{9V ze{%J|Is+CM@9vBB78sMr3vn2U-7y@8p&Fiy5jY*2;zCqMTd^S?!F#X@YoqUL#spwE zhG7)OVKUal2eAtdc+E4W6@?{Kbn-Q(6f=m;o3_JDY)$wOCg608!<8=HgM4PHP#s^v zI(P@wQSc(0!3L;_G{PuM##p@Hqo5fNN2P2UD&@1WE*4-kuEa3h;XI6uh$~%u2SbU2 z7Tb0rQ3FrFmiQ>@d(ZjW|Kmbe*o z6x-oBtcTG{?VdetVX?e10Tll<#r%Bs3lm6_u)ZI!N3(PH)dih`Zr4`G{jPDhF@bE1{B)Ol!f;Y zKZr` z_!g?;YE)+KppI3&wRUY2P^Tmdb*#FePD^i8$HPz^OhwIjDK^FJs3ogJwR?W8XLtR7 zsZfe)uVbTNA}TYJQ5|`x^F0Uk-eT0Idk=L{m7+hEqcU(BwVBVMzW)KWDQ{ychP-2s z<-HySH9Q72Cv%$`^K57q4L=9{P_QzLH zOIeA&co{?R8b;~--=UyQ6TZ>Dn1pH|6P2pYs1)`?W#T2&KnhVyQ;d55DC+%_s3oaF zP2@HP;qMrXew*w7LeZc8O*93KyfJE|ZP5qs$Dx>wYG5^L<{PmVevCf+OqZcLKJ=dT zG^P+=LoH#<`=lE?BL9rfW@83p5#BxjwYJz9#GsB@JSrm@sMJ5`;)hWK9p#*c%D_C- z0M|O-bM@O$13Q75`FE&2a21uI8b#z^GYK!U9mS$Dkche{GEmR^Vr_iVJs;=dX{ej= zWz>6X-19A{36$Xdc+%BJe87e!PDEX3Jw71+`fv;t>fo=aHGa{>D^N4rgc{gZ)bZNq zJcHWhx3C%3EVgT#jx~wzLw(;1m4Qc5dt#`Ib36)4MJ}r0e5{9yurIE6@h_;E*8I?z zQ>=M1sso>G{D5I7YN&%_dFlX}js2~<>|M*1IA zL$N#T=IV}GtEVs(J=Dy%pi;UE>tGpbz!j(gU&L^{g*`A}ryWRNR6Fx9Q|Esdg(xa+ z;@uSQvYRg%TTTsAD$-m7(bvgG*5Z+=}|X z6kF22IZUA;-o{7_FR?E+N7c7S&Eyf(6+O~DACH>pG*p9ga4ass0r(5{!#>-5Wif6H!aG5Myy8>bt|J?=GPR8obZl ze5iqTL=B)fM&LNqL}%>t>_}gyg57A|c5cQv;!;!x7qA=F*l#!A1E|#ZM=i;4)Qm@? z2Jj4OfG?qzbTw*;cA(zdgUawxkAg;0j!NZ4)Ijc_KCD${UrcbOpc-!H;sL0E40G{B zR0q#uO`M4VSb#~m2=#m?s$Z{+LLUlWq8ds#U|&o}&15iY^W!5x9Fe=44 zsMJnHE$LkJ$3l$8b?ApB&V9%LJ#&ac01wJB1J9t&XZRsw9>=cO3YTFr9zd=2b!?1v z58I5jb#_P94@PzPywgJ+!&#`kuoB~S{y(9RLd7{uz&b~41~O3t8G`9pfYWQRc9=!n z`Iz19&!XO2fqL%*>b~$jZvU`}M(v^bsDZzW%FGe$NdM+@3SF?)3EMy)%p{(Pn)!Bo z05719Pm9lNLl2-j9D|zK+gJy;V>3L6&G9;F$r^rc+iQz@{uFv$Da@hJ*oR|;i-@m$ zVfTV}(r%Ik7)bpJ)LwW8`{D)k#q@H!DcfT`;(@3&ACHgVEYyrEus)teZQ`5dwM z{-tfG4Jx(i&Rk3*UWYBQ0u#}o-`7-!$vp`<8Tf};Cj^3 zlwfN-?)(EapjH=bdr#lh<5!4+cJ~ns#xGE7a~5?m1zofkPZ)*}XQ9@-8%E<}7>{|V zHC~9y#7b1V-=e;&Mt%1aK3#*$sfvy7Q5bv4K6t*`?#_9r1{a|peuOEw+tpviaN@Ab zcK0_yt!ZCuj2^DVLL7qGSL|QGt5AF3JZi7RUgg~w3Xf4}f|D^B7dm&Mj@1Rs#`@oL zso)^&flaU3B^!?#&{hn>16T_`LuKeJ`rt39^Zy&Rz_1@!|7H|A{$M}MK{Yf1gYgAd zKganxDuqi?zm^+NOSIe7@55N)a#Ticq1sRU(H`GEsLT#RefPqTtbYRvv#9XJWmp?m zpgP#(>Pt{JTPcQO1!|yGsQ2%nG8u5)e%BQBUM6ZH*)Hzu9Eu^-=Xw;>z;hUevr!k! zV)w%PsE$8Ib$AT5i@(7*jJRP>Nqb}~nSQA6`=h=a@9O`KU5RI48kS-k^nRwGR z?twwh>8Q=L9QAy+i*KMB2>;2}cSB|HIZVU?XEEyHI)!lzJDU<{Pg@#y>i0L|$Ca5fdj)${QKiX)00cu{P>5X~O8d){~};DL(e< Ys?i~NlTxOR8#yXx#FXM0*Z=hWA5`HE3;+NC delta 5856 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 mlV7>Nq~g(*d5=u@\n" +"PO-Revision-Date: 2012-05-09 11:03+0000\n" +"Last-Translator: Sean Hammond \n" "Language-Team: Slovak (http://www.transifex.net/projects/p/ckan/language/sk/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -2147,7 +2147,7 @@ msgstr "Aktualizovať existujúce role pre autorizačné skupiny" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "bez bočnej lišty" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/sl/LC_MESSAGES/ckan.mo b/ckan/i18n/sl/LC_MESSAGES/ckan.mo index 04ebcc047da5ddf2934d089aa89a12b8e530ebb1..f15c38d250a829d73e8ba9991eefb73e7c23a2a0 100644 GIT binary patch delta 24 gcmdmgfqDN0<_+zgoTj=4mI{W3R)(7=bgqvB0DZX$e*gdg delta 22 ecmdmgfqDN0<_+zgljA$tn2oHAHc#kW9|r(, 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:23+0000\n" +"PO-Revision-Date: 2012-05-09 11:13+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Slovenian (http://www.transifex.net/projects/p/ckan/language/sl/)\n" "MIME-Version: 1.0\n" @@ -2142,7 +2143,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/sq/LC_MESSAGES/ckan.mo b/ckan/i18n/sq/LC_MESSAGES/ckan.mo index e5f17fbe3e5811e8fe18ad434072bf7996f13601..4dc4304b85c75edf469789ecc92c6bca344e734e 100644 GIT binary patch delta 24 fcmeCY!Q6R+c|&_Ar>U-irGlZMmBHo-os~%dbtMS! delta 22 dcmeCY!Q6R+c|&{W, 2011. # , 2011, 2012. # , 2011. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:05+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Albanian (http://www.transifex.net/projects/p/ckan/language/sq/)\n" "MIME-Version: 1.0\n" @@ -2144,7 +2145,7 @@ msgstr "" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/sr/LC_MESSAGES/ckan.mo b/ckan/i18n/sr/LC_MESSAGES/ckan.mo index 0481b5d7f28561dbbbeed2d2cadfdaca1839c903..50cc7865f4b182a8bb3c163a052645b1c0035815 100644 GIT binary patch delta 25 hcmZoY%hGz5WkY)>m#MCSrGlZMm7($GiJf2O004Vy3BLdU delta 23 fcmZoY%hGz5WkY-C, 2011, 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:13+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Serbian (http://www.transifex.net/projects/p/ckan/language/sr/)\n" "MIME-Version: 1.0\n" @@ -2142,7 +2143,7 @@ msgstr "Ажурирај постојеће улоге за групу ауто #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 diff --git a/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.mo b/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.mo index 7256b2737de6a55259391ea2dcdbbda09fc7cf32..90574103de48d60eb5581eafc4f1b7be34a96132 100644 GIT binary patch delta 25 hcmbREhI!%}<_+zgT&B7PmI{W3R))r#Cw4aE004o{32y)Z delta 23 fcmbREhI!%}<_+zgljA$tSd6R;O*c>MY{&rseSQhi diff --git a/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po b/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po index 6fc34e8adfe..ac6c86ce2a1 100644 --- a/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po +++ b/ckan/i18n/sr_Latn/LC_MESSAGES/ckan.po @@ -4,12 +4,13 @@ # # Translators: # , 2011, 2012. +# Sean Hammond , 2012. msgid "" msgstr "" "Project-Id-Version: CKAN\n" "Report-Msgid-Bugs-To: http://trac.ckan.org/\n" "POT-Creation-Date: 2012-04-26 14:49+0200\n" -"PO-Revision-Date: 2012-04-26 12:15+0000\n" +"PO-Revision-Date: 2012-05-09 11:13+0000\n" "Last-Translator: Sean Hammond \n" "Language-Team: Serbian (Latin) (http://www.transifex.net/projects/p/ckan/language/sr@latin/)\n" "MIME-Version: 1.0\n" @@ -2142,7 +2143,7 @@ msgstr "Ažurirаj postojeće uloge zа grupu аutorizаcijа" #: ckan/templates/package/related_list.html:14 #: ckan/templates/revision/diff.html:6 ckan/templates/revision/list.html:7 msgid "no-sidebar" -msgstr "" +msgstr "no-sidebar" #: ckan/templates/group/edit_form.html:10 #: ckan/templates/group/new_group_form.html:101 From c33113beb98481ba74be49fecd3ea5b10168c16f Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 9 May 2012 12:38:14 +0100 Subject: [PATCH 092/109] fix no-sidebar class being localised --- ckan/templates/group/edit.html | 2 +- ckan/templates/home/index.html | 2 +- ckan/templates/package/edit.html | 2 +- ckan/templates/package/editresources.html | 2 +- ckan/templates/package/history.html | 2 +- ckan/templates/package/new.html | 2 +- ckan/templates/revision/diff.html | 2 +- ckan/templates/revision/list.html | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ckan/templates/group/edit.html b/ckan/templates/group/edit.html index 7d31c866d3c..5456ce00356 100644 --- a/ckan/templates/group/edit.html +++ b/ckan/templates/group/edit.html @@ -4,7 +4,7 @@ Edit: ${c.group.display_name} Edit: ${c.group.display_name} - no-sidebar + ${h.literal('no-sidebar')}
    diff --git a/ckan/templates/home/index.html b/ckan/templates/home/index.html index 84a647c88e9..540deecf38a 100644 --- a/ckan/templates/home/index.html +++ b/ckan/templates/home/index.html @@ -4,7 +4,7 @@ py:strip="" > - no-sidebar + ${h.literal('no-sidebar')} Welcome diff --git a/ckan/templates/package/edit.html b/ckan/templates/package/edit.html index 48d5c9ca47b..5506137aa66 100644 --- a/ckan/templates/package/edit.html +++ b/ckan/templates/package/edit.html @@ -5,7 +5,7 @@ ${c.pkg.title or c.pkg.name} - Edit - Datasets Edit: ${c.pkg.title or c.pkg.name} - no-sidebar + ${h.literal('no-sidebar')}