Merge pull request #860 from taigaio/libs/upgrade

Upgrade requirements
remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro 2016-11-10 14:38:54 +01:00 committed by GitHub
commit 17bea5b219
83 changed files with 1780 additions and 315 deletions

View File

@ -1,13 +1,13 @@
-r requirements.txt
factory_boy==2.6.1
factory_boy==2.7.0
py==1.4.31
pytest==2.8.7
pytest-django==2.9.1
pytest-pythonpath==0.7
pytest==3.0.3
pytest-django==3.0.0
pytest-pythonpath==0.7.1
coverage==4.0.3
coverage==4.2
coveralls==1.1
django-slowdown==0.0.1
transifex-client==0.11.1.beta
transifex-client==0.12.2

View File

@ -1,37 +1,35 @@
Django==1.9.2
Django==1.10.3
#djangorestframework==2.3.13 # It's not necessary since Taiga 1.7
django-picklefield==0.3.2
django-sampledatahelper==0.4.0
gunicorn==19.4.5
psycopg2==2.6.1
Pillow==3.1.1
pytz==2015.7
gunicorn==19.6.0
psycopg2==2.6.2
Pillow==3.4.2
pytz==2016.7
six==1.10.0
amqp==1.4.9
djmail==0.12.0.post1
django-pgjson==0.3.1
djorm-pgarray==1.2 # Use until Taiga 2.1. Keep compatibility with old migrations
django-jinja==2.1.2
amqp==2.1.1
djmail==0.13.0
django-jinja==2.2.1
jinja2==2.8
pygments==2.0.2
pygments==2.1.3
django-sites==0.9
Markdown==2.6.5
Markdown==2.6.7
fn==0.4.3
diff-match-patch==20121119
requests==2.9.1
django-sr==0.0.4
easy-thumbnails==2.3
celery==3.1.20
celery==3.1.24
redis==2.10.5
Unidecode==0.04.19
raven==5.10.2
bleach==1.4.3
django-ipware==1.1.3
premailer==2.9.7
django-ipware==1.1.6
premailer==3.0.1
cssutils==1.0.1 # Compatible with python 3.5
lxml==3.5.0
git+https://github.com/Xof/django-pglocks.git@dbb8d7375066859f897604132bd437832d2014ea
pyjwkest==1.1.5
python-dateutil==2.4.2
lxml==3.6.4
git+https://github.com/Xof/django-pglocks.git
pyjwkest==1.3.1
python-dateutil==2.5.3
netaddr==0.7.18
serpy==0.1.1

View File

@ -282,6 +282,7 @@ INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.staticfiles",
"django.contrib.sitemaps",
"django.contrib.postgres",
"taiga.base",
"taiga.base.api",

View File

@ -817,8 +817,18 @@ class ModelSerializer((six.with_metaclass(SerializerMetaclass, BaseSerializer)))
else:
# Reverse relationships are only included if they are explicitly
# present in the `fields` option on the serializer
reverse_rels = opts.get_all_related_objects()
reverse_rels += opts.get_all_related_many_to_many_objects()
# NOTE: Rewrite after Django 1.10 upgrade.
# See https://docs.djangoproject.com/es/1.10/ref/models/meta/#migrating-from-the-old-api
reverse_rels = [
f for f in opts.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
reverse_rels += [
f for f in opts.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]
for relation in reverse_rels:
accessor_name = relation.get_accessor_name()
@ -1024,16 +1034,32 @@ class ModelSerializer((six.with_metaclass(SerializerMetaclass, BaseSerializer)))
m2m_data = {}
related_data = {}
nested_forward_relations = {}
model = self.opts.model
meta = self.opts.model._meta
# Reverse fk or one-to-one relations
for (obj, model) in meta.get_all_related_objects_with_model():
# NOTE: Rewrite after Django 1.10 upgrade.
# See https://docs.djangoproject.com/es/1.10/ref/models/meta/#migrating-from-the-old-api
related_objes_with_models = [
(f, f.model if f.model != model else None)
for f in meta.get_fields()
if (f.one_to_many or f.one_to_one)
and f.auto_created and not f.concrete
]
for (obj, model) in related_objes_with_models:
field_name = obj.get_accessor_name()
if field_name in attrs:
related_data[field_name] = attrs.pop(field_name)
# Reverse m2m relations
for (obj, model) in meta.get_all_related_m2m_objects_with_model():
# NOTE: Rewrite after Django 1.10 upgrade.
# See https://docs.djangoproject.com/es/1.10/ref/models/meta/#migrating-from-the-old-api
related_m2m_objects_with_model = [
(f, f.model if f.model != model else None)
for f in meta.get_fields(include_hidden=True)
if f.many_to_many and f.auto_created
]
for (obj, model) in related_m2m_objects_with_model:
field_name = obj.get_accessor_name()
if field_name in attrs:
m2m_data[field_name] = attrs.pop(field_name)

View File

@ -44,7 +44,7 @@
from django.core.urlresolvers import RegexURLResolver
from django.conf.urls import patterns, url, include
from django.conf.urls import url, include
from .settings import api_settings
@ -67,7 +67,7 @@ def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required):
else:
# Regular URL pattern
regex = urlpattern.regex.pattern.rstrip("$") + suffix_pattern
view = urlpattern._callback or urlpattern._callback_str
view = urlpattern.callback
kwargs = urlpattern.default_args
name = urlpattern.name
# Add in both the existing and the new urlpattern

View File

View File

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .json import JSONField

View File

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2016 Andrey Antukh <niwi@niwi.nz>
# Copyright (C) 2014-2016 Jesús Espino <jespinog@gmail.com>
# Copyright (C) 2014-2016 David Barragán <bameda@dbarragan.com>
# Copyright (C) 2014-2016 Alejandro Alonso <alejandro.alonso@kaleidos.net>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.core.serializers.json import DjangoJSONEncoder
from django.contrib.postgres.fields import JSONField as DjangoJSONField
# NOTE: After upgrade Django to the future release (1.11) change
# class JSONField(FutureDjangoJSONField):
# to
# class JSONField(DjangoJSONField):
# and remove the classes JsonAdapter and FutureDjangoJSONField
import json
from psycopg2.extras import Json
from django.core import exceptions
class JsonAdapter(Json):
"""
Customized psycopg2.extras.Json to allow for a custom encoder.
"""
def __init__(self, adapted, dumps=None, encoder=None):
self.encoder = encoder
super().__init__(adapted, dumps=dumps)
def dumps(self, obj):
options = {'cls': self.encoder} if self.encoder else {}
return json.dumps(obj, **options)
class FutureDjangoJSONField(DjangoJSONField):
def __init__(self, verbose_name=None, name=None, encoder=None, **kwargs):
if encoder and not callable(encoder):
raise ValueError("The encoder parameter must be a callable object.")
self.encoder = encoder
super().__init__(verbose_name, name, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.encoder is not None:
kwargs['encoder'] = self.encoder
return name, path, args, kwargs
def get_prep_value(self, value):
if value is not None:
return JsonAdapter(value, encoder=self.encoder)
return value
def validate(self, value, model_instance):
super().validate(value, model_instance)
options = {'cls': self.encoder} if self.encoder else {}
try:
json.dumps(value, **options)
except TypeError:
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)
__all__ = ["JSONField"]
class JSONField(FutureDjangoJSONField):
def __init__(self, verbose_name=None, name=None, encoder=DjangoJSONEncoder, **kwargs):
super().__init__(verbose_name, name, encoder, **kwargs)

View File

@ -30,7 +30,7 @@ import serpy
# NOTE: This should be in other place, for example taiga.base.api.serializers
class JsonField(serializers.WritableField):
class JSONField(serializers.WritableField):
"""
Json objects serializer.
"""
@ -95,12 +95,12 @@ class I18NField(Field):
return _(ret)
class I18NJsonField(Field):
class I18NJSONField(Field):
"""
Json objects serializer.
"""
def __init__(self, i18n_fields=(), *args, **kwargs):
super(I18NJsonField, self).__init__(*args, **kwargs)
super(I18NJSONField, self).__init__(*args, **kwargs)
self.i18n_fields = i18n_fields
def translate_values(self, d):

View File

