Пример #1
0
    def search(cls, phrase, limit=10, keys_only=False):
        """Queries search indices for phrases using a merge-join.
        
        Use of this class method lets you easily restrict searches to a kind
        and retrieve entities or keys.

        Args:
            phrase: Search phrase (string)
            limit: Number of entities or keys to return.
            keys_only: If True, return only keys with title of parent entity.
        
        Returns:
            A list.  If keys_only is True, the list holds (key, title) tuples.
            If keys_only is False, the list holds Model instances.
        """
        key_list = Searchable.full_text_search(
            phrase, limit=limit, kind=cls.kind(), stemming=cls.INDEX_STEMMING, multi_word_literal=cls.INDEX_MULTI_WORD
        )
        if keys_only:
            logging.debug("key_list: %s", key_list)
            return key_list
        else:
            # Andrew changed this to do a mass get and some cleanup.
            ret = IP4DB.get([resultKey for stemKey, resultKey, resultTitle in key_list])
            badStems = [stemKey for result, (stemKey, resultKey, resultTitle) in zip(ret, key_list) if result is None]
            if badStems:
                from google.appengine.ext import deferred

                deferred.defer(db.delete, badStems[:500])  # Google only allows 500 in a delete.
            ret = [r for r in ret if r is not None]
            return ret
Пример #2
0
 def post(self):
     key_str = self.request.get("key")
     only_index_str = self.request.get("only_index")
     if key_str:
         key = db.Key(key_str)
         entity = IP4DB.get(key)
         if not entity:
             self.response.set_status(200)  # Clear task because it's a bad key
         else:
             only_index = only_index_str.split(",") if only_index_str else None
             entity.index()
Пример #3
0
 def post(self):
     key_str = self.request.get('key')
     only_index_str = self.request.get('only_index')
     if key_str:
         key = db.Key(key_str)
         entity = IP4DB.get(key)
         if not entity:
             self.response.set_status(
                 200)  # Clear task because it's a bad key
         else:
             only_index = only_index_str.split(
                 ',') if only_index_str else None
             entity.index()
Пример #4
0
 def indexed_title_changed(self):
     """Renames index entities for this model to match new title."""
     klass = StemmedIndex if self.INDEX_STEMMING else LiteralIndex
     query = klass.all(keys_only=True).ancestor(self.key())
     old_index_keys = query.fetch(1000)
     if not hasattr(self, "INDEX_TITLE_FROM_PROP"):
         raise IndexTitleError("Must declare a property name via INDEX_TITLE_FROM_PROP")
     new_keys = []
     for old_key in old_index_keys:
         old_index = IP4DB.get(old_key)
         index_num = SearchIndex.get_index_num(old_key.name())
         index_key = klass.put_index(parent=self, index_num=index_num, phrases=old_index.phrases)
         new_keys.append(index_key)
     delete_keys = filter(lambda key: key not in new_keys, old_index_keys)
     db.delete(delete_keys)
Пример #5
0
 def indexed_title_changed(self):
     """Renames index entities for this model to match new title."""
     klass = StemmedIndex if self.INDEX_STEMMING else LiteralIndex
     query = klass.all(keys_only=True).ancestor(self.key())
     old_index_keys = query.fetch(1000)
     if not hasattr(self, 'INDEX_TITLE_FROM_PROP'):
         raise IndexTitleError(
             'Must declare a property name via INDEX_TITLE_FROM_PROP')
     new_keys = []
     for old_key in old_index_keys:
         old_index = IP4DB.get(old_key)
         index_num = SearchIndex.get_index_num(old_key.name())
         index_key = klass.put_index(parent=self,
                                     index_num=index_num,
                                     phrases=old_index.phrases)
         new_keys.append(index_key)
     delete_keys = filter(lambda key: key not in new_keys, old_index_keys)
     db.delete(delete_keys)
