7 def __init__(self, site, list_name, prefix, limit=None, return_values=None, max_items=None, *args, **kwargs):
10 self.list_name = list_name
11 self.generator = 'list'
18 limit = site.api_limit
19 self.args[self.prefix + 'limit'] = str(limit)
20 if 'continue' not in self.args:
21 self.args['continue'] = ''
24 self.max_items = max_items
26 self._iter = iter(xrange(0))
29 self.result_member = list_name
30 self.return_values = return_values
35 def next(self, full=False):
36 if self.max_items is not None:
37 if self.count >= self.max_items:
40 item = self._iter.next()
42 if 'timestamp' in item:
43 item['timestamp'] = client.parse_timestamp(item['timestamp'])
47 if type(self.return_values) is tuple:
48 return tuple((item[i] for i in self.return_values))
49 elif self.return_values is None:
52 return item[self.return_values]
58 return List.next(self, full=full)
61 data = self.site.api('query', (self.generator, self.list_name), *[(str(k), v) for k, v in self.args.iteritems()])
67 if data.get('continue'):
68 # New style continuation, added in MediaWiki 1.21
69 self.args.update(data['continue'])
71 elif self.list_name in data.get('query-continue', ()):
72 # Old style continuation
73 self.args.update(data['query-continue'][self.list_name])
78 def set_iter(self, data):
79 if self.result_member not in data['query']:
80 self._iter = iter(xrange(0))
81 elif type(data['query'][self.result_member]) is list:
82 self._iter = iter(data['query'][self.result_member])
84 self._iter = data['query'][self.result_member].itervalues()
87 return "<List object '%s' for %s>" % (self.list_name, self.site)
90 def generate_kwargs(_prefix, *args, **kwargs):
92 for key, value in kwargs.iteritems():
93 if value is not None and value is not False:
94 yield _prefix + key, value
97 def get_prefix(prefix, generator=False):
104 def get_list(generator=False):
111 class GeneratorList(List):
113 def __init__(self, site, list_name, prefix, *args, **kwargs):
114 List.__init__(self, site, list_name, prefix, *args, **kwargs)
116 self.args['g' + self.prefix + 'limit'] = self.args[self.prefix + 'limit']
117 del self.args[self.prefix + 'limit']
118 self.generator = 'generator'
120 self.args['prop'] = 'info|imageinfo'
121 self.args['inprop'] = 'protection'
123 self.result_member = 'pages'
125 self.page_class = page.Page
128 info = List.next(self, full=True)
130 return Category(self.site, u'', info)
132 return page.Image(self.site, u'', info)
133 return page.Page(self.site, u'', info)
135 def load_chunk(self):
136 # Put this here so that the constructor does not fail
137 # on uninitialized sites
138 self.args['iiprop'] = 'timestamp|user|comment|url|size|sha1|metadata|archivename'
139 return List.load_chunk(self)
142 class Category(page.Page, GeneratorList):
144 def __init__(self, site, name, info=None, namespace=None):
145 page.Page.__init__(self, site, name, info)
147 kwargs['gcmtitle'] = self.name
149 kwargs['gcmnamespace'] = namespace
150 GeneratorList.__init__(self, site, 'categorymembers', 'cm', **kwargs)
153 return "<Category object '%s' for %s>" % (self.name.encode('utf-8'), self.site)
155 def members(self, prop='ids|title', namespace=None, sort='sortkey',
156 dir='asc', start=None, end=None, generator=True):
157 prefix = self.get_prefix('cm', generator)
158 kwargs = dict(self.generate_kwargs(prefix, prop=prop, namespace=namespace,
159 sort=sort, dir=dir, start=start, end=end, title=self.name))
160 return self.get_list(generator)(self.site, 'categorymembers', 'cm', **kwargs)
163 class PageList(GeneratorList):
165 def __init__(self, site, prefix=None, start=None, namespace=0, redirects='all'):
166 self.namespace = namespace
170 kwargs['apprefix'] = prefix
172 kwargs['apfrom'] = start
174 GeneratorList.__init__(self, site, 'allpages', 'ap',
175 apnamespace=str(namespace), apfilterredir=redirects, **kwargs)
177 def __getitem__(self, name):
178 return self.get(name, None)
180 def get(self, name, info=()):
181 if self.namespace == 14:
182 return Category(self.site, self.site.namespaces[14] + ':' + name, info)
183 elif self.namespace == 6:
184 return page.Image(self.site, self.site.namespaces[6] + ':' + name, info)
185 elif self.namespace != 0:
186 return page.Page(self.site, self.site.namespaces[self.namespace] + ':' + name, info)
188 # Guessing page class
189 if type(name) is not int:
190 namespace = self.guess_namespace(name)
192 return Category(self.site, name, info)
194 return page.Image(self.site, name, info)
195 return page.Page(self.site, name, info)
197 def guess_namespace(self, name):
198 normal_name = page.Page.normalize_title(name)
199 for ns in self.site.namespaces:
202 if name.startswith(u'%s:' % self.site.namespaces[ns].replace(' ', '_')):
204 elif ns in self.site.default_namespaces:
205 if name.startswith(u'%s:' % self.site.default_namespaces[ns].replace(' ', '_')):
210 class PageProperty(List):
212 def __init__(self, page, prop, prefix, *args, **kwargs):
213 List.__init__(self, page.site, prop, prefix, titles=page.name, *args, **kwargs)
215 self.generator = 'prop'
217 def set_iter(self, data):
218 for page in data['query']['pages'].itervalues():
219 if page['title'] == self.page.name:
220 self._iter = iter(page.get(self.list_name, ()))
225 class PagePropertyGenerator(GeneratorList):
227 def __init__(self, page, prop, prefix, *args, **kwargs):
228 GeneratorList.__init__(self, page.site, prop, prefix, titles=page.name, *args, **kwargs)
232 class RevisionsIterator(PageProperty):
234 def load_chunk(self):
235 if 'rvstartid' in self.args and 'rvstart' in self.args:
236 del self.args['rvstart']
237 return PageProperty.load_chunk(self)