@ -18,8 +18,6 @@
import datetime
from optparse import make_option
from django.apps import apps
from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
@ -33,28 +31,27 @@ from taiga.projects.history.services import get_history_queryset_by_model_instan
class Command(BaseCommand):
args = '<email>'
option_list = BaseCommand.option_list + (
make_option('--locale', '-l', default=None, dest='locale',
help='Send emails in an specific language.'),
)
help = 'Send an example of all emails'
def handle(self, *args, **options):
if len(args) != 1:
print("Usage: ./manage.py test_emails <email-address>")
return
def add_arguments(self, parser):
parser.add_argument('--locale', '-l',
default=None,
dest='locale',
help='Send emails in an specific language.')
parser.add_argument('email',
help='Emeil address to send sample emails.')
def handle(self, *args, **options):
locale = options.get('locale')
test_email = args[0]
email_address = options.get('email')
# Register email
context = {"lang": locale,
"user": get_user_model().objects.all().order_by("?").first(),
"cancel_token": "cancel-token"}
email = mail_builder.registered_user(test_email, context)
email = mail_builder.registered_user(email_address, context)
email.send()
# Membership invitation
@ -63,13 +60,13 @@ class Command(BaseCommand):
membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"
context = {"lang": locale, "membership": membership}
email = mail_builder.membership_invitation(test_email, context)
email = mail_builder.membership_invitation(email_address, context)
email.send()
# Membership notification
context = {"lang": locale,
"membership": Membership.objects.order_by("?").filter(user__isnull=False).first()}
email = mail_builder.membership_notification(test_email, context)
email = mail_builder.membership_notification(email_address, context)
email.send()
# Feedback
@ -85,17 +82,17 @@ class Command(BaseCommand):
"key2": "value2",
},
}
email = mail_builder.feedback_notification(test_email, context)
email = mail_builder.feedback_notification(email_address, context)
email.send()
# Password recovery
context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
email = mail_builder.password_recovery(test_email, context)
email = mail_builder.password_recovery(email_address, context)
email.send()
# Change email
context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
email = mail_builder.change_email(test_email, context)
email = mail_builder.change_email(email_address, context)
email.send()
# Export/Import emails
@ -106,7 +103,7 @@ class Command(BaseCommand):
"error_subject": "Error generating project dump",
"error_message": "Error generating project dump",
}
email = mail_builder.export_error(test_email, context)
email = mail_builder.export_error(email_address, context)
email.send()
context = {
"lang": locale,
@ -114,7 +111,7 @@ class Command(BaseCommand):
"error_subject": "Error importing project dump",
"error_message": "Error importing project dump",
}
email = mail_builder.import_error(test_email, context)
email = mail_builder.import_error(email_address, context)
email.send()
deletion_date = timezone.now() + datetime.timedelta(seconds=60*60*24)
@ -125,7 +122,7 @@ class Command(BaseCommand):
"project": Project.objects.all().order_by("?").first(),
"deletion_date": deletion_date,
}
email = mail_builder.dump_project(test_email, context)
email = mail_builder.dump_project(email_address, context)
email.send()
context = {
@ -133,7 +130,7 @@ class Command(BaseCommand):
"user": get_user_model().objects.all().order_by("?").first(),
"project": Project.objects.all().order_by("?").first(),
}
email = mail_builder.load_dump(test_email, context)
email = mail_builder.load_dump(email_address, context)
email.send()
# Notification emails
@ -187,7 +184,7 @@ class Command(BaseCommand):
cls = type("InlineCSSTemplateMail", (InlineCSSTemplateMail,), {"name": notification_email[1]})
email = cls()
email.send(test_email, context)
email.send(email_address, context)
# Transfer Emails
@ -195,7 +192,7 @@ class Command(BaseCommand):
"project": Project.objects.all().order_by("?").first(),
"requester": User.objects.all().order_by("?").first(),
}
email = mail_builder.transfer_request(test_email, context)
email = mail_builder.transfer_request(email_address, context)
email.send()
context = {
@ -204,7 +201,7 @@ class Command(BaseCommand):
"token": "test-token",
"reason": "Test reason"
}
email = mail_builder.transfer_start(test_email, context)
email = mail_builder.transfer_start(email_address, context)
email.send()
context = {
@ -213,7 +210,7 @@ class Command(BaseCommand):
"new_owner": User.objects.all().order_by("?").first(),
"reason": "Test reason"
}
email = mail_builder.transfer_accept(test_email, context)
email = mail_builder.transfer_accept(email_address, context)
email.send()
context = {
@ -221,5 +218,5 @@ class Command(BaseCommand):
"rejecter": User.objects.all().order_by("?").first(),
"reason": "Test reason"
}
email = mail_builder.transfer_reject(test_email, context)
email = mail_builder.transfer_reject(email_address, context)
email.send()

View File

@ -20,7 +20,7 @@
import itertools
from collections import namedtuple
from django.conf.urls import patterns, url
from django.conf.urls import url
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import NoReverseMatch
@ -79,7 +79,7 @@ class BaseRouter(object):
@property
def urls(self):
if not hasattr(self, '_urls'):
self._urls = patterns('', *self.get_urls())
self._urls = self.get_urls()
return self._urls

View File

@ -26,7 +26,7 @@ from django.contrib.contenttypes.models import ContentType
from taiga.base.api import serializers
from taiga.base.exceptions import ValidationError
from taiga.base.fields import JsonField
from taiga.base.fields import JSONField
from taiga.mdrender.service import render as mdrender
from taiga.users import models as users_models
@ -144,7 +144,7 @@ class ProjectRelatedField(serializers.RelatedField):
raise ValidationError(_("{}=\"{}\" not found in this project".format(self.slug_field, data)))
class HistoryUserField(JsonField):
class HistoryUserField(JSONField):
def from_native(self, data):
if data is None:
return {}
@ -162,7 +162,7 @@ class HistoryUserField(JsonField):
return {"pk": pk, "name": data[1]}
class HistoryValuesField(JsonField):
class HistoryValuesField(JSONField):
def from_native(self, data):
if data is None:
return []
@ -171,7 +171,7 @@ class HistoryValuesField(JsonField):
return data
class HistoryDiffField(JsonField):
class HistoryDiffField(JSONField):
def from_native(self, data):
if data is None:
return []

View File

@ -28,13 +28,13 @@ from taiga.projects.notifications import services as notifications_services
from taiga.projects.history import services as history_service
from .fields import (UserRelatedField, HistoryUserField, HistoryDiffField,
JsonField, HistoryValuesField, CommentField, FileField)
JSONField, HistoryValuesField, CommentField, FileField)
class HistoryExportValidator(validators.ModelValidator):
user = HistoryUserField()
diff = HistoryDiffField(required=False)
snapshot = JsonField(required=False)
snapshot = JSONField(required=False)
values = HistoryValuesField(required=False)
comment = CommentField(required=False)
delete_comment_date = serializers.DateTimeField(required=False)

View File