Пример #6
0
    def get(self):
        user = users.get_current_user()

        fixkey = self.request.get('fixkey', None)
        if fixkey is not None:
            fixModel = IP4DB.get(fixkey)
            if fixModel is not None:
                fixModel.deleteSearchResult()
                fixModel.putSearchResult()
            return self.redirect(self.request.referrer)

        # Show me everything I own.
        myResults = user and [
            sr for sr in SearchModels.SearchResult.SearchRequest().setUser(
                user).get()
        ] or []
        myTitles = [mr.title for mr in myResults]
        myModels = [mr.model for mr in myResults]
        myKeys = [str(mm.key()) for mm in myModels]
        myViewablesOrNones = [((user in mm.viewers) and mm or None)
                              for mm in myModels]

        modelHtml = []
        for thisResult, thisTitle, thisModel, thisKey, thisViewableOrNone \
        in zip(myResults, myTitles, myModels, myKeys, myViewablesOrNones):

            notViewableLink = ''
            if thisViewableOrNone is None:
                notViewableLink = '(Should not be viewable.  <a href="fixme?fixkey=%(thisKey)s">Fix this</a>)' % locals(
                )

            modelHtml.append(\
            """ %(thisTitle)s %(notViewableLink)s
            """ % locals())

        modelHtml = '<br/>'.join(modelHtml)
        self.response.out.write(\
        """ <html>
                <body>
                    %(modelHtml)s
                </body>
            </html> 
        """ % locals())
Пример #7
0
    def search(cls, phrase, limit=10, keys_only=False):
        """Queries search indices for phrases using a merge-join.
        
        Use of this class method lets you easily restrict searches to a kind
        and retrieve entities or keys.

        Args:
            phrase: Search phrase (string)
            limit: Number of entities or keys to return.
            keys_only: If True, return only keys with title of parent entity.
        
        Returns:
            A list.  If keys_only is True, the list holds (key, title) tuples.
            If keys_only is False, the list holds Model instances.
        """
        key_list = Searchable.full_text_search(
            phrase,
            limit=limit,
            kind=cls.kind(),
            stemming=cls.INDEX_STEMMING,
            multi_word_literal=cls.INDEX_MULTI_WORD)
        if keys_only:
            logging.debug("key_list: %s", key_list)
            return key_list
        else:
            # Andrew changed this to do a mass get and some cleanup.
            ret = IP4DB.get(
                [resultKey for stemKey, resultKey, resultTitle in key_list])
            badStems = [
                stemKey for result, (stemKey, resultKey,
                                     resultTitle) in zip(ret, key_list)
                if result is None
            ]
            if badStems:
                from google.appengine.ext import deferred
                deferred.defer(
                    db.delete,
                    badStems[:500])  # Google only allows 500 in a delete.
            ret = [r for r in ret if r is not None]
            return ret
Пример #8
0
    def get(self):
        user = users.get_current_user()

        fixkey = self.request.get('fixkey', None)
        if fixkey is not None:
            fixModel = IP4DB.get(fixkey)
            if fixModel is not None:
                fixModel.deleteSearchResult()
                fixModel.putSearchResult()
            return self.redirect(self.request.referrer)

        # Show me everything I own.
        myResults = user and [ sr for sr in SearchModels.SearchResult.SearchRequest().setUser(user).get() ] or []
        myTitles = [ mr.title for mr in myResults ]
        myModels = [ mr.model for mr in myResults ]
        myKeys = [ str(mm.key()) for mm in myModels ]
        myViewablesOrNones = [ ((user in mm.viewers) and mm or None) for mm in myModels ]

        modelHtml = []
        for thisResult, thisTitle, thisModel, thisKey, thisViewableOrNone \
        in zip(myResults, myTitles, myModels, myKeys, myViewablesOrNones):

            notViewableLink = ''
            if thisViewableOrNone is None:
                notViewableLink = '(Should not be viewable.  <a href="fixme?fixkey=%(thisKey)s">Fix this</a>)' % locals()

            modelHtml.append(\
            """ %(thisTitle)s %(notViewableLink)s
            """ % locals())

        modelHtml = '<br/>'.join(modelHtml)
        self.response.out.write(\
        """ <html>
                <body>
                    %(modelHtml)s
                </body>
            </html> 
        """ % locals())
