udata 7.0.7.dev28410__py2.py3-none-any.whl → 7.0.7.dev28435__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of udata might be problematic. Click here for more details.

Files changed (99) hide show
  1. udata/api/oauth2.py +1 -1
  2. udata/app.py +2 -1
  3. udata/commands/db.py +1 -1
  4. udata/core/activity/models.py +1 -1
  5. udata/core/badges/models.py +1 -1
  6. udata/core/badges/tests/test_commands.py +2 -1
  7. udata/core/badges/tests/test_model.py +1 -1
  8. udata/core/contact_point/models.py +1 -1
  9. udata/core/dataset/api.py +3 -2
  10. udata/core/dataset/api_fields.py +2 -5
  11. udata/core/dataset/apiv2.py +2 -3
  12. udata/core/dataset/commands.py +5 -5
  13. udata/core/dataset/constants.py +82 -0
  14. udata/core/dataset/forms.py +2 -0
  15. udata/core/dataset/models.py +2 -87
  16. udata/core/dataset/rdf.py +2 -1
  17. udata/core/dataset/search.py +2 -3
  18. udata/core/dataset/tasks.py +2 -1
  19. udata/core/discussions/constants.py +1 -0
  20. udata/core/discussions/forms.py +2 -1
  21. udata/core/discussions/models.py +1 -5
  22. udata/core/followers/models.py +1 -1
  23. udata/core/jobs/models.py +1 -1
  24. udata/core/metrics/models.py +1 -1
  25. udata/core/organization/api.py +2 -1
  26. udata/core/organization/api_fields.py +1 -4
  27. udata/core/organization/constants.py +29 -0
  28. udata/core/organization/forms.py +2 -4
  29. udata/core/organization/models.py +2 -34
  30. udata/core/organization/tasks.py +2 -1
  31. udata/core/post/constants.py +9 -0
  32. udata/core/post/forms.py +2 -1
  33. udata/core/post/models.py +2 -12
  34. udata/core/reuse/api.py +2 -1
  35. udata/core/reuse/api_fields.py +1 -1
  36. udata/core/reuse/constants.py +37 -0
  37. udata/core/reuse/factories.py +2 -1
  38. udata/core/reuse/forms.py +3 -2
  39. udata/core/reuse/models.py +2 -38
  40. udata/core/spam/api.py +1 -1
  41. udata/core/spam/constants.py +5 -0
  42. udata/core/spam/fields.py +1 -1
  43. udata/core/spam/models.py +2 -6
  44. udata/core/spam/tests/test_spam.py +3 -3
  45. udata/core/spatial/constants.py +9 -0
  46. udata/core/spatial/models.py +4 -15
  47. udata/core/spatial/tests/test_fields.py +1 -1
  48. udata/core/tags/models.py +1 -1
  49. udata/core/user/api_fields.py +1 -3
  50. udata/core/user/constants.py +2 -0
  51. udata/core/user/forms.py +1 -1
  52. udata/core/user/models.py +1 -1
  53. udata/factories.py +2 -2
  54. udata/features/transfer/models.py +1 -1
  55. udata/frontend/csv.py +1 -1
  56. udata/linkchecker/models.py +1 -1
  57. udata/models/__init__.py +1 -118
  58. udata/mongo/__init__.py +42 -0
  59. udata/mongo/engine.py +73 -0
  60. udata/routing.py +1 -1
  61. udata/search/__init__.py +1 -1
  62. udata/tests/api/test_datasets_api.py +2 -3
  63. udata/tests/api/test_reuses_api.py +2 -1
  64. udata/tests/dataset/test_dataset_model.py +3 -4
  65. udata/tests/dataset/test_dataset_rdf.py +1 -1
  66. udata/tests/forms/test_basic_fields.py +1 -1
  67. udata/tests/forms/test_daterange_field.py +1 -1
  68. udata/tests/forms/test_dict_field.py +1 -1
  69. udata/tests/forms/test_extras_fields.py +1 -1
  70. udata/tests/forms/test_form_field.py +1 -1
  71. udata/tests/forms/test_image_field.py +1 -1
  72. udata/tests/forms/test_model_field.py +1 -1
  73. udata/tests/forms/test_model_list_field.py +1 -1
  74. udata/tests/forms/test_nested_model_list_field.py +1 -1
  75. udata/tests/forms/test_reference_field.py +1 -1
  76. udata/tests/forms/test_uuid_field.py +1 -1
  77. udata/tests/frontend/test_csv.py +1 -1
  78. udata/tests/plugin.py +1 -1
  79. udata/tests/search/__init__.py +1 -1
  80. udata/tests/site/test_site_metrics.py +2 -1
  81. udata/tests/test_model.py +2 -1
  82. udata/tests/test_owned.py +1 -1
  83. udata/tests/test_routing.py +2 -2
  84. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/METADATA +3 -1
  85. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/RECORD +99 -89
  86. /udata/{models → mongo}/badges_field.py +0 -0
  87. /udata/{models → mongo}/datetime_fields.py +0 -0
  88. /udata/{models → mongo}/document.py +0 -0
  89. /udata/{models → mongo}/extras_fields.py +0 -0
  90. /udata/{models → mongo}/owned.py +0 -0
  91. /udata/{models → mongo}/queryset.py +0 -0
  92. /udata/{models → mongo}/slug_fields.py +0 -0
  93. /udata/{models → mongo}/taglist_field.py +0 -0
  94. /udata/{models → mongo}/url_field.py +0 -0
  95. /udata/{models → mongo}/uuid_fields.py +0 -0
  96. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/LICENSE +0 -0
  97. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/WHEEL +0 -0
  98. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/entry_points.txt +0 -0
  99. {udata-7.0.7.dev28410.dist-info → udata-7.0.7.dev28435.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,37 @@
1
+ from udata.i18n import lazy_gettext as _
2
+
3
+ REUSE_TYPES = {
4
+ 'api': _('API'),
5
+ 'application': _('Application'),
6
+ 'idea': _('Idea'),
7
+ 'news_article': _('News Article'),
8
+ 'paper': _('Paper'),
9
+ 'post': _('Post'),
10
+ 'visualization': _('Visualization'),
11
+ 'hardware': _('Connected device'),
12
+ }
13
+
14
+ REUSE_TOPICS = {
15
+ 'health': _('Health'),
16
+ 'transport_and_mobility': _('Transport and mobility'),
17
+ 'housing_and_development': _('Housing and development'),
18
+ 'food_and_agriculture': _('Food and agriculture'),
19
+ 'culture_and_recreation': _('Culture and recreation'),
20
+ 'economy_and_business': _('Economy and business'),
21
+ 'environment_and_energy': _('Environment and energy'),
22
+ 'work_and_training': _('Work and training'),
23
+ 'politics_and_public_life': _('Politics and public life'),
24
+ 'safety_and_security': _('Safety and security'),
25
+ 'education_and_research': _('Education and research'),
26
+ 'society_and_demography': _('Society and demography'),
27
+ 'law_and_justice': _('Law and justice'),
28
+ 'open_data_tools': _('Open data tools'),
29
+ 'others': _('Others'),
30
+ }
31
+
32
+
33
+ IMAGE_SIZES = [500, 100, 50, 25]
34
+ IMAGE_MAX_SIZE = 800
35
+
36
+ TITLE_SIZE_LIMIT = 350
37
+ DESCRIPTION_SIZE_LIMIT = 100000
@@ -6,7 +6,8 @@ from udata.core.dataset.factories import DatasetFactory
6
6
  from udata.factories import ModelFactory
7
7
  from udata.utils import faker
8
8
 
9
- from .models import Reuse, REUSE_TYPES, REUSE_TOPICS
9
+ from .models import Reuse
10
+ from .constants import REUSE_TYPES, REUSE_TOPICS
10
11
 
11
12
 
12
13
  class ReuseFactory(ModelFactory):
udata/core/reuse/forms.py CHANGED
@@ -1,8 +1,9 @@
1
1
  from udata.forms import ModelForm, fields, validators
2
2
  from udata.i18n import lazy_gettext as _
3
- from udata.models import Reuse, REUSE_TYPES, REUSE_TOPICS
3
+ from udata.models import Reuse
4
+ from udata.core.reuse.constants import REUSE_TYPES, REUSE_TOPICS
4
5
 
5
- from .models import IMAGE_SIZES, TITLE_SIZE_LIMIT, DESCRIPTION_SIZE_LIMIT
6
+ from .constants import IMAGE_SIZES, TITLE_SIZE_LIMIT, DESCRIPTION_SIZE_LIMIT
6
7
 
7
8
  __all__ = ('ReuseForm', )
8
9
 
@@ -8,45 +8,9 @@ from udata.i18n import lazy_gettext as _
8
8
  from udata.models import db, BadgeMixin, WithMetrics
9
9
  from udata.utils import hash_url
10
10
  from udata.uris import endpoint_for
11
+ from .constants import IMAGE_MAX_SIZE, IMAGE_SIZES, REUSE_TOPICS, REUSE_TYPES
11
12
 
12
- __all__ = ('Reuse', 'REUSE_TYPES', 'REUSE_TOPICS')
13
-
14
-
15
- REUSE_TYPES = {
16
- 'api': _('API'),
17
- 'application': _('Application'),
18
- 'idea': _('Idea'),
19
- 'news_article': _('News Article'),
20
- 'paper': _('Paper'),
21
- 'post': _('Post'),
22
- 'visualization': _('Visualization'),
23
- 'hardware': _('Connected device'),
24
- }
25
-
26
- REUSE_TOPICS = {
27
- 'health': _('Health'),
28
- 'transport_and_mobility': _('Transport and mobility'),
29
- 'housing_and_development': _('Housing and development'),
30
- 'food_and_agriculture': _('Food and agriculture'),
31
- 'culture_and_recreation': _('Culture and recreation'),
32
- 'economy_and_business': _('Economy and business'),
33
- 'environment_and_energy': _('Environment and energy'),
34
- 'work_and_training': _('Work and training'),
35
- 'politics_and_public_life': _('Politics and public life'),
36
- 'safety_and_security': _('Safety and security'),
37
- 'education_and_research': _('Education and research'),
38
- 'society_and_demography': _('Society and demography'),
39
- 'law_and_justice': _('Law and justice'),
40
- 'open_data_tools': _('Open data tools'),
41
- 'others': _('Others'),
42
- }
43
-
44
-
45
- IMAGE_SIZES = [500, 100, 50, 25]
46
- IMAGE_MAX_SIZE = 800
47
-
48
- TITLE_SIZE_LIMIT = 350
49
- DESCRIPTION_SIZE_LIMIT = 100000
13
+ __all__ = ('Reuse',)
50
14
 
51
15
 
52
16
  class ReuseQuerySet(db.OwnedQuerySet):
udata/core/spam/api.py CHANGED
@@ -4,7 +4,7 @@ from udata.api import api, API
4
4
  from udata.auth import admin_permission
5
5
  from udata.core.discussions.models import Discussion
6
6
  from udata.core.spam.fields import potential_spam_fields
7
- from udata.core.spam.models import POTENTIAL_SPAM
7
+ from udata.core.spam.constants import POTENTIAL_SPAM
8
8
  from udata.utils import id_or_404
9
9
 
10
10
 
@@ -0,0 +1,5 @@
1
+ NOT_CHECKED = 'not_checked'
2
+ POTENTIAL_SPAM = 'potential_spam'
3
+ NO_SPAM = 'no_spam'
4
+
5
+ SPAM_STATUS_CHOICES = [NOT_CHECKED, POTENTIAL_SPAM, NO_SPAM]
udata/core/spam/fields.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from udata.api import api, fields
2
- from .models import SPAM_STATUS_CHOICES
2
+ from .constants import SPAM_STATUS_CHOICES
3
3
 
4
4
  spam_fields = api.model('Spam', {
5
5
  'status': fields.String(description='Status', enum=SPAM_STATUS_CHOICES, readonly=True),
udata/core/spam/models.py CHANGED
@@ -1,15 +1,11 @@
1
1
  from flask import current_app
2
2
  from langdetect import detect
3
3
 
4
- from udata.models import db
4
+ from udata.mongo import db
5
5
  from .signals import on_new_potential_spam
6
6
  from mongoengine import signals
7
7
 
8
- NOT_CHECKED = 'not_checked'
9
- POTENTIAL_SPAM = 'potential_spam'
10
- NO_SPAM = 'no_spam'
11
-
12
- SPAM_STATUS_CHOICES = [NOT_CHECKED, POTENTIAL_SPAM, NO_SPAM]
8
+ from .constants import NO_SPAM, POTENTIAL_SPAM, SPAM_STATUS_CHOICES, NOT_CHECKED
13
9
 
14
10
 
15
11
  class SpamInfo(db.EmbeddedDocument):
@@ -1,10 +1,10 @@
1
1
  import logging
2
2
  import pytest
3
3
  from udata.tests import TestCase
4
- from udata.tests.helpers import assert_not_emit
5
- from udata.models import db
4
+ from udata.mongo import db
6
5
 
7
- from ..models import POTENTIAL_SPAM, SpamMixin
6
+ from ..models import SpamMixin
7
+ from ..constants import POTENTIAL_SPAM
8
8
 
9
9
 
10
10
  log = logging.getLogger(__name__)
@@ -0,0 +1,9 @@
1
+ from udata.i18n import L_
2
+
3
+ BASE_GRANULARITIES = [
4
+ ('poi', L_('POI')),
5
+ ('other', L_('Other')),
6
+ ]
7
+
8
+ ADMIN_LEVEL_MIN = 1
9
+ ADMIN_LEVEL_MAX = 110
@@ -4,25 +4,14 @@ from werkzeug.utils import cached_property
4
4
 
5
5
  from udata.app import cache
6
6
  from udata.uris import endpoint_for
7
- from udata.i18n import _, L_, get_locale, language
8
- from udata.models import db
7
+ from udata.i18n import _, get_locale, language
8
+ from udata.mongo import db
9
9
 
10
10
  from . import geoids
11
+ from .constants import ADMIN_LEVEL_MIN, ADMIN_LEVEL_MAX, BASE_GRANULARITIES
11
12
 
12
13
 
13
- __all__ = (
14
- 'GeoLevel', 'GeoZone', 'SpatialCoverage', 'BASE_GRANULARITIES',
15
- 'spatial_granularities',
16
- )
17
-
18
-
19
- BASE_GRANULARITIES = [
20
- ('poi', L_('POI')),
21
- ('other', L_('Other')),
22
- ]
23
-
24
- ADMIN_LEVEL_MIN = 1
25
- ADMIN_LEVEL_MAX = 110
14
+ __all__ = ('GeoLevel', 'GeoZone', 'SpatialCoverage', 'spatial_granularities')
26
15
 
27
16
 
28
17
  class GeoLevel(db.Document):
@@ -5,7 +5,7 @@ from datetime import timedelta
5
5
  from werkzeug.datastructures import MultiDict
6
6
 
7
7
  from udata.forms import Form
8
- from udata.models import db
8
+ from udata.mongo import db
9
9
  from udata.tests import TestCase
10
10
  from udata.tests.helpers import assert_json_equal
11
11
  from udata.utils import faker
udata/core/tags/models.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
 
3
- from udata.models import db
3
+ from udata.mongo import db
4
4
 
5
5
  log = logging.getLogger(__name__)
6
6
 
@@ -1,9 +1,7 @@
1
1
  from udata.auth.helpers import current_user_is_admin_or_self
2
2
  from udata.api import api, fields, base_reference
3
3
 
4
- from .models import AVATAR_SIZES
5
-
6
- BIGGEST_AVATAR_SIZE = AVATAR_SIZES[0]
4
+ from .constants import BIGGEST_AVATAR_SIZE
7
5
 
8
6
 
9
7
  user_ref_fields = api.inherit('UserReference', base_reference, {
@@ -0,0 +1,2 @@
1
+ AVATAR_SIZES = [500, 200, 100, 32, 25]
2
+ BIGGEST_AVATAR_SIZE = AVATAR_SIZES[0]
udata/core/user/forms.py CHANGED
@@ -2,7 +2,7 @@ from udata.forms import ModelForm, fields, validators
2
2
  from udata.i18n import lazy_gettext as _
3
3
  from udata.models import User
4
4
 
5
- from .models import AVATAR_SIZES
5
+ from .constants import AVATAR_SIZES
6
6
 
7
7
 
8
8
  __all__ = ('UserProfileForm', 'UserProfileAdminForm')
udata/core/user/models.py CHANGED
@@ -19,10 +19,10 @@ from udata.i18n import lazy_gettext as _
19
19
  from udata.models import db, WithMetrics, Follow
20
20
  from udata.core.discussions.models import Discussion
21
21
  from udata.core.storages import avatars, default_image_basename
22
+ from .constants import AVATAR_SIZES
22
23
 
23
24
  __all__ = ('User', 'Role', 'datastore')
24
25
 
25
- AVATAR_SIZES = [500, 200, 100, 32, 25]
26
26
 
27
27
 
28
28
  # TODO: use simple text for role
udata/factories.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import factory
2
2
 
3
- from .models import DateRange
3
+ from .models import db
4
4
 
5
5
 
6
6
  class ModelFactory(factory.mongoengine.MongoEngineFactory):
@@ -14,7 +14,7 @@ class ModelFactory(factory.mongoengine.MongoEngineFactory):
14
14
 
15
15
  class DateRangeFactory(ModelFactory):
16
16
  class Meta:
17
- model = DateRange
17
+ model = db.DateRange
18
18
 
19
19
  start = factory.Faker('date_between', start_date='-10y', end_date='-5y')
20
20
  end = factory.Faker('date_between', start_date='-5y', end_date='-2y')
@@ -3,7 +3,7 @@ import logging
3
3
  from datetime import datetime
4
4
 
5
5
  from udata.i18n import lazy_gettext as _
6
- from udata.models import db
6
+ from udata.mongo import db
7
7
 
8
8
  log = logging.getLogger(__name__)
9
9
 
udata/frontend/csv.py CHANGED
@@ -8,7 +8,7 @@ from datetime import datetime, date
8
8
 
9
9
  from flask import Response, stream_with_context
10
10
 
11
- from udata.models import db
11
+ from udata.mongo import db
12
12
  from udata.utils import recursive_get
13
13
 
14
14
 
@@ -1,4 +1,4 @@
1
- from udata.models import db
1
+ from udata.mongo import db
2
2
  from udata.core.dataset.models import ResourceMixin
3
3
 
4
4
  # Register harvest extras
udata/models/__init__.py CHANGED
@@ -1,81 +1,7 @@
1
- import logging
2
- import warnings
3
-
4
- from urllib.parse import urlparse
5
-
6
- from bson import ObjectId, DBRef
7
- from flask_mongoengine import MongoEngine, MongoEngineSessionInterface
8
- from mongoengine.base import TopLevelDocumentMetaclass, get_document
9
1
  from mongoengine.errors import ValidationError
10
- from mongoengine.signals import pre_save, post_save
11
-
12
- from flask_storage.mongo import FileField, ImageField
13
2
 
14
3
  from udata import entrypoints
15
- from udata.errors import ConfigError
16
-
17
- from .badges_field import BadgesField
18
- from .taglist_field import TagListField
19
- from .datetime_fields import DateField, DateRange, Datetimed
20
- from .extras_fields import ExtrasField, OrganizationExtrasField
21
- from .slug_fields import SlugField
22
- from .url_field import URLField
23
- from .uuid_fields import AutoUUIDField
24
- from .owned import Owned, OwnedQuerySet
25
- from .queryset import UDataQuerySet
26
- from .document import UDataDocument, DomainModel
27
-
28
- log = logging.getLogger(__name__)
29
-
30
- class UDataMongoEngine(MongoEngine):
31
- '''Customized mongoengine with extra fields types and helpers'''
32
- def __init__(self, app=None):
33
- super(UDataMongoEngine, self).__init__(app)
34
- self.BadgesField = BadgesField
35
- self.TagListField = TagListField
36
- self.DateField = DateField
37
- self.Datetimed = Datetimed
38
- self.ExtrasField = ExtrasField
39
- self.OrganizationExtrasField = OrganizationExtrasField
40
- self.SlugField = SlugField
41
- self.AutoUUIDField = AutoUUIDField
42
- self.Document = UDataDocument
43
- self.DomainModel = DomainModel
44
- self.DateRange = DateRange
45
- self.BaseQuerySet = UDataQuerySet
46
- self.BaseDocumentMetaclass = TopLevelDocumentMetaclass
47
- self.FileField = FileField
48
- self.ImageField = ImageField
49
- self.URLField = URLField
50
- self.ValidationError = ValidationError
51
- self.ObjectId = ObjectId
52
- self.DBRef = DBRef
53
- self.Owned = Owned
54
- self.OwnedQuerySet = OwnedQuerySet
55
- self.post_save = post_save
56
- self.pre_save = pre_save
57
-
58
- def resolve_model(self, model):
59
- '''
60
- Resolve a model given a name or dict with `class` entry.
61
-
62
- :raises ValueError: model specification is wrong or does not exists
63
- '''
64
- if not model:
65
- raise ValueError('Unsupported model specifications')
66
- if isinstance(model, str):
67
- classname = model
68
- elif isinstance(model, dict) and 'class' in model:
69
- classname = model['class']
70
- else:
71
- raise ValueError('Unsupported model specifications')
72
-
73
- try:
74
- return get_document(classname)
75
- except self.NotRegistered:
76
- message = 'Model "{0}" does not exist'.format(classname)
77
- raise ValueError(message)
78
-
4
+ from udata.mongo import *
79
5
 
80
6
  class FieldValidationError(ValidationError):
81
7
  field: str
@@ -84,11 +10,6 @@ class FieldValidationError(ValidationError):
84
10
  self.field = field
85
11
  super().__init__(*args, **kwargs)
86
12
 
87
-
88
- db = UDataMongoEngine()
89
- session_interface = MongoEngineSessionInterface(db)
90
-
91
-
92
13
  # Load all core models and mixins
93
14
  from udata.core.spatial.models import * # noqa
94
15
  from udata.core.metrics.models import * # noqa
@@ -117,43 +38,5 @@ from udata.harvest.models import HarvestSource as Harvest # noqa
117
38
  import udata.linkchecker.models # noqa
118
39
 
119
40
 
120
- MONGODB_DEPRECATED_SETTINGS = 'MONGODB_PORT', 'MONGODB_DB'
121
- MONGODB_DEPRECATED_MSG = '{0} is deprecated, use the MONGODB_HOST url syntax'
122
-
123
-
124
-
125
- def validate_config(config):
126
- for setting in MONGODB_DEPRECATED_SETTINGS:
127
- if setting in config:
128
- msg = MONGODB_DEPRECATED_MSG.format(setting)
129
- log.warning(msg)
130
- warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
131
- url = config['MONGODB_HOST']
132
- parsed_url = urlparse(url)
133
- if not all((parsed_url.scheme, parsed_url.netloc)):
134
- raise ConfigError('{0} is not a valid MongoDB URL'.format(url))
135
- if len(parsed_url.path) <= 1:
136
- raise ConfigError('{0} is missing the database path'.format(url))
137
-
138
-
139
- def build_test_config(config):
140
- if 'MONGODB_HOST_TEST' in config:
141
- config['MONGODB_HOST'] = config['MONGODB_HOST_TEST']
142
- else:
143
- # use `{database_name}-test` database for testing
144
- parsed_url = urlparse(config['MONGODB_HOST'])
145
- parsed_url = parsed_url._replace(path='%s-test' % parsed_url.path)
146
- config['MONGODB_HOST'] = parsed_url.geturl()
147
- validate_config(config)
148
-
149
-
150
- # Avoid nose misdetecting this function as a test
151
- build_test_config.__test__ = False
152
-
153
-
154
41
  def init_app(app):
155
- validate_config(app.config)
156
- if app.config['TESTING']:
157
- build_test_config(app.config)
158
- db.init_app(app)
159
42
  entrypoints.get_enabled('udata.models', app)
@@ -0,0 +1,42 @@
1
+ import logging
2
+ import warnings
3
+ from urllib.parse import urlparse
4
+
5
+ from udata.errors import ConfigError
6
+
7
+ from .engine import db
8
+
9
+ log = logging.getLogger(__name__)
10
+
11
+ MONGODB_DEPRECATED_SETTINGS = 'MONGODB_PORT', 'MONGODB_DB'
12
+ MONGODB_DEPRECATED_MSG = '{0} is deprecated, use the MONGODB_HOST url syntax'
13
+
14
+ def validate_config(config):
15
+ for setting in MONGODB_DEPRECATED_SETTINGS:
16
+ if setting in config:
17
+ msg = MONGODB_DEPRECATED_MSG.format(setting)
18
+ log.warning(msg)
19
+ warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
20
+ url = config['MONGODB_HOST']
21
+ parsed_url = urlparse(url)
22
+ if not all((parsed_url.scheme, parsed_url.netloc)):
23
+ raise ConfigError('{0} is not a valid MongoDB URL'.format(url))
24
+ if len(parsed_url.path) <= 1:
25
+ raise ConfigError('{0} is missing the database path'.format(url))
26
+
27
+
28
+ def build_test_config(config):
29
+ if 'MONGODB_HOST_TEST' in config:
30
+ config['MONGODB_HOST'] = config['MONGODB_HOST_TEST']
31
+ else:
32
+ # use `{database_name}-test` database for testing
33
+ parsed_url = urlparse(config['MONGODB_HOST'])
34
+ parsed_url = parsed_url._replace(path='%s-test' % parsed_url.path)
35
+ config['MONGODB_HOST'] = parsed_url.geturl()
36
+ validate_config(config)
37
+
38
+ def init_app(app):
39
+ validate_config(app.config)
40
+ if app.config['TESTING']:
41
+ build_test_config(app.config)
42
+ db.init_app(app)
udata/mongo/engine.py ADDED
@@ -0,0 +1,73 @@
1
+ from bson import ObjectId, DBRef
2
+ from flask_mongoengine import MongoEngine, MongoEngineSessionInterface
3
+ from mongoengine.base import TopLevelDocumentMetaclass, get_document
4
+ from mongoengine.errors import ValidationError
5
+ from mongoengine.signals import pre_save, post_save
6
+
7
+ from flask_storage.mongo import FileField, ImageField
8
+
9
+ from .badges_field import BadgesField
10
+ from .taglist_field import TagListField
11
+ from .datetime_fields import DateField, DateRange, Datetimed
12
+ from .extras_fields import ExtrasField, OrganizationExtrasField
13
+ from .slug_fields import SlugField
14
+ from .url_field import URLField
15
+ from .uuid_fields import AutoUUIDField
16
+ from .owned import Owned, OwnedQuerySet
17
+ from .queryset import UDataQuerySet
18
+ from .document import UDataDocument, DomainModel
19
+
20
+
21
+ class UDataMongoEngine(MongoEngine):
22
+ '''Customized mongoengine with extra fields types and helpers'''
23
+ def __init__(self, app=None):
24
+ super(UDataMongoEngine, self).__init__(app)
25
+ self.BadgesField = BadgesField
26
+ self.TagListField = TagListField
27
+ self.DateField = DateField
28
+ self.Datetimed = Datetimed
29
+ self.ExtrasField = ExtrasField
30
+ self.OrganizationExtrasField = OrganizationExtrasField
31
+ self.SlugField = SlugField
32
+ self.AutoUUIDField = AutoUUIDField
33
+ self.Document = UDataDocument
34
+ self.DomainModel = DomainModel
35
+ self.DateRange = DateRange
36
+ self.BaseQuerySet = UDataQuerySet
37
+ self.BaseDocumentMetaclass = TopLevelDocumentMetaclass
38
+ self.FileField = FileField
39
+ self.ImageField = ImageField
40
+ self.URLField = URLField
41
+ self.ValidationError = ValidationError
42
+ self.ObjectId = ObjectId
43
+ self.DBRef = DBRef
44
+ self.Owned = Owned
45
+ self.OwnedQuerySet = OwnedQuerySet
46
+ self.post_save = post_save
47
+ self.pre_save = pre_save
48
+
49
+ def resolve_model(self, model):
50
+ '''
51
+ Resolve a model given a name or dict with `class` entry.
52
+
53
+ :raises ValueError: model specification is wrong or does not exists
54
+ '''
55
+ if not model:
56
+ raise ValueError('Unsupported model specifications')
57
+ if isinstance(model, str):
58
+ classname = model
59
+ elif isinstance(model, dict) and 'class' in model:
60
+ classname = model['class']
61
+ else:
62
+ raise ValueError('Unsupported model specifications')
63
+
64
+ try:
65
+ return get_document(classname)
66
+ except self.NotRegistered:
67
+ message = 'Model "{0}" does not exist'.format(classname)
68
+ raise ValueError(message)
69
+
70
+
71
+
72
+ db = UDataMongoEngine()
73
+ session_interface = MongoEngineSessionInterface(db)
udata/routing.py CHANGED
@@ -8,7 +8,7 @@ from werkzeug.routing import BaseConverter, PathConverter
8
8
  from werkzeug.urls import url_quote
9
9
 
10
10
  from udata import models
11
- from udata.models import db
11
+ from udata.mongo import db
12
12
  from udata.core.spatial.models import GeoZone
13
13
  from udata.i18n import ISO_639_1_CODES
14
14
 
udata/search/__init__.py CHANGED
@@ -6,7 +6,7 @@ import udata.event # noqa
6
6
  from flask import current_app
7
7
  from mongoengine.signals import post_save, post_delete
8
8
 
9
- from udata.models import db
9
+ from udata.mongo import db
10
10
  from udata.tasks import task, as_task_param
11
11
 
12
12
  log = logging.getLogger(__name__)
@@ -25,9 +25,8 @@ from udata.core.spatial.factories import SpatialCoverageFactory
25
25
  from udata.core.topic.factories import TopicFactory
26
26
  from udata.core.user.factories import AdminFactory, UserFactory
27
27
  from udata.i18n import gettext as _
28
- from udata.models import (LEGACY_FREQUENCIES, RESOURCE_TYPES,
29
- UPDATE_FREQUENCIES, CommunityResource, Dataset,
30
- Follow, Member, db)
28
+ from udata.models import CommunityResource, Dataset, Follow, Member, db
29
+ from udata.core.dataset.constants import LEGACY_FREQUENCIES, RESOURCE_TYPES, UPDATE_FREQUENCIES
31
30
  from udata.tags import MAX_TAG_LENGTH, MIN_TAG_LENGTH
32
31
  from udata.tests.features.territories import create_geozones_fixtures
33
32
  from udata.tests.helpers import assert200, assert404, assert204
@@ -10,7 +10,8 @@ from udata.core.user.factories import AdminFactory
10
10
  from udata.core.reuse.factories import ReuseFactory
11
11
  from udata.core.organization.factories import OrganizationFactory
12
12
  from udata.core.user.factories import UserFactory
13
- from udata.models import Reuse, Follow, Member, REUSE_TOPICS, REUSE_TYPES
13
+ from udata.models import Reuse, Follow, Member
14
+ from udata.core.reuse.constants import REUSE_TOPICS, REUSE_TYPES
14
15
  from udata.utils import faker
15
16
 
16
17
  from udata.tests.helpers import (
@@ -3,12 +3,11 @@ from datetime import datetime, timedelta
3
3
  import pytest
4
4
  import requests
5
5
  from flask import current_app
6
- from mongoengine import post_save, ValidationError
6
+ from mongoengine import post_save
7
7
 
8
8
  from udata.app import cache
9
- from udata.models import (
10
- db, Dataset, License, LEGACY_FREQUENCIES, ResourceSchema, UPDATE_FREQUENCIES, Schema, FieldValidationError
11
- )
9
+ from udata.models import db, Dataset, License, ResourceSchema, Schema
10
+ from udata.core.dataset.constants import LEGACY_FREQUENCIES, UPDATE_FREQUENCIES
12
11
  from udata.core.dataset.models import HarvestDatasetMetadata, HarvestResourceMetadata
13
12
  from udata.core.dataset.factories import (
14
13
  ResourceFactory, DatasetFactory, CommunityResourceFactory, LicenseFactory, ResourceSchemaMockData
@@ -10,7 +10,7 @@ from rdflib import Graph, URIRef, Literal, BNode
10
10
  from rdflib.namespace import FOAF, RDF
11
11
  from rdflib.resource import Resource as RdfResource
12
12
 
13
- from udata.models import db
13
+ from udata.mongo import db
14
14
  from udata.core.dataset.models import Dataset, Resource, License, Checksum, HarvestDatasetMetadata
15
15
  from udata.core.dataset.factories import (
16
16
  DatasetFactory, ResourceFactory, LicenseFactory
@@ -1,7 +1,7 @@
1
1
  from werkzeug.datastructures import MultiDict
2
2
 
3
3
  from udata.forms import Form, fields
4
- from udata.models import db
4
+ from udata.mongo import db
5
5
  from udata.tests import TestCase
6
6
  from udata.utils import faker
7
7
 
@@ -3,7 +3,7 @@ from datetime import date, timedelta
3
3
  from werkzeug.datastructures import MultiDict
4
4
 
5
5
  from udata.forms import Form, fields
6
- from udata.models import db
6
+ from udata.mongo import db
7
7
  from udata.tests import TestCase
8
8
  from udata.utils import to_iso_date
9
9