@ -20,7 +20,7 @@ from django.utils.translation import ugettext as _
from taiga.base.api import serializers
from taiga.base.api import validators
from taiga.base.fields import JsonField, PgArrayField
from taiga.base.fields import JSONField, PgArrayField
from taiga.base.exceptions import ValidationError
from taiga.projects import models as projects_models
@ -133,7 +133,7 @@ class IssueCustomAttributeExportValidator(validators.ModelValidator):
class BaseCustomAttributesValuesExportValidator(validators.ModelValidator):
attributes_values = JsonField(source="attributes_values", required=True)
attributes_values = JSONField(source="attributes_values", required=True)
_custom_attribute_model = None
_container_field = None
@ -378,7 +378,7 @@ class ProjectExportValidator(WatcheableObjectModelValidatorMixin):
issue_statuses = IssueStatusExportValidator(many=True, required=False)
priorities = PriorityExportValidator(many=True, required=False)
severities = SeverityExportValidator(many=True, required=False)
tags_colors = JsonField(required=False)
tags_colors = JSONField(required=False)
creation_template = serializers.SlugRelatedField(slug_field="slug", required=False)
default_points = serializers.SlugRelatedField(slug_field="name", required=False)
default_us_status = serializers.SlugRelatedField(slug_field="name", required=False)

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('version', models.IntegerField(default=1, verbose_name='version')),
('attributes_values', django_pgjson.fields.JsonField(default={}, verbose_name='attributes_values')),
('attributes_values', taiga.base.db.models.fields.JSONField(default={}, verbose_name='attributes_values')),
('issue', models.OneToOneField(verbose_name='issue', to='issues.Issue', related_name='custom_attributes_values')),
],
options={
@ -36,7 +36,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('version', models.IntegerField(default=1, verbose_name='version')),
('attributes_values', django_pgjson.fields.JsonField(default={}, verbose_name='attributes_values')),
('attributes_values', taiga.base.db.models.fields.JSONField(default={}, verbose_name='attributes_values')),
('task', models.OneToOneField(verbose_name='task', to='tasks.Task', related_name='custom_attributes_values')),
],
options={
@ -52,7 +52,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
('version', models.IntegerField(default=1, verbose_name='version')),
('attributes_values', django_pgjson.fields.JsonField(default={}, verbose_name='attributes_values')),
('attributes_values', taiga.base.db.models.fields.JSONField(default={}, verbose_name='attributes_values')),
('user_story', models.OneToOneField(verbose_name='user story', to='userstories.UserStory', related_name='custom_attributes_values')),
],
options={

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -15,19 +15,19 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='issuecustomattributesvalues',
name='attributes_values',
field=django_pgjson.fields.JsonField(verbose_name='values', default={}),
field=taiga.base.db.models.fields.JSONField(verbose_name='values', default={}),
preserve_default=True,
),
migrations.AlterField(
model_name='taskcustomattributesvalues',
name='attributes_values',
field=django_pgjson.fields.JsonField(verbose_name='values', default={}),
field=taiga.base.db.models.fields.JSONField(verbose_name='values', default={}),
preserve_default=True,
),
migrations.AlterField(
model_name='userstorycustomattributesvalues',
name='attributes_values',
field=django_pgjson.fields.JsonField(verbose_name='values', default={}),
field=taiga.base.db.models.fields.JSONField(verbose_name='values', default={}),
preserve_default=True,
),
]

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -55,7 +55,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.IntegerField(default=1, verbose_name='version')),
('attributes_values', django_pgjson.fields.JsonField(default={}, verbose_name='values')),
('attributes_values', taiga.base.db.models.fields.JSONField(default={}, verbose_name='values')),
('epic', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='custom_attributes_values', to='epics.Epic', verbose_name='epic')),
],
options={

View File

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:34
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('custom_attributes', '0010_auto_20160928_0540'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="custom_attributes_epiccustomattributesvalues",
column_name="attributes_values",
),
reverse_sql=migrations.RunSQL.noop
),
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="custom_attributes_userstorycustomattributesvalues",
column_name="attributes_values",
),
reverse_sql=migrations.RunSQL.noop
),
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="custom_attributes_taskcustomattributesvalues",
column_name="attributes_values",
),
reverse_sql=migrations.RunSQL.noop
),
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="custom_attributes_issuecustomattributesvalues",
column_name="attributes_values",
),
reverse_sql=migrations.RunSQL.noop
),
# Function: Remove a key in a json field
migrations.RunSQL(
"""
CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" jsonb, VARIADIC "keys_to_delete" text[])
RETURNS jsonb
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT COALESCE ((SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
FROM jsonb_each("json")
WHERE "key" <> ALL ("keys_to_delete")),
'{}')::text::jsonb $function$;
""",
reverse_sql="""
CREATE OR REPLACE FUNCTION "json_object_delete_keys"("json" json, VARIADIC "keys_to_delete" text[])
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT COALESCE ((SELECT ('{' || string_agg(to_json("key") || ':' || "value", ',') || '}')
FROM json_each("json")
WHERE "key" <> ALL ("keys_to_delete")),
'{}')::json $function$;"""
),
]

View File

@ -20,7 +20,7 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from taiga.base.utils.time import timestamp_ms
from taiga.projects.occ.mixins import OCCModelMixin
@ -92,7 +92,7 @@ class IssueCustomAttribute(AbstractCustomAttribute):
#######################################################
class AbstractCustomAttributesValues(OCCModelMixin, models.Model):
attributes_values = JsonField(null=False, blank=False, default={}, verbose_name=_("values"))
attributes_values = JSONField(null=False, blank=False, default={}, verbose_name=_("values"))
class Meta:
abstract = True

View File

@ -17,7 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from taiga.base.fields import JsonField, Field
from taiga.base.fields import JSONField, Field
from taiga.base.api import serializers

View File

@ -19,7 +19,7 @@
from django.utils.translation import ugettext_lazy as _
from taiga.base.fields import JsonField
from taiga.base.fields import JSONField
from taiga.base.exceptions import ValidationError
from taiga.base.api.validators import ModelValidator
@ -92,7 +92,7 @@ class IssueCustomAttributeValidator(BaseCustomAttributeValidator):
class BaseCustomAttributesValuesValidator(ModelValidator):
attributes_values = JsonField(source="attributes_values", label="attributes values")
attributes_values = JSONField(source="attributes_values", label="attributes values")
_custom_attribute_model = None
_container_field = None

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
import taiga.projects.history.models
import django.utils.timezone
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -17,14 +17,14 @@ class Migration(migrations.Migration):
name='HistoryEntry',
fields=[
('id', models.CharField(primary_key=True, unique=True, max_length=255, serialize=False, default=taiga.projects.history.models._generate_uuid, editable=False)),
('user', django_pgjson.fields.JsonField(default=None, blank=True, null=True)),
('user', taiga.base.db.models.fields.JSONField(default=None, blank=True, null=True)),
('created_at', models.DateTimeField(default=django.utils.timezone.now)),
('type', models.SmallIntegerField(choices=[(1, 'Change'), (2, 'Create'), (3, 'Delete')])),
('is_snapshot', models.BooleanField(default=False)),
('key', models.CharField(max_length=255, default=None, blank=True, null=True)),
('diff', django_pgjson.fields.JsonField(default=None, null=True)),
('snapshot', django_pgjson.fields.JsonField(default=None, null=True)),
('values', django_pgjson.fields.JsonField(default=None, null=True)),
('diff', taiga.base.db.models.fields.JSONField(default=None, null=True)),
('snapshot', taiga.base.db.models.fields.JSONField(default=None, null=True)),
('values', taiga.base.db.models.fields.JSONField(default=None, null=True)),
('comment', models.TextField(blank=True)),
('comment_html', models.TextField(blank=True)),
],

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
import django_pgjson.fields
import taiga.base.db.models.fields
def change_fk_with_tuple_pk_and_name(apps, schema_editor):
HistoryEntry = apps.get_model("history", "HistoryEntry")
@ -31,7 +31,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='historyentry',
name='delete_comment_user',
field=django_pgjson.fields.JsonField(null=True, blank=True, default=None),
field=taiga.base.db.models.fields.JSONField(null=True, blank=True, default=None),
preserve_default=True,
),

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from django.db import models, migrations

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -15,19 +15,19 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='historyentry',
name='diff',
field=django_pgjson.fields.JsonField(null=True, default=None, blank=True),
field=taiga.base.db.models.fields.JSONField(null=True, default=None, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='historyentry',
name='snapshot',
field=django_pgjson.fields.JsonField(null=True, default=None, blank=True),
field=taiga.base.db.models.fields.JSONField(null=True, default=None, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='historyentry',
name='values',
field=django_pgjson.fields.JsonField(null=True, default=None, blank=True),
field=taiga.base.db.models.fields.JSONField(null=True, default=None, blank=True),
preserve_default=True,
),
]

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals
from django.db import migrations, models
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='historyentry',
name='comment_versions',
field=django_pgjson.fields.JsonField(blank=True, default=None, null=True),
field=taiga.base.db.models.fields.JSONField(blank=True, default=None, null=True),
),
migrations.AddField(
model_name='historyentry',

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals
from django.db import migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -16,6 +16,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='historyentry',
name='values_diff_cache',
field=django_pgjson.fields.JsonField(blank=True, default=None, null=True),
field=taiga.base.db.models.fields.JSONField(blank=True, default=None, null=True),
),
]