Пример #9
0
    def get(self):
        user = users.get_current_user()
        if not (user and (users.is_current_user_admin() or LINK_SQUAD.find(user.email()) != -1 or LINK_SQUAD.find(user.user_id()) != -1)):
            return self.kickOutUser(user)
        userEmail, userId = user.email(), user.user_id()

        fixkey = self.request.get('fixkey', None)
        if fixkey is not None:
            fixModel = IP4DB.get(fixkey)
            if fixModel is not None:
                fixModel.fixedurl = self.request.get('fixurl');
                fixModel.put()

        allModels = models.ReportedUrl.all().filter('fixedurl', '')
        allModels.filter('url !=', '/characters/missingCompendium')
        # Put back when above line removed! XXX allModels.order('-modified')

        reportedUrlModels = [ rum for rum in allModels ]
        reportedCharKeys = [ ru.character for ru in reportedUrlModels ]
        reportedKeys = [ ru.key() for ru in reportedUrlModels ]
        reportedNames = [ ru.name for ru in reportedUrlModels ]
        reportedNameNoPluses = [ ru.namenoplus for ru in reportedUrlModels ]
        reportedUrls = [ ru.url for ru in reportedUrlModels ]
        reportedUrlGuesses = [ ru.urlguess or '' for ru in reportedUrlModels ]
        reportedFixedUrls = [ ru.fixedurl for ru in reportedUrlModels ]

        modelHtml, scriptHtml = [], []
        for modelIndex, model, charKey, key, name, reportedNameNoPlus, url, urlGuess, fixedUrl \
        in zip(range(len(reportedUrls)), reportedUrlModels, reportedCharKeys, reportedKeys, reportedNames, reportedNameNoPluses, reportedUrls, reportedUrlGuesses, reportedFixedUrls):
            defaultedFixedUrl = fixedUrl or DEFAULT_URL

            scriptHtml.append("""\
                    $('fixedlink' + %(modelIndex)d).href = $('fixedUrl' + %(modelIndex)d).value;
            """ % locals())

            modelHtml.append("""\
                <tr>
                    <td style="padding-right:24px;">
                        <a target="character" id="charlink%(modelIndex)d" href="/view?key=%(charKey)s">Open</a>
                    </td>
                    <td style="padding-right:24px;">
                        <a name="%(key)s" target="linksquad" id="link%(modelIndex)d" href="%(url)s">%(name)s</a>
                    </td>
                    <td style="padding-right:24px;">
                        <input target="linksquad" value="%(reportedNameNoPlus)s" 
                            onclick="this.focus();this.select();"
                        />
                    </td>
                    <td style="padding-right:24px;">
                        <input style="width:400px;" id="fixedUrl%(modelIndex)d" value="%(urlGuess)s"
                            onkeyup="
                                $('fixedlink' + %(modelIndex)d).href = $('fixedUrl' + %(modelIndex)d).value;
                            "
                        />
                    </td>
                    <td style="padding-right:24px;">
                        <a target="linksquad" id="fixedlink%(modelIndex)d" href="%(defaultedFixedUrl)s"
                            onclick="
                                $('savebutton' + %(modelIndex)d).style.display = 'inline';
                            "
                        >%(name)s</a>
                        <input type="button" id="savebutton%(modelIndex)s" value="Save URL"
                         style="display:none;"
                         onclick="
                            $('fixkey').value = '%(key)s';
                            $('fixurl').value = $('fixedUrl%(modelIndex)d').value;
                            $(this).up('form').submit();
                         "
                    </td>
                </tr>
            """ % locals())

        modelHtml = ''.join(modelHtml)
        scriptHtml = ''.join(scriptHtml)
        self.response.out.write(\
        """ <html>
                <head>
                    <title>
                        iPlay4e Link Squad, Attack!
                    </title>
                    <script type="text/javascript" language="javascript" src="/TIME_TOKEN/js/combo.js"></script>
                </head>
                <body>
                    <h2>
                        Greetings, iPlay4e Link Squad!
                    </h2>
                    <h2>
                        Instructions
                    </h2>
                    <p>
                        The items below have been reported but not yet fixed.  To fix an item, please:
                        <ol>
                            <li>
                                <a href="http://www.wizards.com/dndinsider/compendium/" target="compendium">Open the Compendium</a>
                            </li>
                            <li>
                                Search the Compendium for the item in question, or a related entry that includes it.
                            </li>
                            <li>
                                While viewing the entry, right-click the power/item card and click
                                "Open frame in new tab" (or your browser's equivalent)
                            </li>
                            <li>
                                Copy the address from the compendium entry's browser tab.
                            </li>
                            <li>
                                Paste the address into the Fixed URL box for the item below.
                            </li>
                            <li>
                                Click the Fixed Link next to the Fixed URL box to make sure it works.
                            </li>
                            <li>
                                Click the "Save URL" button next to the Fixed Link.
                            </li>
                        </ol>
                    </p>
                    <form action="/linksquad" method="POST">
                        <input type="hidden" id="fixkey" name="fixkey" value=""/>
                        <input type="hidden" id="fixurl" name="fixurl" value=""/>
                        <table>
                            <tr>
                                <th style="text-align:left;">Character</th>
                                <th style="text-align:left;">Original Link</th>
                                <th style="text-align:left;">Base Name</th>
                                <th style="text-align:left;">Fixed URL</th>
                                <th style="text-align:left;">Fixed Link</th>
                            </tr>
                            %(modelHtml)s
                        </table>
                    </form>
                    <script>
                        %(scriptHtml)s
                    </script>
                </body>
            </html> 
        """ % locals())
