Exemple #1
0
    def __next__(self):
        if self.max_items is not None:
            if self.count >= self.max_items:
                raise StopIteration

        # For filered lists, we might have to do several requests
        # to get the next element due to miser mode.
        # See: https://github.com/mwclient/mwclient/issues/194
        while True:
            try:
                item = six.next(self._iter)
                if item is not None:
                    break
            except StopIteration:
                if self.last:
                    raise
                self.load_chunk()

        self.count += 1
        if 'timestamp' in item:
            item['timestamp'] = parse_timestamp(item['timestamp'])

        if isinstance(self, GeneratorList):
            return item
        if isinstance(self.return_values, tuple):
            return tuple((item[i] for i in self.return_values))
        if self.return_values is not None:
            return item[self.return_values]
        return item
Exemple #2
0
    def __init__(self, site, name, info=None, extra_properties=None):
        if type(name) is type(self):
            self.__dict__.update(name.__dict__)
            return
        self.site = site
        self.name = name
        self._textcache = {}

        if not info:
            if extra_properties:
                prop = 'info|' + '|'.join(six.iterkeys(extra_properties))
                extra_props = []
                for extra_prop in six.itervalues(extra_properties):
                    extra_props.extend(extra_prop)
            else:
                prop = 'info'
                extra_props = ()

            if isinstance(name, int):
                info = self.site.get('query',
                                     prop=prop,
                                     pageids=name,
                                     inprop='protection',
                                     *extra_props)
            else:
                info = self.site.get('query',
                                     prop=prop,
                                     titles=name,
                                     inprop='protection',
                                     *extra_props)
            info = six.next(six.itervalues(info['query']['pages']))
        self._info = info

        if 'invalid' in info:
            raise mwklient.errors.InvalidPageTitle(info.get('invalidreason'))

        self.namespace = info.get('ns', 0)
        self.name = info.get('title', u'')
        if self.namespace:
            self.page_title = strip_namespace(self.name)
        else:
            self.page_title = self.name

        self.touched = parse_timestamp(info.get('touched'))
        self.revision = info.get('lastrevid', 0)
        self.exists = 'missing' not in info
        self.length = info.get('length')
        self.protection = {
            i['type']: (i['level'], i['expiry'])
            for i in info.get('protection', ()) if i
        }
        self.redirect = 'redirect' in info
        self.pageid = info.get('pageid', None)
        self.contentmodel = info.get('contentmodel', None)
        self.pagelanguage = info.get('pagelanguage', None)
        self.restrictiontypes = info.get('restrictiontypes', None)

        self.last_rev_time = None
        self.edit_time = None
Exemple #3
0
    def revisions(self, revids, prop='ids|timestamp|flags|comment|user'):
        """Get data about a list of revisions.

        See also the `Page.revisions()` method.

        API doc: https://www.mediawiki.org/wiki/API:Revisions

        Example: Get revision text for two revisions:

            >>> for revision in site.revisions([689697696, 689816909],
            prop='content'):
            ...     print revision['*']

        Args:
            revids (list): A list of (max 50) revisions.
            prop (str): Which properties to get for each revision.

        Returns:
            A list of revisions
        """
        kwargs = {
            'prop': 'revisions',
            'rvprop': prop,
            'revids': '|'.join(map(text_type, revids))
        }

        revisions = []
        pages = self.get('query', **kwargs).get('query', {}).get('pages',
                                                                 {}).values()
        for page in pages:
            for revision in page.get('revisions', ()):
                revision['pageid'] = page.get('pageid')
                revision['pagetitle'] = page.get('title')
                revision['timestamp'] = parse_timestamp(revision['timestamp'])
                revisions.append(revision)
        return revisions
Exemple #4
0
    def _edit(self, summary, minor, bot, section, **kwargs):
        self._check_edit()

        data = {}
        if minor:
            data['minor'] = '1'
        if not minor:
            data['notminor'] = '1'
        if self.last_rev_time:
            data['basetimestamp'] = time.strftime('%Y%m%d%H%M%S',
                                                  self.last_rev_time)
        if self.edit_time:
            data['starttimestamp'] = time.strftime('%Y%m%d%H%M%S',
                                                   self.edit_time)
        if bot:
            data['bot'] = '1'
        if section:
            data['section'] = section

        data.update(kwargs)

        if self.site.force_login:
            data['assert'] = 'user'

        def do_edit():
            result = self.site.post(
                'edit',
                title=self.name,
                summary=summary,
                token=self.__get_token__('edit'),
                **data)
            if result['edit'].get('result').lower() == 'failure':
                raise mwklient.errors.EditError(self, result['edit'])
            return result

        try:
            result = do_edit()
        except mwklient.errors.APIError as err:
            if err.code == 'badtoken':
                # Retry, but only once to avoid an infinite loop
                self.__get_token__('edit', force=True)
                try:
                    result = do_edit()
                except mwklient.errors.APIError as err:
                    self.handle_edit_error(err, summary)
            else:
                self.handle_edit_error(err, summary)

        # 'newtimestamp' is not included if no change was made
        if 'newtimestamp' in result['edit'].keys():
            self.last_rev_time = parse_timestamp(
                result['edit'].get('newtimestamp'))

        # Workaround for https://phabricator.wikimedia.org/T211233
        for cookie in self.site.connection.cookies:
            if 'PostEditRevision' in cookie.name:
                self.site.connection.cookies.clear(
                    cookie.domain, cookie.path, cookie.name)

        # clear the page text cache
        self._textcache = {}
        return result['edit']
Exemple #5
0
 def test_parse_nonempty_timestamp(self):
     nice_ts = time.struct_time((2015, 1, 2, 20, 18, 36, 4, 2, -1))
     self.assertEqual(nice_ts, parse_timestamp('2015-01-02T20:18:36Z'))
Exemple #6
0
 def test_parse_none_timestamp(self):
     empty_ts = time.struct_time((0, 0, 0, 0, 0, 0, 0, 0, 0))
     self.assertEqual(empty_ts, parse_timestamp(None))
Exemple #7
0
 def test_parse_empty_timestamp(self):
     empty_ts = time.struct_time((0, 0, 0, 0, 0, 0, 0, 0, 0))
     self.assertEqual(empty_ts, parse_timestamp('0000-00-00T00:00:00Z'))
Exemple #8
0
 def test_parse_missing_timestamp(self):
     assert time.struct_time(
         (0, 0, 0, 0, 0, 0, 0, 0, 0)) == parse_timestamp(None)