<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ADump</id>
	<title>Module:Dump - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ADump"/>
	<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Dump&amp;action=history"/>
	<updated>2026-06-13T23:26:01Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.3</generator>
	<entry>
		<id>https://mywikibiz.com/index.php?title=Module:Dump&amp;diff=471533&amp;oldid=prev</id>
		<title>Zoran: Pywikibot 6.4.0</title>
		<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Dump&amp;diff=471533&amp;oldid=prev"/>
		<updated>2021-07-15T21:23:09Z</updated>

		<summary type="html">&lt;p&gt;Pywikibot 6.4.0&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Dump a table to help develop other modules.&lt;br /&gt;
-- It is also possible to use mw.dumpObject() but the result from this&lt;br /&gt;
-- module is clearer and is close to valid Lua source.&lt;br /&gt;
-- The main purpose is to allow easy inspection of Wikidata items.&lt;br /&gt;
-- Preview the following in a sandbox to see entity Q833639 as a Lua table:&lt;br /&gt;
--   {{#invoke:dump|wikidata|Q833639}}&lt;br /&gt;
-- Preview the following to dump a built-in table:&lt;br /&gt;
--   {{#invoke:dump|testcase}}&lt;br /&gt;
&lt;br /&gt;
local Collection  -- a table to hold items&lt;br /&gt;
Collection = {&lt;br /&gt;
	add = function (self, item)&lt;br /&gt;
		if item ~= nil then&lt;br /&gt;
			self.n = self.n + 1&lt;br /&gt;
			self[self.n] = item&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
	join = function (self, sep)&lt;br /&gt;
		return table.concat(self, sep)&lt;br /&gt;
	end,&lt;br /&gt;
	remove = function (self, pos)&lt;br /&gt;
		if self.n &amp;gt; 0 and (pos == nil or (0 &amp;lt; pos and pos &amp;lt;= self.n)) then&lt;br /&gt;
			self.n = self.n - 1&lt;br /&gt;
			return table.remove(self, pos)&lt;br /&gt;
		end&lt;br /&gt;
	end,&lt;br /&gt;
	sort = function (self, comp)&lt;br /&gt;
		table.sort(self, comp)&lt;br /&gt;
	end,&lt;br /&gt;
	new = function ()&lt;br /&gt;
		return setmetatable({n = 0}, Collection)&lt;br /&gt;
	end&lt;br /&gt;
}&lt;br /&gt;
Collection.__index = Collection&lt;br /&gt;
&lt;br /&gt;
local function pre_block(text)&lt;br /&gt;
	-- Pre tags returned by a module do not act like wikitext &amp;lt;pre&amp;gt;...&amp;lt;/pre&amp;gt;.&lt;br /&gt;
	return '&amp;lt;pre&amp;gt;\n' ..&lt;br /&gt;
		mw.text.nowiki(text) ..&lt;br /&gt;
		(text:sub(-1) == '\n' and '' or '\n') ..&lt;br /&gt;
		'&amp;lt;/pre&amp;gt;\n'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function make_tabstr(indent)&lt;br /&gt;
	-- Return a string to generate one level of indent.&lt;br /&gt;
	if indent == 'tab' then&lt;br /&gt;
		-- Tabs do not work well in a browser edit window, but can force them.&lt;br /&gt;
		return '\t'&lt;br /&gt;
	end&lt;br /&gt;
	indent = tonumber(indent)&lt;br /&gt;
	if not (type(indent) == 'number' and 1 &amp;lt;= indent and indent &amp;lt;= 32) then&lt;br /&gt;
		indent = 4&lt;br /&gt;
	end&lt;br /&gt;
	return string.rep(' ', indent)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function _dumphtml(html, tabwidth)&lt;br /&gt;
	-- Return a pretty-text formatted dump of an html string.&lt;br /&gt;
	-- This assumes clean html, for example, tag &amp;quot;&amp;lt;table&amp;gt;&amp;quot; not &amp;quot;&amp;lt; table &amp;gt;&amp;quot;.&lt;br /&gt;
	if type(html) ~= 'string' then&lt;br /&gt;
		return ''&lt;br /&gt;
	end&lt;br /&gt;
	local selfClosingTags = {  -- from mw.html.lua&lt;br /&gt;
		area = true,&lt;br /&gt;
		base = true,&lt;br /&gt;
		br = true,&lt;br /&gt;
		col = true,&lt;br /&gt;
		command = true,&lt;br /&gt;
		embed = true,&lt;br /&gt;
		hr = true,&lt;br /&gt;
		img = true,&lt;br /&gt;
		input = true,&lt;br /&gt;
		keygen = true,&lt;br /&gt;
		link = true,&lt;br /&gt;
		meta = true,&lt;br /&gt;
		param = true,&lt;br /&gt;
		source = true,&lt;br /&gt;
		track = true,&lt;br /&gt;
		wbr = true,&lt;br /&gt;
	}&lt;br /&gt;
	local tabstr = make_tabstr(tabwidth)&lt;br /&gt;
	local function indent_pad(depth, isfirst)&lt;br /&gt;
		-- Return a string with an indent to match depth.&lt;br /&gt;
		if depth &amp;gt; 0 then&lt;br /&gt;
			return '\n' .. string.rep(tabstr, depth)&lt;br /&gt;
		end&lt;br /&gt;
		return isfirst and '' or '\n'&lt;br /&gt;
	end&lt;br /&gt;
	local function extract(result, html, pos, len, depth, currenttag)&lt;br /&gt;
		-- Dump more of html into table result and return new pos.&lt;br /&gt;
		local has_child&lt;br /&gt;
		while pos &amp;lt;= len do&lt;br /&gt;
			local s, e = html:find('&amp;lt;[^&amp;lt;&amp;gt;]*&amp;gt;', pos)&lt;br /&gt;
			if s then&lt;br /&gt;
				if s &amp;gt; pos then&lt;br /&gt;
					table.insert(result, html:sub(pos, s-1))&lt;br /&gt;
				end&lt;br /&gt;
				if html:sub(s+1, s+1) == '/' then&lt;br /&gt;
					-- A closing tag.&lt;br /&gt;
					local tag = html:match('^([a-zA-Z0-9]+)&amp;gt;', s+2) or 'NOTAG'&lt;br /&gt;
					if tag == currenttag then&lt;br /&gt;
						local indent = has_child and indent_pad(depth - 1) or ''&lt;br /&gt;
						table.insert(result, indent .. '&amp;lt;/' .. tag .. '&amp;gt;')&lt;br /&gt;
					else&lt;br /&gt;
						-- Should never happen.&lt;br /&gt;
						table.insert(result, '\n&amp;lt;/' .. tag .. '&amp;gt;')&lt;br /&gt;
					end&lt;br /&gt;
					return e + 1&lt;br /&gt;
				end&lt;br /&gt;
				local tag = html:match('^[a-zA-Z0-9]+', s+1) or 'NOTAG'&lt;br /&gt;
				if html:sub(e-1, e-1) == '/' or selfClosingTags[tag] then&lt;br /&gt;
					-- A self-closing tag.&lt;br /&gt;
					table.insert(result, html:sub(s, e))&lt;br /&gt;
					pos = e + 1&lt;br /&gt;
				else&lt;br /&gt;
					-- An opening tag.&lt;br /&gt;
					table.insert(result, indent_pad(depth, pos == 1) .. html:sub(s, e))&lt;br /&gt;
					pos = extract(result, html, e+1, len, depth+1, tag)&lt;br /&gt;
					has_child = true&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				table.insert(result, html:sub(pos))&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return len + 1&lt;br /&gt;
	end&lt;br /&gt;
	local result = {}&lt;br /&gt;
	html = html:gsub('&amp;gt;%s+&amp;lt;', '&amp;gt;&amp;lt;'):gsub('\n%s*', ' ')&lt;br /&gt;
	extract(result, html, 1, #html, 0)&lt;br /&gt;
	return pre_block(table.concat(result))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dumphtml(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	local text = args[1] or pargs[1]&lt;br /&gt;
	local indent = args.indent or pargs.indent&lt;br /&gt;
	return _dumphtml(text, indent)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function quoted(str)&lt;br /&gt;
	return (string.format('%q', str):gsub('\\\n', '\\n'))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function iterkeys(var, control)&lt;br /&gt;
	-- Return an iterator over the keys of var (which should be a table).&lt;br /&gt;
	-- The keys are sorted with numbered keys first, then other types.&lt;br /&gt;
	-- The iterator returns key, repr where key is the actual key, and&lt;br /&gt;
	-- repr is its representation: a number for the ipairs keys, or&lt;br /&gt;
	-- a string, including for number keys above the table length.&lt;br /&gt;
	if type(var) ~= 'table' then&lt;br /&gt;
		return function () return nil end&lt;br /&gt;
	end&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	local results = Collection.new()&lt;br /&gt;
	for i, _ in ipairs(var) do&lt;br /&gt;
		nums[i] = true&lt;br /&gt;
		results:add({ i, i })&lt;br /&gt;
	end&lt;br /&gt;
	local keys = Collection.new()&lt;br /&gt;
	for k, _ in pairs(var) do&lt;br /&gt;
		if not nums[k] then&lt;br /&gt;
			keys:add(k)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local autoname = control.autoname&lt;br /&gt;
	keys:sort(function (a, b)&lt;br /&gt;
			local ta, tb = type(a), type(b)&lt;br /&gt;
			if ta == tb then&lt;br /&gt;
				if ta == 'number' or ta == 'string' then&lt;br /&gt;
					return a &amp;lt; b&lt;br /&gt;
				end&lt;br /&gt;
				if ta == 'boolean' then&lt;br /&gt;
					return b and not a&lt;br /&gt;
				end&lt;br /&gt;
				return autoname(a) &amp;lt; autoname(b)&lt;br /&gt;
			end&lt;br /&gt;
			if ta == 'number' then&lt;br /&gt;
				return true&lt;br /&gt;
			elseif tb == 'number' then&lt;br /&gt;
				return false&lt;br /&gt;
			else&lt;br /&gt;
				return ta &amp;lt; tb&lt;br /&gt;
			end&lt;br /&gt;
		end)&lt;br /&gt;
	for _, k in ipairs(keys) do&lt;br /&gt;
		local repr&lt;br /&gt;
		local tk = type(k)&lt;br /&gt;
		if tk == 'number' then&lt;br /&gt;
			repr = '[' .. k .. ']'&lt;br /&gt;
		elseif tk == 'string' then&lt;br /&gt;
			if k:match('^[%a_][%w_]*$') then&lt;br /&gt;
				repr = k&lt;br /&gt;
			else&lt;br /&gt;
				repr = '[' .. quoted(k) .. ']'&lt;br /&gt;
			end&lt;br /&gt;
		elseif tk == 'boolean' then&lt;br /&gt;
			repr = '[' .. tostring(k) .. ']'&lt;br /&gt;
		else&lt;br /&gt;
			repr = autoname(k)&lt;br /&gt;
			control.needed[repr] = true&lt;br /&gt;
		end&lt;br /&gt;
		results:add({ k, repr })&lt;br /&gt;
	end&lt;br /&gt;
	local last = 0&lt;br /&gt;
	return function ()&lt;br /&gt;
		if last &amp;lt; results.n then&lt;br /&gt;
			last = last + 1&lt;br /&gt;
			return unpack(results[last])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function vardump(var, vname, depth, control, self, parents)&lt;br /&gt;
	-- Update items in control with results from dumping a variable.&lt;br /&gt;
	local function put(value, options)&lt;br /&gt;
		options = options or {}&lt;br /&gt;
		local indent = options.indent or depth&lt;br /&gt;
		local comma = (options.kind == 'open' or indent == 0) and '' or ','&lt;br /&gt;
		control.items:add({&lt;br /&gt;
			key = (type(vname) == 'string' and options.kind ~= 'close') and vname or nil,&lt;br /&gt;
			value = value .. comma,&lt;br /&gt;
			depth = indent,&lt;br /&gt;
			note = options.note&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	if var == nil then&lt;br /&gt;
		put('nil')&lt;br /&gt;
	elseif type(var) == 'string' then&lt;br /&gt;
		put(quoted(var))&lt;br /&gt;
	elseif type(var) == 'table' then&lt;br /&gt;
		local this = control.autoname(var)&lt;br /&gt;
		if depth &amp;gt;= control.limitdepth then&lt;br /&gt;
			put(this)&lt;br /&gt;
		elseif parents and parents[this] then&lt;br /&gt;
			control.needed[this] = true&lt;br /&gt;
			if self == this then&lt;br /&gt;
				put(this, {note = 'self'})&lt;br /&gt;
				control.needed['self'] = true&lt;br /&gt;
			else&lt;br /&gt;
				put(this, {note = 'repeat'})&lt;br /&gt;
				control.needed['repeat'] = true&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			parents = parents or {}&lt;br /&gt;
			parents[this] = true&lt;br /&gt;
			self = this&lt;br /&gt;
			put('{', {kind = 'open', note = this})&lt;br /&gt;
			local mt = getmetatable(var)&lt;br /&gt;
			if mt then&lt;br /&gt;
				vardump(mt, '__metatable', depth + 1, control, self, parents)&lt;br /&gt;
			end&lt;br /&gt;
			local maxsize = control.items.n + control.limititems&lt;br /&gt;
			for key, keyrep in iterkeys(var, control) do&lt;br /&gt;
				if control.items.n &amp;gt; maxsize then&lt;br /&gt;
					put('...more...')&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
				vardump(var[key], keyrep, depth + 1, control, self, parents)&lt;br /&gt;
			end&lt;br /&gt;
			put('}', { kind = 'close' })&lt;br /&gt;
		end&lt;br /&gt;
	elseif type(var) == 'boolean' or type(var) == 'number' then&lt;br /&gt;
		put(tostring(var))&lt;br /&gt;
	else  -- function (or userdata or thread)&lt;br /&gt;
		put(control.autoname(var))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dumper(var, vname, tabwidth, wantraw, limititems, limitdepth)&lt;br /&gt;
	-- Return a string representing var in almost-correct Lua syntax.&lt;br /&gt;
	-- There is no newline at the end of the result.&lt;br /&gt;
	local onames = {}&lt;br /&gt;
	local tcounts = {}&lt;br /&gt;
	local function autoname(var)&lt;br /&gt;
		-- Return a string that is a unique name for var, given it is not&lt;br /&gt;
		-- a number or string.&lt;br /&gt;
		if not onames[var] then&lt;br /&gt;
			local name = type(var)&lt;br /&gt;
			tcounts[name] = (tcounts[name] or 0) + 1&lt;br /&gt;
			onames[var] = name .. '_' .. tcounts[name]&lt;br /&gt;
		end&lt;br /&gt;
		return onames[var]&lt;br /&gt;
	end&lt;br /&gt;
	local control = {&lt;br /&gt;
		autoname = autoname,&lt;br /&gt;
		limititems = limititems or 10000,&lt;br /&gt;
		limitdepth = limitdepth or 50,&lt;br /&gt;
		items = Collection.new(),&lt;br /&gt;
		needed = {},&lt;br /&gt;
	}&lt;br /&gt;
	vardump(var, tostring(vname or 'variable'), 0, control)&lt;br /&gt;
	local tabstr = make_tabstr(tabwidth)&lt;br /&gt;
	local lines = Collection.new()&lt;br /&gt;
	for i, v in ipairs(control.items) do&lt;br /&gt;
		local indent = string.rep(tabstr, v.depth)&lt;br /&gt;
		local note = v.note&lt;br /&gt;
		if note and control.needed[note] then&lt;br /&gt;
			note = '  -- ' .. note&lt;br /&gt;
		else&lt;br /&gt;
			note = ''&lt;br /&gt;
		end&lt;br /&gt;
		local k = v.key and (v.key .. ' = ') or ''&lt;br /&gt;
		lines:add(indent .. k .. v.value .. note)&lt;br /&gt;
	end&lt;br /&gt;
	local raw = lines:join('\n')&lt;br /&gt;
	return wantraw and raw or pre_block(raw)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dump_testcase(frame)&lt;br /&gt;
	local item&lt;br /&gt;
	if type(frame) == 'table' then&lt;br /&gt;
		item = frame.args[1]&lt;br /&gt;
	else&lt;br /&gt;
		item = frame&lt;br /&gt;
	end&lt;br /&gt;
	if item == 'G' or item == '_G' then&lt;br /&gt;
		return dumper(_G, '_G', frame.args.indent)&lt;br /&gt;
	end&lt;br /&gt;
	local fruit = { 'apple', 'banana', [0] = 'zero', [{'anon'}] = 'anon' }&lt;br /&gt;
	local testcase = {&lt;br /&gt;
		[100] = 'one hundred',&lt;br /&gt;
		[99] = 'ninety nine',&lt;br /&gt;
		[0.5] = 'one half',&lt;br /&gt;
		[-1] = 'negative one',&lt;br /&gt;
		'one',&lt;br /&gt;
		'two',&lt;br /&gt;
		[' '] = 'space',&lt;br /&gt;
		['1 –◆— z'] = 'unicode',&lt;br /&gt;
		alpha = 'aaa',&lt;br /&gt;
		beta = 'bbb',&lt;br /&gt;
		c = 123,&lt;br /&gt;
		data = {&lt;br /&gt;
			dumper = dumper,&lt;br /&gt;
			[dumper] = 'dumper',&lt;br /&gt;
			'three',&lt;br /&gt;
			'four',&lt;br /&gt;
			T = true,&lt;br /&gt;
			[true] = 'T',&lt;br /&gt;
			alpha2 = 'aaa2',&lt;br /&gt;
			beta2 = 'bbb2',&lt;br /&gt;
			F = false,&lt;br /&gt;
			[false] = 'F',&lt;br /&gt;
			c2 = 1234,&lt;br /&gt;
			data2 = {&lt;br /&gt;
				'five',&lt;br /&gt;
				'six',&lt;br /&gt;
				alpha3 = 'aaa3',&lt;br /&gt;
				beta3 = 'bbb3',&lt;br /&gt;
				c3 = 12345,&lt;br /&gt;
				fruit = fruit,&lt;br /&gt;
				[fruit] = 'fruit',&lt;br /&gt;
			},&lt;br /&gt;
		},&lt;br /&gt;
		z = 'zoo',&lt;br /&gt;
	}&lt;br /&gt;
	testcase.testcase = testcase&lt;br /&gt;
	testcase.data.me = testcase.data&lt;br /&gt;
	testcase.data.data2.me = testcase&lt;br /&gt;
	testcase.data.data2.fruit.back = testcase.data&lt;br /&gt;
	setmetatable(testcase.data, {&lt;br /&gt;
		__index = function (self, key) return type(key) == 'string' and #key or nil end,&lt;br /&gt;
		__tostring = function (self) return tostring(#self) end,&lt;br /&gt;
	})&lt;br /&gt;
	if item == 'return table' then&lt;br /&gt;
		return testcase&lt;br /&gt;
	end&lt;br /&gt;
	return dumper(testcase, 'testcase', frame.args.indent)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function execute(frame)&lt;br /&gt;
	-- Return a dump of the result from executing {{#invoke:dump|execute|EXPRESSION}}.&lt;br /&gt;
	-- In general that is not possible in Scribunto so this has built-in code&lt;br /&gt;
	-- to parse some expressions of interest.&lt;br /&gt;
	-- The primary aim is to test the result of calling a Wikidata function&lt;br /&gt;
	-- while previewing an edit in an article.&lt;br /&gt;
	-- Examples of EXPRESSION:&lt;br /&gt;
	--   mw.wikibase.getEntityIdForCurrentPage()&lt;br /&gt;
	--   mw.wikibase.getBestStatements('Q868', 'P214')&lt;br /&gt;
	--   mw.wikibase.getBestStatements(Q868, P214)       -- also accepted&lt;br /&gt;
	--   mw.wikibase.getEntity():getDescription('de')&lt;br /&gt;
	--   mw.wikibase.getEntity('Q868'):getDescription('de')&lt;br /&gt;
	-- getEntityObject is an alias for getEntity.&lt;br /&gt;
	-- Using the following gives an &amp;quot;out of memory&amp;quot; error presumably because&lt;br /&gt;
	-- the result is a table with a metatable that dump repeatedly expands.&lt;br /&gt;
	--   mw.title.getCurrentTitle()&lt;br /&gt;
	local function params(ptext, first)&lt;br /&gt;
		local p = { first }&lt;br /&gt;
		for item in (ptext .. ','):gmatch('(%S.-)%s*,') do&lt;br /&gt;
			-- Remove any quotes around each parameter because it is already a string.&lt;br /&gt;
			local _, s = item:match([[^%s*(['&amp;quot;])(.*)%1%s*$]])&lt;br /&gt;
			table.insert(p, s or tonumber(item) or item)&lt;br /&gt;
		end&lt;br /&gt;
		return unpack(p)&lt;br /&gt;
	end&lt;br /&gt;
	local expression = frame.args[1] or ''&lt;br /&gt;
	local text = expression:match('^%s*mw(%..-)%s*$')&lt;br /&gt;
	if not text then&lt;br /&gt;
		return 'Expression not recognized: &amp;quot;' .. expression .. '&amp;quot;'&lt;br /&gt;
	end&lt;br /&gt;
	-- Look for a supported expression of form 'mw.a.b(c):d.e(f)'.&lt;br /&gt;
	local entity&lt;br /&gt;
	local object = mw&lt;br /&gt;
	local item, ptext, rest = text:match('^%.wikibase%.(%w+)%s*%((.*)%):(.*)$')&lt;br /&gt;
	if item == 'getEntity' or item == 'getEntityObject' then&lt;br /&gt;
		entity = mw.wikibase.getEntity(params(ptext))&lt;br /&gt;
		if not entity then&lt;br /&gt;
			return 'No entity found for (' .. ptext .. ')'&lt;br /&gt;
		end&lt;br /&gt;
		object = entity&lt;br /&gt;
		text = '.' .. rest  -- treat ':' as '.'&lt;br /&gt;
	end&lt;br /&gt;
	local upto = 1&lt;br /&gt;
	for i1, item, i2 in text:gmatch('()%.(%w+)()') do&lt;br /&gt;
		if i1 == upto and type(object) == 'table' then&lt;br /&gt;
			object = object[item]&lt;br /&gt;
		else&lt;br /&gt;
			object = nil&lt;br /&gt;
		end&lt;br /&gt;
		if object == nil then&lt;br /&gt;
			return 'Invalid item &amp;quot;' .. item .. '&amp;quot;'&lt;br /&gt;
		end&lt;br /&gt;
		if type(object) == 'function' then&lt;br /&gt;
			if text:sub(i2, i2 + 1) == '()' then&lt;br /&gt;
				object = object()&lt;br /&gt;
				i2 = i2 + 2&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		upto = i2&lt;br /&gt;
	end&lt;br /&gt;
	local parm = text:sub(upto):match('^%((.*)%)%s*$')&lt;br /&gt;
	if parm then&lt;br /&gt;
		object = object(params(parm, entity))&lt;br /&gt;
	end&lt;br /&gt;
	return dumper(object, expression)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function dumpargs(frame)&lt;br /&gt;
	-- Return text dump of frame.args.&lt;br /&gt;
	-- {{#invoke:dump|args|&amp;lt;ref&amp;gt;Example&amp;lt;/ref&amp;gt;}} → display ref strip marker&lt;br /&gt;
	local control = {&lt;br /&gt;
		autoname = function (var) return tostring(var) end,  -- should not be called since keys should be numbers or strings&lt;br /&gt;
	}&lt;br /&gt;
	local lines = Collection.new()&lt;br /&gt;
	for key, keyrep in iterkeys(frame.args, control) do&lt;br /&gt;
		lines:add(keyrep .. ' = &amp;lt;code&amp;gt;' .. mw.text.nowiki(frame.args[key]) .. '&amp;lt;/code&amp;gt;')&lt;br /&gt;
	end&lt;br /&gt;
	return lines:join('&amp;lt;br&amp;gt;\n')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parameters(frame)&lt;br /&gt;
	-- Return text dump of args and parent args from frame.&lt;br /&gt;
	-- This is for debugging a module to show what parameters it received.&lt;br /&gt;
	local control = {&lt;br /&gt;
		autoname = function (var) return tostring(var) end,  -- should not be called since keys should be numbers or strings&lt;br /&gt;
	}&lt;br /&gt;
	local lines = Collection.new()&lt;br /&gt;
	lines:add('')&lt;br /&gt;
	for _, f in ipairs({ frame, frame:getParent() }) do&lt;br /&gt;
		lines:add('[[' .. f:getTitle() .. ']]')&lt;br /&gt;
		for key, keyrep in iterkeys(f.args, control) do&lt;br /&gt;
			lines:add('&amp;amp;nbsp;&amp;amp;nbsp;' .. mw.text.nowiki(keyrep .. '=' .. f.args[key]))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	lines:add('')&lt;br /&gt;
	return lines:join('&amp;lt;br&amp;gt;\n')&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function wikidata(frame)&lt;br /&gt;
	local item = frame.args[1]&lt;br /&gt;
	if item then&lt;br /&gt;
		local id = item:match('^%s*([PQ]%d+)%s*$')&lt;br /&gt;
		if id then&lt;br /&gt;
			local entity = mw.wikibase.getEntity(id)&lt;br /&gt;
			return dumper(entity, id, frame.args.indent)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return 'Parameter should be a Wikidata identifier such as P2386 or Q833639'&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local builtins = {&lt;br /&gt;
	-- Handle preview of wikitext like {{#invoke|dump|TEXT}}&lt;br /&gt;
	-- where TEXT is a built-in value that can be dumped.&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		local result&lt;br /&gt;
		local function caller()&lt;br /&gt;
			return result&lt;br /&gt;
		end&lt;br /&gt;
		if type(key) == 'string' then&lt;br /&gt;
			local title = key:match('^%s*[\'&amp;quot;]?(.*%.tab)[\'&amp;quot;]?%s*$')&lt;br /&gt;
			if title then&lt;br /&gt;
				-- Assume structured data from Commons at [[c:Data:&amp;lt;title&amp;gt;]].&lt;br /&gt;
				if title:match('^[Dd]ata:') then&lt;br /&gt;
					title = title:sub(6)&lt;br /&gt;
				end&lt;br /&gt;
				local data = mw.ext.data.get(title)  -- false if page does not exist&lt;br /&gt;
				result = dumper(data, '[[c:Data:' .. title .. ']]')&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		result = result or ('UNKNOWN: ' .. tostring(key))&lt;br /&gt;
		return caller&lt;br /&gt;
	end&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return setmetatable({&lt;br /&gt;
	args = dumpargs,&lt;br /&gt;
	_dump = dumper,&lt;br /&gt;
	_dumphtml = _dumphtml,&lt;br /&gt;
	dumphtml = dumphtml,&lt;br /&gt;
	execute = execute,&lt;br /&gt;
	parameters = parameters,&lt;br /&gt;
	testcase = dump_testcase,&lt;br /&gt;
	wikidata = wikidata,&lt;br /&gt;
}, builtins)&lt;/div&gt;</summary>
		<author><name>Zoran</name></author>
	</entry>
</feed>