View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:34
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('history', '0013_historyentry_values_diff_cache'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "history_historyentry"
ALTER COLUMN "delete_comment_user" TYPE jsonb USING to_json("delete_comment_user"::text)::jsonb,
ALTER COLUMN "comment_versions" TYPE jsonb USING to_json("comment_versions"::text)::jsonb,
ALTER COLUMN "values_diff_cache" TYPE jsonb USING to_json("values_diff_cache"::text)::jsonb,
ALTER COLUMN "user" TYPE jsonb USING to_json("user"::text)::jsonb,
ALTER COLUMN "diff" TYPE jsonb USING to_json("diff"::text)::jsonb,
ALTER COLUMN "snapshot" TYPE jsonb USING to_json("snapshot"::text)::jsonb,
ALTER COLUMN "values" TYPE jsonb USING to_json("values"::text)::jsonb;
""",
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -22,7 +22,7 @@ from django.utils import timezone
from django.db import models
from django.contrib.auth import get_user_model
from django.utils.functional import cached_property
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from taiga.mdrender.service import get_diff_of_htmls
@ -52,32 +52,32 @@ class HistoryEntry(models.Model):
editable=False, default=_generate_uuid)
project = models.ForeignKey("projects.Project")
user = JsonField(null=True, blank=True, default=None)
user = JSONField(null=True, blank=True, default=None)
created_at = models.DateTimeField(default=timezone.now)
type = models.SmallIntegerField(choices=HISTORY_TYPE_CHOICES)
key = models.CharField(max_length=255, null=True, default=None, blank=True, db_index=True)
# Stores the last diff
diff = JsonField(null=True, blank=True, default=None)
diff = JSONField(null=True, blank=True, default=None)
# Stores the values_diff cache
values_diff_cache = JsonField(null=True, blank=True, default=None)
values_diff_cache = JSONField(null=True, blank=True, default=None)
# Stores the last complete frozen object snapshot
snapshot = JsonField(null=True, blank=True, default=None)
snapshot = JSONField(null=True, blank=True, default=None)
# Stores a values of all identifiers used in
values = JsonField(null=True, blank=True, default=None)
values = JSONField(null=True, blank=True, default=None)
# Stores a comment
comment = models.TextField(blank=True)
comment_html = models.TextField(blank=True)
delete_comment_date = models.DateTimeField(null=True, blank=True, default=None)
delete_comment_user = JsonField(null=True, blank=True, default=None)
delete_comment_user = JSONField(null=True, blank=True, default=None)
# Historic version of comments
comment_versions = JsonField(null=True, blank=True, default=None)
comment_versions = JSONField(null=True, blank=True, default=None)
edit_comment_date = models.DateTimeField(null=True, blank=True, default=None)
# Flag for mark some history entries as

View File

@ -17,7 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from taiga.base.api import serializers
from taiga.base.fields import I18NJsonField, Field, MethodField
from taiga.base.fields import I18NJSONField, Field, MethodField
from taiga.users.services import get_user_photo_url
from taiga.users.gravatar import get_user_gravatar_id
@ -35,8 +35,8 @@ class HistoryEntrySerializer(serializers.LightSerializer):
diff = Field()
snapshot = Field()
values = Field()
values_diff = I18NJsonField()
comment = I18NJsonField()
values_diff = I18NJSONField()
comment = I18NJSONField()
comment_html = Field()
delete_comment_date = Field()
delete_comment_user = Field()

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
import django.utils.timezone
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
name='Issue',
fields=[
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
('tags', djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='tags')),
('tags', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=[], null=True, size=None, verbose_name='tags')),
('version', models.IntegerField(default=1, verbose_name='version')),
('is_blocked', models.BooleanField(default=False, verbose_name='is blocked')),
('blocked_note', models.TextField(blank=True, default='', verbose_name='blocked note')),

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='issue',
name='external_reference',
field=djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='external reference'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=False, null=False), blank=True, default=None, null=True, size=None, verbose_name='external reference'),
preserve_default=True,
),
]

View File

@ -3,10 +3,9 @@ from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
import django_pgjson.fields
import django.contrib.postgres.fields
import django.utils.timezone
import django.db.models.deletion
import djorm_pgarray.fields
import taiga.projects.history.models
@ -40,7 +39,7 @@ class Migration(migrations.Migration):
name='Project',
fields=[
('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')),
('tags', djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='tags')),
('tags', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=[], null=True, size=None, verbose_name='tags')),
('name', models.CharField(max_length=250, unique=True, verbose_name='name')),
('slug', models.SlugField(max_length=250, unique=True, verbose_name='slug', blank=True)),
('description', models.TextField(verbose_name='description')),
@ -54,10 +53,10 @@ class Migration(migrations.Migration):
('is_issues_activated', models.BooleanField(default=True, verbose_name='active issues panel')),
('videoconferences', models.CharField(max_length=250, null=True, choices=[('appear-in', 'AppearIn'), ('talky', 'Talky')], verbose_name='videoconference system', blank=True)),
('videoconferences_salt', models.CharField(max_length=250, null=True, verbose_name='videoconference room salt', blank=True)),
('anon_permissions', djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('view_us', 'View user stories'), ('view_tasks', 'View tasks'), ('view_issues', 'View issues'), ('view_wiki_pages', 'View wiki pages'), ('view_wiki_links', 'View wiki links')], dbtype='text', default=[], verbose_name='anonymous permissions')),
('public_permissions', djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('view_us', 'View user stories'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('view_tasks', 'View tasks'), ('view_wiki_pages', 'View wiki pages'), ('view_wiki_links', 'View wiki links'), ('request_membership', 'Request membership'), ('add_us_to_project', 'Add user story to project'), ('add_comments_to_us', 'Add comments to user stories'), ('add_comments_to_task', 'Add comments to tasks'), ('add_issue', 'Add issues'), ('add_comments_issue', 'Add comments to issues'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link')], dbtype='text', default=[], verbose_name='user permissions')),
('anon_permissions', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('view_us', 'View user stories'), ('view_tasks', 'View tasks'), ('view_issues', 'View issues'), ('view_wiki_pages', 'View wiki pages'), ('view_wiki_links', 'View wiki links')]), blank=True, default=[], null=True, size=None, verbose_name='anonymous permissions')),
('public_permissions', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('view_us', 'View user stories'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('view_tasks', 'View tasks'), ('view_wiki_pages', 'View wiki pages'), ('view_wiki_links', 'View wiki links'), ('request_membership', 'Request membership'), ('add_us_to_project', 'Add user story to project'), ('add_comments_to_us', 'Add comments to user stories'), ('add_comments_to_task', 'Add comments to tasks'), ('add_issue', 'Add issues'), ('add_comments_issue', 'Add comments to issues'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='user permissions')),
('is_private', models.BooleanField(default=False, verbose_name='is private')),
('tags_colors', djorm_pgarray.fields.TextArrayField(dbtype='text', dimension=2, default=[], null=False, verbose_name='tags colors')),
('tags_colors', django.contrib.postgres.fields.ArrayField(base_field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=True, null=True), size=2), blank=True, default=[], null=True, size=None, verbose_name='tags colors')),
],
options={
'ordering': ['name'],

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
import django.utils.timezone
import django_pgjson.fields
import taiga.base.db.models.fields
import django.db.models.deletion
import taiga.projects.history.models
@ -100,15 +100,15 @@ class Migration(migrations.Migration):
('is_issues_activated', models.BooleanField(verbose_name='active issues panel', default=True)),
('videoconferences', models.CharField(max_length=250, null=True, choices=[('appear-in', 'AppearIn'), ('talky', 'Talky')], verbose_name='videoconference system', blank=True)),
('videoconferences_salt', models.CharField(max_length=250, null=True, verbose_name='videoconference room salt', blank=True)),
('default_options', django_pgjson.fields.JsonField(null=True, verbose_name='default options', blank=True)),
('us_statuses', django_pgjson.fields.JsonField(null=True, verbose_name='us statuses', blank=True)),
('points', django_pgjson.fields.JsonField(null=True, verbose_name='points', blank=True)),
('task_statuses', django_pgjson.fields.JsonField(null=True, verbose_name='task statuses', blank=True)),
('issue_statuses', django_pgjson.fields.JsonField(null=True, verbose_name='issue statuses', blank=True)),
('issue_types', django_pgjson.fields.JsonField(null=True, verbose_name='issue types', blank=True)),
('priorities', django_pgjson.fields.JsonField(null=True, verbose_name='priorities', blank=True)),
('severities', django_pgjson.fields.JsonField(null=True, verbose_name='severities', blank=True)),
('roles', django_pgjson.fields.JsonField(null=True, verbose_name='roles', blank=True)),
('default_options', taiga.base.db.models.fields.JSONField(null=True, verbose_name='default options', blank=True)),
('us_statuses', taiga.base.db.models.fields.JSONField(null=True, verbose_name='us statuses', blank=True)),
('points', taiga.base.db.models.fields.JSONField(null=True, verbose_name='points', blank=True)),
('task_statuses', taiga.base.db.models.fields.JSONField(null=True, verbose_name='task statuses', blank=True)),
('issue_statuses', taiga.base.db.models.fields.JSONField(null=True, verbose_name='issue statuses', blank=True)),
('issue_types', taiga.base.db.models.fields.JSONField(null=True, verbose_name='issue types', blank=True)),
('priorities', taiga.base.db.models.fields.JSONField(null=True, verbose_name='priorities', blank=True)),
('severities', taiga.base.db.models.fields.JSONField(null=True, verbose_name='severities', blank=True)),
('roles', taiga.base.db.models.fields.JSONField(null=True, verbose_name='roles', blank=True)),
],
options={
'verbose_name_plural': 'project templates',

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='project',
name='modules_config',
field=django_pgjson.fields.JsonField(blank=True, null=True, verbose_name='modules config'),
field=taiga.base.db.models.fields.JSONField(blank=True, null=True, verbose_name='modules config'),
preserve_default=True,
),
]

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
name='ProjectModulesConfig',
fields=[
('id', models.AutoField(serialize=False, auto_created=True, verbose_name='ID', primary_key=True)),
('config', django_pgjson.fields.JsonField(null=True, verbose_name='modules config', blank=True)),
('config', taiga.base.db.models.fields.JSONField(null=True, verbose_name='modules config', blank=True)),
('project', models.OneToOneField(to='projects.Project', verbose_name='project', related_name='modules_config')),
],
options={

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from django.db import models, migrations

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='project',
name='public_permissions',
field=djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], verbose_name='user permissions', dbtype='text', default=[]),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='user permissions'),
preserve_default=True,
),
]

View File

@ -2,8 +2,8 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
from django.conf import settings
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -17,7 +17,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='project',
name='public_permissions',
field=djorm_pgarray.fields.TextArrayField(default=[], dbtype='text', choices=[('view_project', 'View project'), ('star_project', 'Star project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('vote_us', 'Vote user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('vote_task', 'Vote task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('vote_issue', 'Vote issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], verbose_name='user permissions'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('star_project', 'Star project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('vote_us', 'Vote user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('vote_task', 'Vote task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('vote_issue', 'Vote issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='user permissions'),
preserve_default=True,
),
]

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='project',
name='public_permissions',
field=djorm_pgarray.fields.TextArrayField(default=[], choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], dbtype='text', verbose_name='user permissions'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='user permissions'),
preserve_default=True,
),
]

View File

@ -2,8 +2,8 @@
# Generated by Django 1.9.2 on 2016-05-19 10:58
from __future__ import unicode_literals
from django.db import migrations
import djorm_pgarray.fields
from django.db import migrations, models
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -16,6 +16,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='project',
name='public_permissions',
field=djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('comment_us', 'Comment user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('comment_task', 'Comment task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('comment_issue', 'Comment issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('comment_wiki_page', 'Comment wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], dbtype='text', default=[], verbose_name='user permissions'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('comment_us', 'Comment user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('comment_task', 'Comment task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('comment_issue', 'Comment issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('comment_wiki_page', 'Comment wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='user permissions'),
),
]

View File

@ -2,10 +2,10 @@
# Generated by Django 1.9.2 on 2016-06-29 14:43
from __future__ import unicode_literals
import django.contrib.postgres.fields
import taiga.base.db.models.fields
from django.db import migrations, models
import django.db.models.deletion
import django_pgjson.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -71,7 +71,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='projecttemplate',
name='epic_statuses',
field=django_pgjson.fields.JsonField(blank=True, null=True, verbose_name='epic statuses'),
field=taiga.base.db.models.fields.JSONField(blank=True, null=True, verbose_name='epic statuses'),
),
migrations.AddField(
model_name='projecttemplate',

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:34
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('projects', '0054_auto_20160928_0540'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "projects_projectmodulesconfig"
ALTER COLUMN "config" TYPE jsonb USING to_json("config"::text)::jsonb;
""",
reverse_sql=migrations.RunSQL.noop
),
migrations.RunSQL(
"""
ALTER TABLE "projects_projecttemplate"
ALTER COLUMN "roles" TYPE jsonb USING to_json("roles"::text)::jsonb,
ALTER COLUMN "default_options" TYPE jsonb USING to_json("default_options"::text)::jsonb,
ALTER COLUMN "epic_statuses" TYPE jsonb USING to_json("epic_statuses"::text)::jsonb,
ALTER COLUMN "us_statuses" TYPE jsonb USING to_json("us_statuses"::text)::jsonb,
ALTER COLUMN "points" TYPE jsonb USING to_json("points"::text)::jsonb,
ALTER COLUMN "task_statuses" TYPE jsonb USING to_json("task_statuses"::text)::jsonb,
ALTER COLUMN "issue_statuses" TYPE jsonb USING to_json("issue_statuses"::text)::jsonb,
ALTER COLUMN "issue_types" TYPE jsonb USING to_json("issue_types"::text)::jsonb,
ALTER COLUMN "priorities" TYPE jsonb USING to_json("priorities"::text)::jsonb,
ALTER COLUMN "severities" TYPE jsonb USING to_json("severities"::text)::jsonb;
""",
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -29,7 +29,7 @@ from django.utils.functional import cached_property
from django_pglocks import advisory_lock
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from taiga.base.utils.time import timestamp_ms
from taiga.projects.tagging.models import TaggedMixin
@ -491,7 +491,7 @@ class Project(ProjectDefaults, TaggedMixin, TagsColorsdMixin, models.Model):
class ProjectModulesConfig(models.Model):
project = models.OneToOneField("Project", null=False, blank=False,
related_name="modules_config", verbose_name=_("project"))
config = JsonField(null=True, blank=True, verbose_name=_("modules config"))
config = JSONField(null=True, blank=True, verbose_name=_("modules config"))
class Meta:
verbose_name = "project modules config"
@ -751,16 +751,16 @@ class ProjectTemplate(models.Model):
videoconferences_extra_data = models.CharField(max_length=250, null=True, blank=True,
verbose_name=_("videoconference extra data"))
default_options = JsonField(null=True, blank=True, verbose_name=_("default options"))
epic_statuses = JsonField(null=True, blank=True, verbose_name=_("epic statuses"))
us_statuses = JsonField(null=True, blank=True, verbose_name=_("us statuses"))
points = JsonField(null=True, blank=True, verbose_name=_("points"))
task_statuses = JsonField(null=True, blank=True, verbose_name=_("task statuses"))
issue_statuses = JsonField(null=True, blank=True, verbose_name=_("issue statuses"))
issue_types = JsonField(null=True, blank=True, verbose_name=_("issue types"))
priorities = JsonField(null=True, blank=True, verbose_name=_("priorities"))
severities = JsonField(null=True, blank=True, verbose_name=_("severities"))
roles = JsonField(null=True, blank=True, verbose_name=_("roles"))
default_options = JSONField(null=True, blank=True, verbose_name=_("default options"))
epic_statuses = JSONField(null=True, blank=True, verbose_name=_("epic statuses"))
us_statuses = JSONField(null=True, blank=True, verbose_name=_("us statuses"))
points = JSONField(null=True, blank=True, verbose_name=_("points"))
task_statuses = JSONField(null=True, blank=True, verbose_name=_("task statuses"))
issue_statuses = JSONField(null=True, blank=True, verbose_name=_("issue statuses"))
issue_types = JSONField(null=True, blank=True, verbose_name=_("issue types"))
priorities = JSONField(null=True, blank=True, verbose_name=_("priorities"))
severities = JSONField(null=True, blank=True, verbose_name=_("severities"))
roles = JSONField(null=True, blank=True, verbose_name=_("roles"))
_importing = None
class Meta:

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
from django.conf import settings
import django.utils.timezone
@ -21,7 +21,7 @@ class Migration(migrations.Migration):
name='Task',
fields=[
('id', models.AutoField(serialize=False, verbose_name='ID', primary_key=True, auto_created=True)),
('tags', djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='tags')),
('tags', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=[], null=True, size=None, verbose_name='tags')),
('version', models.IntegerField(default=1, verbose_name='version')),
('is_blocked', models.BooleanField(verbose_name='is blocked', default=False)),
('blocked_note', models.TextField(blank=True, verbose_name='blocked note', default='')),

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='task',
name='external_reference',
field=djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='external reference'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=False, null=False), blank=True, default=None, null=True, size=None, verbose_name='external reference'),
preserve_default=True,
),
]