Пример #10
0
        def get(self):
            ret = None
            # We have a string or an owner or both.  isViable() said so, right?

            if self.__string:

                # If they didn't enter something like "1-10", we just search for what they typed.
                levelRangeMatch = self.LEVEL_RANGE_REGEX.match(self.__string)
                if not levelRangeMatch:
                    searchStrings = [self.__string]
                else:
                    lowLevel, highLevel = [
                        int(g) for g in levelRangeMatch.groups()
                    ]
                    baseSearch = self.__string.replace(
                        '%d-%d' % (lowLevel, highLevel), '')

                    # But for level-ranged searches, we actually perform multiple searches.
                    lowAndHighLevel = [min(lowLevel, 30), min(highLevel, 30)]
                    lowAndHighLevel.sort(
                    )  # in case they specified 20-11 (high first)
                    lowLevel, highLevel = lowAndHighLevel
                    searchStrings = [
                        '%s %d' % (baseSearch, l)
                        for l in range(lowLevel, highLevel + 1)
                    ]

                #logging.debug('searchStrings: %(searchStrings)r' % locals())
                resultsPerLevel = 200 / len(searchStrings)
                ret = []
                [   ret.extend([r for r in SearchResult.search(ss, limit=resultsPerLevel) if r.isPublic]) \
                    for ss in searchStrings \
                ]

            if self.__user:
                userId = self.__user.user_id()
                # Limit by owner at either the query or result level
                if ret is not None:
                    ret = [
                        r for r in ret if userId in (r.viewerIds or ())
                        or self.__user in r.viewers or self.__user == r.owner
                    ]
                else:
                    # XXX Hopefully, this is temporary code.  It handles the fact that
                    # earlier versions of v31 didn't have the viewers field.
                    badResults = \
                    [   sr for sr in SearchResult.gql('WHERE owner = :1', self.__user) \
                        if self.__user not in sr.viewers \
                    ]
                    db.delete(badResults)
                    [br.model.putSearchResult() for br in badResults]

                    ret = {}
                    for propName, matchValue in \
                    (   ('viewers', self.__user),
                        ('viewerIds', userId),
                    ):
                        [   ret.update({str(sr.key()): sr}) \
                            for sr in SearchResult.gql('WHERE %s = :1' % propName, matchValue) \
                        ]
                    ret = ret.values()

                    # We had a bug for a while that caused 2 SearchResult models for each character.
                    # Clean up from that.
                    newRet, dupResults = {}, []
                    for thisResult in ret:
                        firstRec = newRet.get(thisResult.modelKey, None)
                        if firstRec is None:
                            newRet[thisResult.modelKey] = thisResult
                        else:
                            dupResults.append(thisResult)
                    dupResults and db.delete(dupResults)
                    ret = newRet.values()

                    ret.sort(lambda x, y: cmp(x.title, y.title))

            if self.__campaignKey:
                from IP4ELibs import models
                self.__theCampaign = models.Campaign.get(self.__campaignKey)
                characterKeys = [
                    str(c.key()) for c in self.__theCampaign.characters
                ]
                ret = characterKeys and SearchResult.gql(
                    'WHERE modelKey IN :1 ORDER BY title',
                    characterKeys) or []

            # Either way, we can limit by type
            ret = ret or []
            if self.__typeList is not None:
                ret = [r for r in ret if r.modelType in self.__typeList]

            # Finally, make sure the search results refer to models that still exist.
            # We'd like to remove this code eventually; it exists because we weren't
            # always deleting search results when models were deleted.  Now we are.
            from IP4ELibs import models
            rawModelKeysAndTypes = [(r.modelKey, r.modelType) for r in ret]
            modelKeysAndTypes = [
                (db.Key(IP4DB.hrdKey(r.modelKey)), r.modelType) for r in ret
            ]

            #raise RuntimeError, 'RAW: %(rawModelKeysAndTypes)r, KEYED: %(modelKeysAndTypes)r' % locals()
            modelExistenceBooleans = \
            [   getattr(models, mType).all(keys_only=True).filter('__key__ =', mKey).count() \
                for mKey, mType in modelKeysAndTypes \
            ]
            db.delete([
                r for (r, mBool) in zip(ret, modelExistenceBooleans)
                if not mBool
            ])
            ret = [
                r for (r, mBool) in zip(ret, modelExistenceBooleans) if mBool
            ]

            return ret
