def delete(self, reason='', watch=False, unwatch=False, oldimage=False): """Delete page. If user does not have permission to delete page, an InsufficientPermission exception is raised. """ if not self.can('delete'): raise errors.InsufficientPermission(self) if not self.site.writeapi: raise errors.NoWriteApi(self) data = {} if watch: data['watch'] = '1' if unwatch: data['unwatch'] = '1' if oldimage: data['oldimage'] = oldimage result = self.site.api('delete', title=self.name, token=self.get_token('delete'), reason=reason, **data) return result['delete']
def text(self, section=None, expandtemplates=False): """ Returns the current wikitext of the page, or of a specific section. If the page does not exist, an empty string is returned. :Arguments: - `section` : numbered section or `None` to get the whole page (default: `None`) - `expandtemplates` : set to `True` to expand templates (default: `False`) """ if not self.can('read'): raise errors.InsufficientPermission(self) if not self.exists: return u'' if section is not None: section = text_type(section) revs = self.revisions(prop='content|timestamp', limit=1, section=section, expandtemplates=expandtemplates) try: rev = revs.next() text = rev['*'] self.section = section self.last_rev_time = rev['timestamp'] except StopIteration: text = u'' self.section = None self.last_rev_time = None if not expandtemplates: self.edit_time = time.gmtime() return text
def move(self, new_title, reason='', move_talk=True, no_redirect=False): """Move (rename) page to new_title. If user account is an administrator, specify no_direct as True to not leave a redirect. If user does not have permission to move page, an InsufficientPermission exception is raised. """ if not self.can('move'): raise errors.InsufficientPermission(self) if not self.site.writeapi: raise errors.NoWriteApi(self) data = {} if move_talk: data['movetalk'] = '1' if no_redirect: data['noredirect'] = '1' result = self.site.api('move', ('from', self.name), to=new_title, token=self.get_token('move'), reason=reason, **data) return result['move']
def upload(self, file = None, filename = None, description = '', ignore = False, file_size = None, url = None, session_key = None): if self.version[:2] < (1, 16): return compatibility.old_upload(self, file = file, filename = filename, description = description, ignore = ignore, file_size = file_size) image = self.Images[filename] if not image.can('upload'): raise errors.InsufficientPermission(filename) predata = {} predata['comment'] = description if ignore: predata['ignorewarnings'] = 'true' predata['token'] = image.get_token('edit') predata['action'] = 'upload' predata['format'] = 'json' predata['filename'] = filename if url: predata['url'] = url if session_key: predata['session_key'] = session_key if file is None: postdata = predata else: if type(file) is str: file_size = len(file) file = StringIO(file) if file_size is None: file.seek(0, 2) file_size = file.tell() file.seek(0, 0) postdata = upload.UploadFile('file', filename, file_size, file, predata) wait_token = self.wait_token() while True: try: data = self.raw_call('api', postdata).read() info = json.loads(data) if not info: info = {} if self.handle_api_result(info, kwargs = predata): return info.get('upload', {}) except errors.HTTPStatusError, e: if e[0] == 503 and e[1].getheader('X-Database-Lag'): self.wait(wait_token, int(e[1].getheader('Retry-After'))) elif e[0] < 500 or e[0] > 599: raise else: self.wait(wait_token) except errors.HTTPError: self.wait(wait_token)
def old_upload(self, fileobj, filename, description, license='', ignore=False, file_size=None): image = self.Images[filename] if not image.can('upload'): raise errors.InsufficientPermission(filename) if image.exists and not ignore: raise errors.FileExists(filename) if type(fileobj) is str: file_size = len(fileobj) fileobj = StringIO(fileobj) if file_size is None: fileobj.seek(0, 2) file_size = fileobj.tell() fileobj.seek(0, 0) predata = {} # Do this thing later so that an incomplete upload won't work # predata['wpDestFile'] = filename predata['wpUploadDescription'] = description predata['wpLicense'] = license if ignore: predata['wpIgnoreWarning'] = 'true' predata['wpUpload'] = 'Upload file' predata['wpSourceType'] = 'file' predata['wpDestFile'] = filename predata['wpEditToken'] = image.get_token('edit') postdata = upload.UploadFile('wpUploadFile', filename, file_size, fileobj, predata) wait_token = self.wait_token() while True: try: self.connection.post(self.host, '%sindex.php?title=Special:Upload&maxlag=%s' % (self.path, self.max_lag), data=postdata).read() except errors.HTTPStatusError as exc: e = exc.args if pythonver >= 3 else exc if e[0] == 503 and e[1].getheader('X-Database-Lag'): self.wait(wait_token, int(e[1].getheader('Retry-After'))) elif e[0] < 500 or e[0] > 599: raise else: self.wait(wait_token) except errors.HTTPError: self.wait(wait_token) else: return fileobj.seek(0, 0)
def move(self, new_title, reason = '', move_talk = True, no_redirect = False): if not self.can('move'): raise errors.InsufficientPermission(self) if not self.site.writeapi: return OldPage.move(self, new_title = new_title, reason = reason, move_talk = move_talk) data = {} if move_talk: data['movetalk'] = '1' if no_redirect: data['noredirect'] = '1' result = self.site.api('move', ('from', self.name), to = new_title, token = self.get_token('move'), reason = reason, **data) return result['move']
def delete(self, reason = '', watch = False, unwatch = False, oldimage = False): if not self.can('delete'): raise errors.InsufficientPermission(self) if not self.site.writeapi: return OldPage.delete(self, reason = reason) data = {} if watch: data['watch'] = '1' if unwatch: data['unwatch'] = '1' if oldimage: data['oldimage'] = oldimage result = self.site.api('delete', title = self.name, token = self.get_token('delete'), reason = reason, **data) return result['delete']
def edit(self, section=None, readonly=False): if not self.can('read'): raise errors.InsufficientPermission(self) if not self.exists: return u'' revs = self.revisions(prop='content|timestamp', limit=1) try: rev = revs.next() self.text = rev['*'] self.edit_time = rev['timestamp'] except StopIteration: self.text = u'' self.edit_time = None return self.text
def edit(self, section=None, readonly=False): if not self.can('read'): raise errors.InsufficientPermission(self) if not self.exists: return u'' revs = self.revisions(prop='content|timestamp', limit=1) try: #'RevisionsIterator' object is not an iterator #rev = next(revs) rev = revs.next() self.text = rev['*'] self.last_rev_time = rev['timestamp'] except StopIteration: self.text = u'' self.edit_time = None self.edit_time = time.gmtime() return self.text
def edit(self, section=None, readonly=False, start_timestamp=None): if not self.can('read'): raise errors.InsufficientPermission(self) if not self.exists: return u'' #Edit for pypedia revs = self.revisions(prop='content|timestamp', limit=1, start=start_timestamp) try: rev = revs.next() self.text = rev['*'] self.last_rev_time = rev['timestamp'] except StopIteration: self.text = u'' self.edit_time = None self.edit_time = time.gmtime() return self.text
def upload(self, file=None, filename=None, description='', ignore=False, file_size=None, url=None, filekey=None, comment=None): """ Uploads a file to the site. Returns JSON result from the API. Can raise `errors.InsufficientPermission` and `requests.exceptions.HTTPError`. : Parameters : - file : File object or stream to upload. - filename : Destination filename, don't include namespace prefix like 'File:' - description : Wikitext for the file description page. - ignore : True to upload despite any warnings. - file_size : Deprecated in mwclient 0.7 - url : URL to fetch the file from. - filekey : Key that identifies a previous upload that was stashed temporarily. - comment : Upload comment. Also used as the initial page text for new files if `description` is not specified. Note that one of `file`, `filekey` and `url` must be specified, but not more than one. For normal uploads, you specify `file`. Example: >>> client.upload(open('somefile', 'rb'), filename='somefile.jpg', description='Some description') """ if file_size is not None: # Note that DeprecationWarning is hidden by default since Python 2.7 warnings.warn('file_size is deprecated since mwclient 0.7', DeprecationWarning) file_size = None if filename is None: raise TypeError('filename must be specified') if len([x for x in [file, filekey, url] if x is not None]) != 1: raise TypeError( "exactly one of 'file', 'filekey' and 'url' must be specified") image = self.Images[filename] if not image.can('upload'): raise errors.InsufficientPermission(filename) predata = {} if comment is None: predata['comment'] = description else: predata['comment'] = comment predata['text'] = description if ignore: predata['ignorewarnings'] = 'true' predata['token'] = image.get_token('edit') predata['action'] = 'upload' predata['format'] = 'json' predata['filename'] = filename if url: predata['url'] = url # Renamed from sessionkey to filekey # https://git.wikimedia.org/commit/mediawiki%2Fcore.git/5f13517e if self.version[:2] < (1, 18): predata['sessionkey'] = filekey else: predata['filekey'] = filekey postdata = predata files = None if file is not None: # Workaround for https://github.com/mwclient/mwclient/issues/65 # ---------------------------------------------------------------- # Since the filename in Content-Disposition is not interpreted, # we can send some ascii-only dummy name rather than the real # filename, which might contain non-ascii. file = ('fake-filename', file) # End of workaround # ---------------------------------------------------------------- files = {'file': file} wait_token = self.wait_token() while True: try: data = self.raw_call('api', postdata, files) info = json.loads(data) if not info: info = {} if self.handle_api_result(info, kwargs=predata): return info.get('upload', {}) except requests.exceptions.HTTPError as e: if e.args[0] == 503 and e.args[1].getheader('X-Database-Lag'): self.wait(wait_token, int(e.args[1].getheader('Retry-After'))) elif e.args[0] < 500 or e.args[0] > 599: raise else: self.wait(wait_token) except requests.exceptions.ConnectionError: self.wait(wait_token)
def upload(self, file, filename, description, license = '', ignore = False, file_size = None): image = self.Images[filename] if not image.can('upload'): raise errors.InsufficientPermission(filename) if image.exists and not ignore: raise errors.FileExists(filename) if type(file) is str: file_size = len(file) file = StringIO(file) if file_size is None: file.seek(0, 2) file_size = file.tell() file.seek(0, 0) predata = {} # Do this thing later so that an incomplete upload won't work # predata['wpDestFile'] = filename predata['wpUploadDescription'] = description predata['wpLicense'] = license if ignore: predata['wpIgnoreWarning'] = 'true' predata['wpUpload'] = 'Upload file' predata['wpSourceType'] = 'file' predata['wpDestFile'] = filename boundary = '----%s----' % ''.join((random.choice( 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for i in xrange(32))) data_header = [] for name, value in predata.iteritems(): data_header.append('--' + boundary) data_header.append('Content-Disposition: form-data; name="%s"' % name) data_header.append('') data_header.append(value.encode('utf-8')) data_header.append('--' + boundary) data_header.append('Content-Disposition: form-data; name="wpUploadFile"; filename="%s"' % \ filename.encode('utf-8')) data_header.append('Content-Type: application/octet-stream') data_header.append('') data_header.append('') postdata = '\r\n'.join(data_header) content_length = (len(postdata) + file_size + 2 + # \r\n (6 + len(boundary)) + 49 + # wpUpload 2 + # \r\n 1 + # 1 (4 + len(boundary)) + 2) def iterator(): yield postdata while True: chunk = file.read(32768) if not chunk: break yield chunk yield '\r\n' yield '--%s\r\n' % boundary yield 'Content-Disposition: form-data; name="wpUpload"\r\n' yield '\r\n' yield '1' yield '--%s--' % boundary yield '\r\n' wait_token = self.wait_token() while True: try: self.connection.post(self.host, self.path + 'index.php?title=Special:Upload&maxlag=' + self.max_lag, headers = {'Content-Type': 'multipart/form-data; boundary=' + boundary, 'Content-Length': str(content_length)}, stream_iter = iterator()).read() except errors.HTTPStatusError, e: if e[0] == 503 and e[1].getheader('X-Database-Lag'): self.wait(wait_token, int(e[1].getheader('Retry-After'))) elif e[0] < 500 or e[0] > 599: raise else: self.wait(wait_token) except errors.HTTPError: self.wait(wait_token)