View File

@ -4,7 +4,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
import django.utils.timezone
import djorm_pgarray.fields
import django.contrib.postgres.fields
import django.db.models.deletion
@ -38,7 +38,7 @@ class Migration(migrations.Migration):
name='UserStory',
fields=[
('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')),
('tags', djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='tags')),
('tags', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=[], null=True, size=None, verbose_name='tags')),
('version', models.IntegerField(default=1, verbose_name='version')),
('is_blocked', models.BooleanField(default=False, verbose_name='is blocked')),
('blocked_note', models.TextField(default='', blank=True, verbose_name='blocked note')),

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='userstory',
name='external_reference',
field=djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='external reference'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(blank=False, null=False), blank=True, default=None, null=True, size=None, verbose_name='external reference'),
preserve_default=True,
),
]

View File

@ -22,7 +22,7 @@ from django.utils.translation import ugettext as _
from taiga.base.api import serializers
from taiga.base.api import validators
from taiga.base.exceptions import ValidationError
from taiga.base.fields import JsonField
from taiga.base.fields import JSONField
from taiga.base.fields import PgArrayField
from taiga.users.models import Role
@ -222,15 +222,15 @@ class ProjectValidator(validators.ModelValidator):
######################################################
class ProjectTemplateValidator(validators.ModelValidator):
default_options = JsonField(required=False, label=_("Default options"))
us_statuses = JsonField(required=False, label=_("User story's statuses"))
points = JsonField(required=False, label=_("Points"))
task_statuses = JsonField(required=False, label=_("Task's statuses"))
issue_statuses = JsonField(required=False, label=_("Issue's statuses"))
issue_types = JsonField(required=False, label=_("Issue's types"))
priorities = JsonField(required=False, label=_("Priorities"))
severities = JsonField(required=False, label=_("Severities"))
roles = JsonField(required=False, label=_("Roles"))
default_options = JSONField(required=False, label=_("Default options"))
us_statuses = JSONField(required=False, label=_("User story's statuses"))
points = JSONField(required=False, label=_("Points"))
task_statuses = JSONField(required=False, label=_("Task's statuses"))
issue_statuses = JSONField(required=False, label=_("Issue's statuses"))
issue_types = JSONField(required=False, label=_("Issue's types"))
priorities = JSONField(required=False, label=_("Priorities"))
severities = JSONField(required=False, label=_("Severities"))
roles = JSONField(required=False, label=_("Roles"))
class Meta:
model = models.ProjectTemplate