Пример #11
0
 def model(self):
     return IP4DB.get(self.modelKey)
Пример #12
0
    def get(self):
        user = users.get_current_user()
        if not (user and (users.is_current_user_admin() or LINK_SQUAD.find(
                user.email()) != -1 or LINK_SQUAD.find(user.user_id()) != -1)):
            return self.kickOutUser(user)
        userEmail, userId = user.email(), user.user_id()

        fixkey = self.request.get('fixkey', None)
        if fixkey is not None:
            fixModel = IP4DB.get(fixkey)
            if fixModel is not None:
                fixModel.fixedurl = self.request.get('fixurl')
                fixModel.put()

        allModels = models.ReportedUrl.all().filter('fixedurl', '')
        allModels.filter('url !=', '/characters/missingCompendium')
        # Put back when above line removed! XXX allModels.order('-modified')

        reportedUrlModels = [rum for rum in allModels]
        reportedCharKeys = [ru.character for ru in reportedUrlModels]
        reportedKeys = [ru.key() for ru in reportedUrlModels]
        reportedNames = [ru.name for ru in reportedUrlModels]
        reportedNameNoPluses = [ru.namenoplus for ru in reportedUrlModels]
        reportedUrls = [ru.url for ru in reportedUrlModels]
        reportedUrlGuesses = [ru.urlguess or '' for ru in reportedUrlModels]
        reportedFixedUrls = [ru.fixedurl for ru in reportedUrlModels]

        modelHtml, scriptHtml = [], []
        for modelIndex, model, charKey, key, name, reportedNameNoPlus, url, urlGuess, fixedUrl \
        in zip(range(len(reportedUrls)), reportedUrlModels, reportedCharKeys, reportedKeys, reportedNames, reportedNameNoPluses, reportedUrls, reportedUrlGuesses, reportedFixedUrls):
            defaultedFixedUrl = fixedUrl or DEFAULT_URL

            scriptHtml.append("""\
                    $('fixedlink' + %(modelIndex)d).href = $('fixedUrl' + %(modelIndex)d).value;
            """ % locals())

            modelHtml.append("""\
                <tr>
                    <td style="padding-right:24px;">
                        <a target="character" id="charlink%(modelIndex)d" href="/view?key=%(charKey)s">Open</a>
                    </td>
                    <td style="padding-right:24px;">
                        <a name="%(key)s" target="linksquad" id="link%(modelIndex)d" href="%(url)s">%(name)s</a>
                    </td>
                    <td style="padding-right:24px;">
                        <input target="linksquad" value="%(reportedNameNoPlus)s" 
                            onclick="this.focus();this.select();"
                        />
                    </td>
                    <td style="padding-right:24px;">
                        <input style="width:400px;" id="fixedUrl%(modelIndex)d" value="%(urlGuess)s"
                            onkeyup="
                                $('fixedlink' + %(modelIndex)d).href = $('fixedUrl' + %(modelIndex)d).value;
                            "
                        />
                    </td>
                    <td style="padding-right:24px;">
                        <a target="linksquad" id="fixedlink%(modelIndex)d" href="%(defaultedFixedUrl)s"
                            onclick="
                                $('savebutton' + %(modelIndex)d).style.display = 'inline';
                            "
                        >%(name)s</a>
                        <input type="button" id="savebutton%(modelIndex)s" value="Save URL"
                         style="display:none;"
                         onclick="
                            $('fixkey').value = '%(key)s';
                            $('fixurl').value = $('fixedUrl%(modelIndex)d').value;
                            $(this).up('form').submit();
                         "
                    </td>
                </tr>
            """ % locals())

        modelHtml = ''.join(modelHtml)
        scriptHtml = ''.join(scriptHtml)
        self.response.out.write(\
        """ <html>
                <head>
                    <title>
                        iPlay4e Link Squad, Attack!
                    </title>
                    <script type="text/javascript" language="javascript" src="/TIME_TOKEN/js/combo.js"></script>
                </head>
                <body>
                    <h2>
                        Greetings, iPlay4e Link Squad!
                    </h2>
                    <h2>
                        Instructions
                    </h2>
                    <p>
                        The items below have been reported but not yet fixed.  To fix an item, please:
                        <ol>
                            <li>
                                <a href="http://www.wizards.com/dndinsider/compendium/" target="compendium">Open the Compendium</a>
                            </li>
                            <li>
                                Search the Compendium for the item in question, or a related entry that includes it.
                            </li>
                            <li>
                                While viewing the entry, right-click the power/item card and click
                                "Open frame in new tab" (or your browser's equivalent)
                            </li>
                            <li>
                                Copy the address from the compendium entry's browser tab.
                            </li>
                            <li>
                                Paste the address into the Fixed URL box for the item below.
                            </li>
                            <li>
                                Click the Fixed Link next to the Fixed URL box to make sure it works.
                            </li>
                            <li>
                                Click the "Save URL" button next to the Fixed Link.
                            </li>
                        </ol>
                    </p>
                    <form action="/linksquad" method="POST">
                        <input type="hidden" id="fixkey" name="fixkey" value=""/>
                        <input type="hidden" id="fixurl" name="fixurl" value=""/>
                        <table>
                            <tr>
                                <th style="text-align:left;">Character</th>
                                <th style="text-align:left;">Original Link</th>
                                <th style="text-align:left;">Base Name</th>
                                <th style="text-align:left;">Fixed URL</th>
                                <th style="text-align:left;">Fixed Link</th>
                            </tr>
                            %(modelHtml)s
                        </table>
                    </form>
                    <script>
                        %(scriptHtml)s
                    </script>
                </body>
            </html> 
        """ % locals())
