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
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
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
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']
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'))
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))
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'))
def test_parse_missing_timestamp(self): assert time.struct_time( (0, 0, 0, 0, 0, 0, 0, 0, 0)) == parse_timestamp(None)