View File

@ -46,7 +46,7 @@ class BulkCreator(object):
def create_element(self, element):
self.timeline_objects.append(element)
if len(self.timeline_objects) > 1000:
if len(self.timeline_objects) > 999:
self.flush()
def flush(self):
@ -140,31 +140,28 @@ def generate_timeline(initial_date, final_date, project_id):
class Command(BaseCommand):
help = 'Regenerate project timeline'
option_list = BaseCommand.option_list + (
make_option('--purge',
def add_arguments(self, parser):
parser.add_argument('--purge',
action='store_true',
dest='purge',
default=False,
help='Purge existing timelines'),
) + (
make_option('--initial_date',
help='Purge existing timelines')
parser.add_argument('--initial_date',
action='store',
dest='initial_date',
default=None,
help='Initial date for timeline generation'),
) + (
make_option('--final_date',
help='Initial date for timeline generation')
parser.add_argument('--final_date',
action='store',
dest='final_date',
default=None,
help='Final date for timeline generation'),
) + (
make_option('--project',
help='Final date for timeline generation')
parser.add_argument('--project',
action='store',
dest='project',
default=None,
help='Selected project id for timeline generation'),
)
help='Selected project id for timeline generation')
@override_settings(DEBUG=False)
def handle(self, *args, **options):

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
import django.utils.timezone
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
('object_id', models.PositiveIntegerField()),
('namespace', models.SlugField(default='default')),
('event_type', models.SlugField()),
('data', django_pgjson.fields.JsonField()),
('data', taiga.base.db.models.fields.JSONField()),
('created', models.DateTimeField(default=django.utils.timezone.now)),
('content_type', models.ForeignKey(to='contenttypes.ContentType')),
],

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
from django.utils import timezone
class Migration(migrations.Migration):
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
('namespace', models.SlugField(default='default')),
('event_type', models.SlugField()),
('project', models.ForeignKey(to='projects.Project')),
('data', django_pgjson.fields.JsonField()),
('data', taiga.base.db.models.fields.JSONField()),
('data_content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='data_timelines')),
('created', models.DateTimeField(default=timezone.now)),
('content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='content_type_timelines')),

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:35
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('timeline', '0005_auto_20160706_0723'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="timeline_timeline",
column_name="data",
),
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -17,7 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.db import models
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from django.utils import timezone
from django.contrib.contenttypes.models import ContentType
@ -33,7 +33,7 @@ class Timeline(models.Model):
namespace = models.CharField(max_length=250, default="default", db_index=True)
event_type = models.CharField(max_length=250, db_index=True)
project = models.ForeignKey(Project, null=True)
data = JsonField()
data = JSONField()
data_content_type = models.ForeignKey(ContentType, related_name="data_timelines")
created = models.DateTimeField(default=timezone.now, db_index=True)

View File

@ -17,7 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.conf import settings
from django.conf.urls import patterns, include, url
from django.conf.urls import include, url
from django.contrib import admin
from .routers import router

View File

@ -2,7 +2,6 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.utils.timezone
import re
import django.core.validators

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -18,7 +18,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
('name', models.CharField(verbose_name='name', max_length=200)),
('slug', models.SlugField(verbose_name='slug', max_length=250, blank=True)),
('permissions', djorm_pgarray.fields.TextArrayField(dbtype='text', verbose_name='permissions', choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], default=[])),
('permissions', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('vote_issues', 'Vote issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='permissions')),
('order', models.IntegerField(verbose_name='order', default=10)),
('computable', models.BooleanField(default=True)),
],

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
import django_pgjson.fields
import taiga.base.db.models.fields
def migrate_github_id(apps, schema_editor):
@ -27,7 +27,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)),
('key', models.SlugField()),
('value', models.CharField(max_length=300)),
('extra', django_pgjson.fields.JsonField()),
('extra', taiga.base.db.models.fields.JSONField()),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
options={

View File

@ -2,8 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +14,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='role',
name='permissions',
field=djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('star_project', 'Star project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('vote_us', 'Vote user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('vote_task', 'Vote task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('vote_issue', 'Vote issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], verbose_name='permissions', default=[], dbtype='text'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('star_project', 'Star project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('vote_us', 'Vote user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('vote_task', 'Vote task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('vote_issue', 'Vote issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='permissions'),
preserve_default=True,
),
]

View File

@ -2,8 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import djorm_pgarray.fields
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -15,7 +14,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='role',
name='permissions',
field=djorm_pgarray.fields.TextArrayField(default=[], choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], dbtype='text', verbose_name='permissions'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='permissions'),
preserve_default=True,
),
]

View File