Пример #13
0
        def get(self):
            ret = None
            # We have a string or an owner or both.  isViable() said so, right?

            if self.__string:

                # If they didn't enter something like "1-10", we just search for what they typed.
                levelRangeMatch = self.LEVEL_RANGE_REGEX.match(self.__string)
                if not levelRangeMatch:
                    searchStrings = [self.__string]
                else:
                    lowLevel, highLevel = [ int(g) for g in levelRangeMatch.groups() ]
                    baseSearch = self.__string.replace('%d-%d' % (lowLevel, highLevel), '')

                    # But for level-ranged searches, we actually perform multiple searches.
                    lowAndHighLevel = [min(lowLevel, 30), min(highLevel, 30)]
                    lowAndHighLevel.sort() # in case they specified 20-11 (high first)
                    lowLevel, highLevel = lowAndHighLevel
                    searchStrings = [ '%s %d' % (baseSearch, l) for l in range(lowLevel, highLevel+1) ]
                
                #logging.debug('searchStrings: %(searchStrings)r' % locals())
                resultsPerLevel=200/len(searchStrings)
                ret = []
                [   ret.extend([r for r in SearchResult.search(ss, limit=resultsPerLevel) if r.isPublic]) \
                    for ss in searchStrings \
                ]

            if self.__user:
                userId = self.__user.user_id()
                # Limit by owner at either the query or result level
                if ret is not None:
                    ret = [ r for r in ret if userId in (r.viewerIds or ()) or self.__user in r.viewers or self.__user == r.owner ]
                else:
                    # XXX Hopefully, this is temporary code.  It handles the fact that
                    # earlier versions of v31 didn't have the viewers field.
                    badResults = \
                    [   sr for sr in SearchResult.gql('WHERE owner = :1', self.__user) \
                        if self.__user not in sr.viewers \
                    ]
                    db.delete(badResults)
                    [ br.model.putSearchResult() for br in badResults ]

                    ret = {}
                    for propName, matchValue in \
                    (   ('viewers', self.__user),
                        ('viewerIds', userId),
                    ):
                        [   ret.update({str(sr.key()): sr}) \
                            for sr in SearchResult.gql('WHERE %s = :1' % propName, matchValue) \
                        ]
                    ret = ret.values()

                    # We had a bug for a while that caused 2 SearchResult models for each character.
                    # Clean up from that.
                    newRet, dupResults = {}, []
                    for thisResult in ret:
                        firstRec = newRet.get(thisResult.modelKey, None)
                        if firstRec is None:
                            newRet[thisResult.modelKey] = thisResult
                        else:
                            dupResults.append(thisResult)
                    dupResults and db.delete(dupResults)
                    ret = newRet.values()

                    ret.sort(lambda x,y:cmp(x.title, y.title))

            if self.__campaignKey:
                from IP4ELibs import models
                self.__theCampaign = models.Campaign.get(self.__campaignKey)
                characterKeys = [ str(c.key()) for c in self.__theCampaign.characters ]
                ret = characterKeys and SearchResult.gql('WHERE modelKey IN :1 ORDER BY title', characterKeys) or []

            # Either way, we can limit by type
            ret = ret or []
            if self.__typeList is not None:
                ret = [ r for r in ret if r.modelType in self.__typeList ]

            # Finally, make sure the search results refer to models that still exist.
            # We'd like to remove this code eventually; it exists because we weren't
            # always deleting search results when models were deleted.  Now we are.
            from IP4ELibs import models
            rawModelKeysAndTypes = [ (r.modelKey, r.modelType) for r in ret ]
            modelKeysAndTypes = [ (db.Key(IP4DB.hrdKey(r.modelKey)), r.modelType) for r in ret ]

            #raise RuntimeError, 'RAW: %(rawModelKeysAndTypes)r, KEYED: %(modelKeysAndTypes)r' % locals()
            modelExistenceBooleans = \
            [   getattr(models, mType).all(keys_only=True).filter('__key__ =', mKey).count() \
                for mKey, mType in modelKeysAndTypes \
            ]
            db.delete([ r for (r, mBool) in zip(ret, modelExistenceBooleans ) if not mBool ])
            ret = [ r for (r, mBool) in zip(ret, modelExistenceBooleans ) if mBool ]

            return ret
Пример #14
0
 def model(self):
     return IP4DB.get(self.modelKey)