From 241e5d6e99824bec1ff86b57158c26495fb3601a Mon Sep 17 00:00:00 2001
From: Bryan Tong Minh <bryan.tongminh@gmail.com>
Date: Mon, 2 Nov 2009 18:54:11 +0000
Subject: [PATCH] * Added prop=duplicatefiles * Add stubs for missing functions
 * Update RELEASE-NOTES * Add fileno parameter to HTTPConnection * Properly
 fix alpha versions

---
 mwclient/RELEASE-NOTES.txt | 11 ++++----
 mwclient/client.py         | 57 ++++++++++++++++++++++++++++----------
 mwclient/http.py           |  2 ++
 mwclient/page.py           |  6 ++++
 4 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/mwclient/RELEASE-NOTES.txt b/mwclient/RELEASE-NOTES.txt
index 4134588..d0605fd 100644
--- a/mwclient/RELEASE-NOTES.txt
+++ b/mwclient/RELEASE-NOTES.txt
@@ -4,7 +4,9 @@ This is mwclient 0.6.4. The following are the release notes for this version.
 
 == Changes in version 0.6.4 ==
 Mwclient 0.6.4 is unreleased.
-There are no changes yet.
+* Added support for upload API
+* Added prop=duplicatefiles
+* Properly fix detection of alpha versions
 
 == Changes in version 0.6.3 ==
 * Added domain parameter to login.
@@ -32,9 +34,8 @@ Mwclient 0.6.1 was released in May 2008. No release notes were kept for
 that version. 
 
 Mwclient 0.6.0 was released in February 2008. It was the first official 
-release via Sourceforge.
-
-This version kicked out some Pywikipedia influences added in 0.4.
+release via Sourceforge. This version removed some Pywikipedia influences 
+added in 0.4.
 
 == Mwclient 0.5 ==
 Mwclient 0.5 was an architectural redesign which accomplished easy 
@@ -50,4 +51,4 @@ Mwclient 0.2 and 0.3 were probably a bit of a generalization, and maybe
 already used the API for some part, but details are unknown.
 
 == Mwclient 0.1 ==
-Mwclient 0.1 was a non-API module for accessing Wikipedia using an XML parser.
\ No newline at end of file
+Mwclient 0.1 was a non-API module for accessing Wikipedia using an XML parser.
diff --git a/mwclient/client.py b/mwclient/client.py
index 616a5e6..275aef4 100644
--- a/mwclient/client.py
+++ b/mwclient/client.py
@@ -96,14 +96,22 @@ class Site(object):
 			
 		if self.site['generator'].startswith('MediaWiki '):
 			version = self.site['generator'][10:].split('.')
+			def split_num(s):
+				i = 0
+				while i < len(s):
+					if s[i] < '0' or s[i] > '9':
+						break
+					i += 1
+				return int(s[:i]), s[i:]
 			# FIXME! Fix those awful two hacks
-			if len(version) == 2 and version[1].endswith('alpha'):
-				self.version = (int(version[0]), int(version[1][:-5]), 'alpha')
-			elif len(version) == 2 and version[1].endswith('alpha-wmf'):
-				self.version = (int(version[0]), int(version[1][:-9]), 'alpha-wmf')
+			if len(version) == 2:
+				# An alpha version
+				self.version = (int(version[0]), ) + split_num(version[1])
 			elif len(version) == 3 and 'rc' in version[2]:
+				# Release candidate
 				self.version = (int(version[0]), int(version[1]), version[2])
 			elif len(version) == 3:
+				# Regular y.x.z version
 				self.version = (int(version[0]), int(version[1]), int(version[2]))
 			else:
 				raise errors.MediaWikiVersionError('Unknown MediaWiki %s' % '.'.join(version))
@@ -273,6 +281,7 @@ class Site(object):
 
 	# Actions
 	def email(self, user, text, subject, cc = False):
+		#TODO: Use api!
 		postdata = {}
 		postdata['wpSubject'] = subject
 		postdata['wpText'] = text
@@ -324,7 +333,8 @@ class Site(object):
 			self.site_init()
 
 
-	def upload(self, file, filename, description, ignore = False, file_size = None):
+	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, 
@@ -334,13 +344,7 @@ class Site(object):
 		if not image.can('upload'):
 			raise errors.InsufficientPermission(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
@@ -352,8 +356,23 @@ class Site(object):
 		predata['action'] = 'upload'
 		predata['format'] = 'json'
 		predata['filename'] = filename
-		
-		postdata = upload.UploadFile('file', filename, file_size, file, predata)
+		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:
@@ -362,7 +381,7 @@ class Site(object):
 				info = simplejson.loads(data)
 				if not info:
 					info = {}
-				if self.handle_api_result(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'):
@@ -380,6 +399,11 @@ class Site(object):
 		if title is not None: kwargs['title'] = title
 		result = self.api('parse', **kwargs)
 		return result['parse']
+	
+	# def block: requires 1.12
+	# def unblock: requires 1.12
+	# def patrol: requires 1.14
+	# def import: requires 1.15
 			
 	# Lists
 	def allpages(self, start = None, prefix = None, namespace = '0', filterredir = 'all',
@@ -393,6 +417,8 @@ class Site(object):
 			namespace = namespace, filterredir = filterredir, dir = dir, 
 			filterlanglinks = filterlanglinks))
 		return listing.List.get_list(generator)(self, 'allpages', 'ap', limit = limit, return_values = 'title', **kwargs)
+	# def allimages(self): requires 1.12
+	# TODO!
 
 	def alllinks(self, start = None, prefix = None, unique = False, prop = 'title',
 			namespace = '0', limit = None, generator = True):
@@ -445,6 +471,7 @@ class Site(object):
 		kwargs = dict(listing.List.generate_kwargs('le', prop = prop, type = type, start = start,
 			end = end, dir = dir, user = user, title = title))
 		return listing.List(self, 'logevents', 'le', limit = limit, **kwargs)
+	# def protectedtitles requires 1.15
 	def random(self, namespace, limit = 20):
 		self.require(1, 12)
 		
diff --git a/mwclient/http.py b/mwclient/http.py
index 6a3e726..8cc8507 100644
--- a/mwclient/http.py
+++ b/mwclient/http.py
@@ -168,6 +168,8 @@ class HTTPPersistentConnection(object):
 		
 	def close(self):
 		self._conn.close()
+	def fileno(self):
+		return self._conn.sock.fileno()
 
 class HTTPConnection(HTTPPersistentConnection):
 	def request(self, method, host, path, headers, data,
diff --git a/mwclient/page.py b/mwclient/page.py
index e2ffbff..f03de2b 100644
--- a/mwclient/page.py
+++ b/mwclient/page.py
@@ -191,6 +191,8 @@ class Page(object):
 	def purge(self):
 		self.site.raw_index('purge', title = self.name)
 		
+	# def watch: requires 1.14
+		
 	# Properties
 	def backlinks(self, namespace = None, filterredir = 'all', redirect = False, limit = None, generator = True):
 		self.site.require(1, 9)
@@ -280,6 +282,10 @@ class Image(Page):
 		if redirect: kwargs['%sredirect' % prefix] = '1'
 		return listing.List.get_list(generator)(self.site, 'imageusage', 'iu', 
 			limit = limit, return_values = 'title', **kwargs)
+	def duplicatefiles(self, limit = None):
+		self.require(1, 14)
+		return listing.PageProperty(self, 'duplicatefiles', 'df',
+			dflimit = limit)
 
 	def download(self):
 		url = self.imageinfo['url']
-- 
GitLab