@ -2,9 +2,8 @@
# Generated by Django 1.9.2 on 2016-05-19 10:58
from __future__ import unicode_literals
from django.db import migrations
import djorm_pgarray.fields
from django.db import models, migrations
import django.contrib.postgres.fields
class Migration(migrations.Migration):
@ -16,6 +15,6 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='role',
name='permissions',
field=djorm_pgarray.fields.TextArrayField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('comment_us', 'Comment user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('comment_task', 'Comment task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('comment_issue', 'Comment issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('comment_wiki_page', 'Comment wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')], dbtype='text', default=[], verbose_name='permissions'),
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(choices=[('view_project', 'View project'), ('view_milestones', 'View milestones'), ('add_milestone', 'Add milestone'), ('modify_milestone', 'Modify milestone'), ('delete_milestone', 'Delete milestone'), ('view_us', 'View user story'), ('add_us', 'Add user story'), ('modify_us', 'Modify user story'), ('comment_us', 'Comment user story'), ('delete_us', 'Delete user story'), ('view_tasks', 'View tasks'), ('add_task', 'Add task'), ('modify_task', 'Modify task'), ('comment_task', 'Comment task'), ('delete_task', 'Delete task'), ('view_issues', 'View issues'), ('add_issue', 'Add issue'), ('modify_issue', 'Modify issue'), ('comment_issue', 'Comment issue'), ('delete_issue', 'Delete issue'), ('view_wiki_pages', 'View wiki pages'), ('add_wiki_page', 'Add wiki page'), ('modify_wiki_page', 'Modify wiki page'), ('comment_wiki_page', 'Comment wiki page'), ('delete_wiki_page', 'Delete wiki page'), ('view_wiki_links', 'View wiki links'), ('add_wiki_link', 'Add wiki link'), ('modify_wiki_link', 'Modify wiki link'), ('delete_wiki_link', 'Delete wiki link')]), blank=True, default=[], null=True, size=None, verbose_name='permissions'),
),
]

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:35
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('users', '0022_auto_20160629_1443'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="users_authdata",
column_name="extra",
),
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -34,7 +34,7 @@ from django.dispatch import receiver
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from django_pglocks import advisory_lock
from taiga.auth.tokens import get_token_for_user
@ -323,7 +323,7 @@ class AuthData(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="auth_data")
key = models.SlugField(max_length=50)
value = models.CharField(max_length=300)
extra = JsonField()
extra = JSONField()
class Meta:
unique_together = ["key", "value"]

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
from django.conf import settings
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
('created_date', models.DateTimeField(auto_now_add=True, verbose_name='created date')),
('modified_date', models.DateTimeField(verbose_name='modified date', auto_now=True)),
('key', models.CharField(max_length=255, verbose_name='key')),
('value', django_pgjson.fields.JsonField(verbose_name='value', blank=True, default=None, null=True)),
('value', taiga.base.db.models.fields.JSONField(verbose_name='value', blank=True, default=None, null=True)),
('owner', models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='owner', related_name='storage_entries')),
],
options={

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
from django.db import models, migrations

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:35
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('userstorage', '0002_fix_json_field_not_null'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "{table_name}"
ALTER COLUMN "{column_name}"
TYPE jsonb
USING to_json("{column_name}"::text)::jsonb;
""".format(
table_name="userstorage_storageentry",
column_name="value",
),
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -19,7 +19,7 @@
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
class StorageEntry(models.Model):
@ -30,7 +30,7 @@ class StorageEntry(models.Model):
modified_date = models.DateTimeField(auto_now=True, null=False, blank=False,
verbose_name=_("modified date"))
key = models.CharField(max_length=255, null=False, blank=False, verbose_name=_("key"))
value = JsonField(blank=True, default=None, null=True, verbose_name=_("value"))
value = JSONField(blank=True, default=None, null=True, verbose_name=_("value"))
class Meta:
verbose_name = "storage entry"

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -30,7 +30,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)),
('url', models.URLField(verbose_name='URL')),
('status', models.IntegerField(verbose_name='Status code')),
('request_data', django_pgjson.fields.JsonField(verbose_name='Request data')),
('request_data', taiga.base.db.models.fields.JSONField(verbose_name='Request data')),
('response_data', models.TextField(verbose_name='Response data')),
('webhook', models.ForeignKey(related_name='logs', to='webhooks.Webhook')),
],

View File

@ -3,7 +3,9 @@ from __future__ import unicode_literals
from django.db import models, migrations
import datetime
import django_pgjson.fields
import taiga.base.db.models.fields
from django.utils import timezone
class Migration(migrations.Migration):
@ -16,7 +18,9 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='webhooklog',
name='created',
field=models.DateTimeField(default=datetime.datetime(2015, 1, 22, 10, 21, 17, 188643), auto_now_add=True),
field=models.DateTimeField(
default=datetime.datetime(2015, 1, 22, 10, 21, 17, 188643, timezone.get_default_timezone()),
auto_now_add=True),
preserve_default=False,
),
migrations.AddField(
@ -28,13 +32,13 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='webhooklog',
name='request_headers',
field=django_pgjson.fields.JsonField(default={}, verbose_name='Request headers'),
field=taiga.base.db.models.fields.JSONField(default={}, verbose_name='Request headers'),
preserve_default=True,
),
migrations.AddField(
model_name='webhooklog',
name='response_headers',
field=django_pgjson.fields.JsonField(default={}, verbose_name='Response headers'),
field=taiga.base.db.models.fields.JSONField(default={}, verbose_name='Response headers'),
preserve_default=True,
),
]

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
from django.db import models, migrations
import django_pgjson.fields
import taiga.base.db.models.fields
class Migration(migrations.Migration):
@ -21,13 +21,13 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='webhooklog',
name='request_data',
field=django_pgjson.fields.JsonField(verbose_name='request data'),
field=taiga.base.db.models.fields.JSONField(verbose_name='request data'),
preserve_default=True,
),
migrations.AlterField(
model_name='webhooklog',
name='request_headers',
field=django_pgjson.fields.JsonField(verbose_name='request headers', default={}),
field=taiga.base.db.models.fields.JSONField(verbose_name='request headers', default={}),
preserve_default=True,
),
migrations.AlterField(
@ -39,7 +39,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='webhooklog',
name='response_headers',
field=django_pgjson.fields.JsonField(verbose_name='response headers', default={}),
field=taiga.base.db.models.fields.JSONField(verbose_name='response headers', default={}),
preserve_default=True,
),
migrations.AlterField(

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.2 on 2016-10-26 11:35
from __future__ import unicode_literals
from django.db import migrations
from django.contrib.postgres.fields import JSONField
class Migration(migrations.Migration):
dependencies = [
('webhooks', '0005_auto_20150505_1639'),
]
operations = [
migrations.RunSQL(
"""
ALTER TABLE "webhooks_webhooklog"
ALTER COLUMN "request_headers" TYPE jsonb USING to_json("request_headers"::text)::jsonb,
ALTER COLUMN "request_data" TYPE jsonb USING to_json("request_data"::text)::jsonb,
ALTER COLUMN "response_headers" TYPE jsonb USING to_json("response_headers"::text)::jsonb;
""",
reverse_sql=migrations.RunSQL.noop
),
]

View File

@ -19,7 +19,7 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django_pgjson.fields import JsonField
from taiga.base.db.models.fields import JSONField
class Webhook(models.Model):
@ -39,10 +39,10 @@ class WebhookLog(models.Model):
related_name="logs")
url = models.URLField(null=False, blank=False, verbose_name=_("URL"))
status = models.IntegerField(null=False, blank=False, verbose_name=_("status code"))
request_data = JsonField(null=False, blank=False, verbose_name=_("request data"))
request_headers = JsonField(null=False, blank=False, verbose_name=_("request headers"), default={})
request_data = JSONField(null=False, blank=False, verbose_name=_("request data"))
request_headers = JSONField(null=False, blank=False, verbose_name=_("request headers"), default={})
response_data = models.TextField(null=False, blank=False, verbose_name=_("response data"))
response_headers = JsonField(null=False, blank=False, verbose_name=_("response headers"), default={})
response_headers = JSONField(null=False, blank=False, verbose_name=_("response headers"), default={})
duration = models.FloatField(null=False, blank=False, verbose_name=_("duration"), default=0)
created = models.DateTimeField(auto_now_add=True)

View File

@ -163,12 +163,18 @@ def test_project_update(client, data):
]
project_data = ProjectSerializer(data.private_project2).data
# Because in serializer is a dict anin model is a list of lists
project_data["tags_colors"] = list(map(list, project_data["tags_colors"].items()))
project_data["is_private"] = False
results = helper_test_http_method(client, 'put', url, json.dumps(project_data), users)
assert results == [401, 403, 403, 200]
project_data = ProjectSerializer(data.blocked_project).data
# Because in serializer is a dict anin model is a list of lists
project_data["tags_colors"] = list(map(list, project_data["tags_colors"].items()))
project_data["is_private"] = False
results = helper_test_http_method(client, 'put', blocked_url, json.dumps(project_data), users)
assert results == [401, 403, 403, 451]

View File

@ -18,11 +18,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
import datetime
from unittest.mock import patch
from django.core.urlresolvers import reverse
from django.utils import timezone
from .. import factories as f
from taiga.base.utils import json
@ -286,7 +287,7 @@ def test_get_comment_versions(client):
key=key,
diff={},
user={"pk": project.owner.id},
edit_comment_date=datetime.datetime.now(),
edit_comment_date=timezone.now(),
comment_versions = [{
"comment_html": "<p>test</p>",
"date": "2016-05-09T09:34:27.221Z",

View File

@ -25,10 +25,13 @@ import datetime
import hashlib
import binascii
import struct
import pytz
from unittest.mock import MagicMock, patch
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.apps import apps
from .. import factories as f
@ -931,7 +934,7 @@ def test_retrieve_notify_policies_by_anonymous_user(client):
def test_ms_thread_id():
id = '<test/message@localhost>'
now = datetime.datetime.now()
now = timezone.now()
index = services.make_ms_thread_index(id, now)
parsed = parse_ms_thread_index(index)
@ -953,7 +956,7 @@ def parse_ms_thread_index(index):
# guid = '%08X-%04X-%04X-%04X-%12X' % (guid[0], guid[1], guid[2], (guid[3] >> 48) & 0xFFFF, guid[3] & 0xFFFFFFFFFFFF)
f = struct.unpack('>Q', s[:6] + b'\0\0')[0]
ts = [datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds=f//10)]
ts = [datetime.datetime(1601, 1, 1, tzinfo=pytz.utc) + datetime.timedelta(microseconds=f//10)]
# for the 5 byte appendixes that we won't use
for n in range(22, len(s), 5):

View File

@ -67,6 +67,8 @@ def test_sequences(seq):
@pytest.mark.django_db
def test_unique_reference_per_project(seq, refmodels):
refmodels.Reference.objects.all().delete()
project = factories.ProjectFactory.create()
seqname = refmodels.make_sequence_name(project)
@ -82,6 +84,8 @@ def test_unique_reference_per_project(seq, refmodels):
@pytest.mark.django_db
def test_regenerate_us_reference_on_project_change(seq, refmodels):
refmodels.Reference.objects.all().delete()
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
@ -104,6 +108,8 @@ def test_regenerate_us_reference_on_project_change(seq, refmodels):
@pytest.mark.django_db
def test_regenerate_task_reference_on_project_change(seq, refmodels):
refmodels.Reference.objects.all().delete()
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
@ -126,6 +132,8 @@ def test_regenerate_task_reference_on_project_change(seq, refmodels):
@pytest.mark.django_db
def test_regenerate_issue_reference_on_project_change(seq, refmodels):
refmodels.Reference.objects.all().delete()
project1 = factories.ProjectFactory.create()
seqname1 = refmodels.make_sequence_name(project1)
project2 = factories.ProjectFactory.create()
@ -149,6 +157,8 @@ def test_regenerate_issue_reference_on_project_change(seq, refmodels):
@pytest.mark.django_db
def test_params_validation_in_api_request(client, refmodels):
refmodels.Reference.objects.all().delete()
user = factories.UserFactory.create()
project = factories.ProjectFactory.create(owner=user)
seqname1 = refmodels.make_sequence_name(project)

View File

@ -55,27 +55,3 @@ def test_destroy_role_and_reassign_members(client):
qs = Membership.objects.filter(project=project, role_id=role1.pk)
assert qs.count() == 2
def test_destroy_role_and_reassign_members_with_deleted_project(client):
"""
Regression test, that fixes some 500 errors on production
"""
user1 = f.UserFactory.create()
user2 = f.UserFactory.create()
project = f.ProjectFactory.create(owner=user1)
role1 = f.RoleFactory.create(project=project)
role2 = f.RoleFactory.create(project=project)
f.MembershipFactory.create(project=project, user=user1, role=role1)
f.MembershipFactory.create(project=project, user=user2, role=role2)
Project.objects.filter(pk=project.id).delete()
url = reverse("roles-detail", args=[role2.pk]) + "?moveTo={}".format(role1.pk)
client.login(user1)
response = client.delete(url)
# FIXME: really should return 403? I think it should be 404
assert response.status_code == 403, response.content

View File

@ -35,7 +35,7 @@ def test_add_to_object_timeline():
user1 = factories.UserFactory()
task = factories.TaskFactory()
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task, "test", task.created_date)
@ -54,7 +54,7 @@ def test_get_timeline():
task3= factories.TaskFactory()
task4= factories.TaskFactory()
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
@ -73,7 +73,7 @@ def test_filter_timeline_no_privileges():
user2 = factories.UserFactory()
task1= factories.TaskFactory()
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")
timeline = service.filter_timeline_for_user(timeline, user2)
@ -88,7 +88,7 @@ def test_filter_timeline_public_project():
task1= factories.TaskFactory()
task2= factories.TaskFactory.create(project=project)
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")
@ -104,7 +104,7 @@ def test_filter_timeline_private_project_anon_permissions():
task1= factories.TaskFactory()
task2= factories.TaskFactory.create(project=project)
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")
@ -123,7 +123,7 @@ def test_filter_timeline_private_project_member_permissions():
task1= factories.TaskFactory()
task2= factories.TaskFactory.create(project=project)
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")
@ -140,7 +140,7 @@ def test_filter_timeline_private_project_member_admin():
task1= factories.TaskFactory()
task2= factories.TaskFactory.create(project=project)
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")
@ -157,7 +157,7 @@ def test_filter_timeline_private_project_member_superuser():
task1= factories.TaskFactory()
task2= factories.TaskFactory.create(project=project)
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: str(id(x)))
service.register_timeline_implementation("tasks.task", "test", lambda x, extra_data=None: id(x))
service._add_to_object_timeline(user1, task1, "test", task1.created_date)
service._add_to_object_timeline(user1, task2, "test", task2.created_date)
timeline = Timeline.objects.exclude(event_type="users.user.create")

View File

@ -27,13 +27,15 @@ from taiga.projects.history.choices import HistoryType
from taiga.projects.models import Project
from django.core.urlresolvers import reverse
from django.utils import timezone
pytestmark = pytest.mark.django_db
def test_project_totals_updated_on_activity(client):
project = f.create_project()
totals_updated_datetime = project.totals_updated_datetime
now = datetime.datetime.now()
now = timezone.now()
assert project.total_activity == 0
totals_updated_datetime = project.totals_updated_datetime
@ -120,10 +122,10 @@ def test_project_totals_updated_on_like(client):
f.MembershipFactory.create(project=project, user=project.owner, is_admin=True)
totals_updated_datetime = project.totals_updated_datetime
now = datetime.datetime.now()
now = timezone.now()
assert project.total_activity == 0
now = datetime.datetime.now()
now = timezone.now()
totals_updated_datetime = project.totals_updated_datetime
us = f.UserStoryFactory.create(project=project, owner=project.owner)

View File

@ -27,7 +27,7 @@ pytestmark = pytest.mark.django_db
def test_export_issue_finish_date(client):
issue = f.IssueFactory.create(finished_date="2014-10-22")
issue = f.IssueFactory.create(finished_date="2014-10-22T00:00:00+0000")
output = io.BytesIO()
render_project(issue.project, output)
project_data = json.loads(output.getvalue())
@ -36,7 +36,7 @@ def test_export_issue_finish_date(client):
def test_export_user_story_finish_date(client):
user_story = f.UserStoryFactory.create(finish_date="2014-10-22")
user_story = f.UserStoryFactory.create(finish_date="2014-10-22T00:00:00+0000")
output = io.BytesIO()
render_project(user_story.project, output)
project_data = json.loads(output.getvalue())

View File

@ -23,6 +23,7 @@ from taiga.mdrender.extensions import emojify
from taiga.mdrender.service import render, cache_by_sha, get_diff_of_htmls, render_and_extract
from datetime import datetime
import pytz
dummy_project = MagicMock()
dummy_project.id = 1
@ -206,19 +207,21 @@ def test_render_relative_image():
def test_render_triple_quote_code():
expected_result = "<div class=\"codehilite\"><pre><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s\">\"test\"</span><span class=\"p\">)</span>\n</pre></div>"
expected_result = '<div class="codehilite"><pre><span></span><span class="k">print</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>\n</pre></div>'
assert render(dummy_project, "```python\nprint(\"test\")\n```") == expected_result
def test_render_triple_quote_and_lang_code():
expected_result = "<div class=\"codehilite\"><pre><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s\">\"test\"</span><span class=\"p\">)</span>\n</pre></div>"
expected_result = '<div class="codehilite"><pre><span></span><span class="k">print</span><span class="p">(</span><span class="s2">"test"</span><span class="p">)</span>\n</pre></div>'
assert render(dummy_project, "```python\nprint(\"test\")\n```") == expected_result
def test_cache_by_sha():
@cache_by_sha
def test_cache(project, text):
return datetime.now()
return datetime.now(pytz.utc)
result1 = test_cache(dummy_project, "test")
result2 = test_cache(dummy_project, "test2")