<commit_before>#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import logging
from datetime import datetime

import pymongo
from pymongo.errors import DuplicateKeyError
from pylons import tmpl_context as c, app_globals as g

from ming import schema
from ming.orm.base import session
from ming.orm.property import (FieldProperty, RelationProperty,
                               ForeignIdProperty)
from ming.utils import LazyProperty

from allura.lib import helpers as h
from allura.lib import security
from allura.lib.security import require_access, has_access
from allura.lib import utils
from allura.model.notification import Notification, Mailbox
from allura.model.auth import ProjectRole
from .artifact import Artifact, ArtifactReference, VersionedArtifact, Snapshot, Message, Feed
from .attachments import BaseAttachment
from .auth import User
from .timeline import ActivityObject

log = logging.getLogger(__name__)


class Discussion(Artifact, ActivityObject):
    class __mongometa__:
        name = 'discussion'
    type_s = 'Discussion'

    parent_id = FieldProperty(schema.Deprecated)
    shortname = FieldProperty(str)
    name = FieldProperty(str)
    description = FieldProperty(str, if_missing='')
    num_topics = FieldProperty(int, if_missing=0)
    num_posts = FieldProperty(int, if_missing=0)
    subscriptions = FieldProperty({str: bool})

    threads = RelationProperty('Thread')
    posts = RelationProperty('Post')

    def __json__(self):
        return dict(
            _id=str(self._id),
            shortname=self.shortname,
            name=self.name,
            description=self.description,
            threads=[dict(_id=t._id, subject=t.subject)
                     for t in self.threads])

    @property
    def activity_name(self):
        return 'discussion %s' % self.name

    @classmethod
    def thread_class(cls):
        return cls.threads.related

    @classmethod
    def post_class(cls):
        return cls.posts.related

    @classmethod
    def attachment_class(cls):
        return DiscussionAttachment

    def update_stats(self):
        self.num_topics = self.thread_class().query.find(
            dict(discussion_id=self._id)).count()
        self.num_posts = self.post_class().query.find(
            dict(discussion_id=self._id, status='ok')).count()

    @LazyProperty
    def last_post(self):
        q = self.post_class().query.find(dict(
                discussion_id=self._id))\
            .sort('timestamp', pymongo.DESCENDING)\
            .limit(1)\
            .hint([('discussion_id', pymongo.ASCENDING)])
            # hint is to try to force the index to be used, since mongo wouldn't select it sometimes
            # https://groups.google.com/forum/#!topic/mongodb-user/0TEqPfXxQU8
        return q.first()

    def url(self):
        return self.app.url + '_discuss/'

    def shorthand_id(self):
        return self.shortname

    def index(self):
        result = Artifact.index(self)<commit_msg>[#6347] update index hint to match the index change<commit_after>#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import logging
from datetime import datetime

import pymongo
from pymongo.errors import DuplicateKeyError
from pylons import tmpl_context as c, app_globals as g

from ming import schema
from ming.orm.base import session
from ming.orm.property import (FieldProperty, RelationProperty,
                               ForeignIdProperty)
from ming.utils import LazyProperty

from allura.lib import helpers as h
from allura.lib import security
from allura.lib.security import require_access, has_access
from allura.lib import utils
from allura.model.notification import Notification, Mailbox
from allura.model.auth import ProjectRole
from .artifact import Artifact, ArtifactReference, VersionedArtifact, Snapshot, Message, Feed
from .attachments import BaseAttachment
from .auth import User
from .timeline import ActivityObject

log = logging.getLogger(__name__)


class Discussion(Artifact, ActivityObject):
    class __mongometa__:
        name = 'discussion'
    type_s = 'Discussion'

    parent_id = FieldProperty(schema.Deprecated)
    shortname = FieldProperty(str)
    name = FieldProperty(str)
    description = FieldProperty(str, if_missing='')
    num_topics = FieldProperty(int, if_missing=0)
    num_posts = FieldProperty(int, if_missing=0)
    subscriptions = FieldProperty({str: bool})

    threads = RelationProperty('Thread')
    posts = RelationProperty('Post')

    def __json__(self):
        return dict(
            _id=str(self._id),
            shortname=self.shortname,
            name=self.name,
            description=self.description,
            threads=[dict(_id=t._id, subject=t.subject)
                     for t in self.threads])

    @property
    def activity_name(self):
        return 'discussion %s' % self.name

    @classmethod
    def thread_class(cls):
        return cls.threads.related

    @classmethod
    def post_class(cls):
        return cls.posts.related

    @classmethod
    def attachment_class(cls):
        return DiscussionAttachment

    def update_stats(self):
        self.num_topics = self.thread_class().query.find(
            dict(discussion_id=self._id)).count()
        self.num_posts = self.post_class().query.find(
            dict(discussion_id=self._id, status='ok')).count()

    @LazyProperty
    def last_post(self):
        q = self.post_class().query.find(dict(
                discussion_id=self._id))\
            .sort('timestamp', pymongo.DESCENDING)\
            .limit(1)\
            .hint([('discussion_id', pymongo.ASCENDING), ('status', pymongo.ASCENDING)])
            # hint is to try to force the index to be used, since mongo wouldn't select it sometimes
            # https://groups.google.com/forum/#!topic/mongodb-user/0TEqPfXxQU8
        return q.first()

    def url(self):
        return self.app.url + '_discuss/'

    def shorthand_id(self):
        return self.shortname

    def index(self):
        result = Artifact.index(self)
{'fraction_non_alphanumeric': 0.08205932314125179, 'fraction_numerical': 0.00287468966418398, 'mean_word_length': 2.9130879345603273, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1529730', 'n_tokens_mistral': 2118, 'n_tokens_neox': 2051, 'n_words': 655}