<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mediawiki3d.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ALua_class</id>
	<title>Module:Lua class - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mediawiki3d.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ALua_class"/>
	<link rel="alternate" type="text/html" href="https://mediawiki3d.org/index.php?title=Module:Lua_class&amp;action=history"/>
	<updated>2026-04-26T22:29:33Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://mediawiki3d.org/index.php?title=Module:Lua_class&amp;diff=2744&amp;oldid=prev</id>
		<title>OpenDEM 1: 1 revision imported from :wikipedia:en:Module:Lua_class</title>
		<link rel="alternate" type="text/html" href="https://mediawiki3d.org/index.php?title=Module:Lua_class&amp;diff=2744&amp;oldid=prev"/>
		<updated>2025-08-16T17:02:40Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported from &lt;a href=&quot;https://en.wikipedia.org/wiki/en:Module:Lua_class&quot; class=&quot;extiw&quot; title=&quot;wikipedia:en:Module:Lua class&quot;&gt;wikipedia:en:Module:Lua_class&lt;/a&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:02, 16 August 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key wiki3d:diff:1.41:old-2743:rev-2744 --&gt;
&lt;/table&gt;</summary>
		<author><name>OpenDEM 1</name></author>
	</entry>
	<entry>
		<id>https://mediawiki3d.org/index.php?title=Module:Lua_class&amp;diff=2743&amp;oldid=prev</id>
		<title>wikipedia:en&gt;Pppery: Changed protection settings for &quot;Module:Lua class&quot;: High-risk template or module ([Edit=Require template editor access] (indefinite))</title>
		<link rel="alternate" type="text/html" href="https://mediawiki3d.org/index.php?title=Module:Lua_class&amp;diff=2743&amp;oldid=prev"/>
		<updated>2025-08-11T16:03:29Z</updated>

		<summary type="html">&lt;p&gt;Changed protection settings for &amp;quot;&lt;a href=&quot;/index.php/Module:Lua_class&quot; title=&quot;Module:Lua class&quot;&gt;Module:Lua class&lt;/a&gt;&amp;quot;: &lt;a href=&quot;/index.php?title=WP:High-risk_templates&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;WP:High-risk templates (page does not exist)&quot;&gt;High-risk template or module&lt;/a&gt; ([Edit=Require template editor access] (indefinite))&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local libraryUtil = require(&amp;#039;libraryUtil&amp;#039;) -- overridden for new types and exceptions&lt;br /&gt;
local warn = require(&amp;#039;Module:Warning&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local mode_mt = {__mode=&amp;#039;k&amp;#039;}&lt;br /&gt;
local _classes, _instances = {}, {} -- registry mapping all private classes and instances to their internal counterparts&lt;br /&gt;
setmetatable(_classes, mode_mt); setmetatable(_instances, mode_mt)&lt;br /&gt;
local classes, instances = {}, {} -- same but public -&amp;gt; private&lt;br /&gt;
setmetatable(classes, mode_mt); setmetatable(instances, mode_mt)&lt;br /&gt;
local inst_private_mts, inst_public_mts = {}, {} -- for each class since they are mostly immutable&lt;br /&gt;
&lt;br /&gt;
local una_metamethods = {__ipairs=1, __pairs=1, __tostring=1, __unm=1}&lt;br /&gt;
local bin_metamethods = {__add=1, __concat=1, __div=1, __eq=1, __le=1, __lt=1, __mod=1, __mul=1, __pow=1, __sub=1}&lt;br /&gt;
local oth_metamethods = {__call=1, __index=1, __newindex=1, __init=1}&lt;br /&gt;
local not_metamethods = {__name=1, __bases=1, __methods=1, __classmethods=1, __staticmethods=1, __normalmethods=1, __slots=1, __protected=1}&lt;br /&gt;
	-- __class and __hash&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function objtostr(obj)&lt;br /&gt;
	local copy = {}&lt;br /&gt;
	for key, val in pairs(obj) do&lt;br /&gt;
		copy[key] = type(val) == &amp;#039;function&amp;#039; and &amp;#039;function&amp;#039; or val&lt;br /&gt;
	end&lt;br /&gt;
	return mw.text.jsonEncode(copy, mw.text.JSON_PRETTY)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local inst_mt = {&lt;br /&gt;
	__index = function (self, key)&lt;br /&gt;
		if tonumber(key) or key == &amp;#039;hash&amp;#039; or key == &amp;#039;__hash&amp;#039; then -- don&amp;#039;t search numeric keys in classes and hash isn&amp;#039;t inheritable&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
		return self.__class[key] -- key could be invalid here without issues as __index(cls_private, key) would handle it&lt;br /&gt;
	end,&lt;br /&gt;
	__tostring = objtostr--&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function private_read(self_private, key)&lt;br /&gt;
	return _instances[self_private][key] -- instance should be clean of invalid keys so that __index(cls_private, key) handles them&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function private_read_custom(self_private, key)&lt;br /&gt;
	if not_metamethods[key] then&lt;br /&gt;
		error((&amp;quot;AttributeError: unauthorized read attempt of internal &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
	end&lt;br /&gt;
	local self = _instances[self_private]&lt;br /&gt;
	local value = self.__class.__index(self_private, key) -- custom __index can handle invalid keys&lt;br /&gt;
	if value == nil then&lt;br /&gt;
		return self[key] -- same reason of private_read for not checking key validity&lt;br /&gt;
	end&lt;br /&gt;
	return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function private_write(self_private, key, value)&lt;br /&gt;
	libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;, &amp;#039;number&amp;#039;})&lt;br /&gt;
	local self = _instances[self_private]&lt;br /&gt;
	if type(key) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		local cls = _classes[self.__class]&lt;br /&gt;
		if cls.__normalmethods[key] or key:sub(1,2) == &amp;#039;__&amp;#039; and key ~= &amp;#039;__hash&amp;#039; then&lt;br /&gt;
			error((&amp;quot;AttributeError: forbidden write attempt {%s: %s} to immutable method or invalid key&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		elseif key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
			error((&amp;quot;AttributeError: invalid attribute name &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
		elseif key == &amp;#039;__hash&amp;#039; and self.__hash ~= nil then&lt;br /&gt;
			error(&amp;quot;AttributeError: forbidden update attempt to immutable __hash&amp;quot;, 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	self[key] = value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function private_write_custom(self_private, key, value)&lt;br /&gt;
	local self = _instances[self_private]&lt;br /&gt;
	local cls = _classes[self.__class]&lt;br /&gt;
	local keyType = type(key)&lt;br /&gt;
	if keyType == &amp;#039;string&amp;#039; and (cls.__normalmethods[key] or key:sub(1,2) == &amp;#039;__&amp;#039; and key ~= &amp;#039;__hash&amp;#039;) then&lt;br /&gt;
		error((&amp;quot;AttributeError: forbidden write attempt {%s: %s} to immutable method or invalid key&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
	end&lt;br /&gt;
	if cls.__newindex(self_private, key, value) == false then -- custom __newindex can handle invalid keys&lt;br /&gt;
		libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;, &amp;#039;number&amp;#039;})&lt;br /&gt;
		if keyType == &amp;#039;string&amp;#039; then&lt;br /&gt;
			if key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
				error((&amp;quot;AttributeError: invalid attribute name &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif key == &amp;#039;__hash&amp;#039; and self.__hash ~= nil then&lt;br /&gt;
				error(&amp;quot;AttributeError: forbidden update attempt to immutable __hash&amp;quot;, 2)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		self[key] = value&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function public_read(self_public, key)&lt;br /&gt;
	if type(key) == &amp;#039;string&amp;#039; and key:sub(1,1) == &amp;#039;_&amp;#039; then&lt;br /&gt;
		error((&amp;quot;AttributeError: unauthorized read attempt of nonpublic &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
	end&lt;br /&gt;
	return _instances[instances[self_public]][key] -- same reason of private_read...&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function public_read_custom(self_public, key)&lt;br /&gt;
	if type(key) == &amp;#039;string&amp;#039; and key:sub(1,1) == &amp;#039;_&amp;#039; then&lt;br /&gt;
		error((&amp;quot;AttributeError: unauthorized read attempt of nonpublic &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
	end&lt;br /&gt;
	local self = _instances[instances[self_public]]&lt;br /&gt;
	local value = self.__class.__index(instances[self_public], key)&lt;br /&gt;
	if value == nil then&lt;br /&gt;
		return self[key] -- same reason of private_read...&lt;br /&gt;
	end&lt;br /&gt;
	return value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function public_write(self_public, key, value)&lt;br /&gt;
	local self = _instances[instances[self_public]]&lt;br /&gt;
	local cls = _classes[self.__class]&lt;br /&gt;
	if type(key) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		if key:sub(1,1) == &amp;#039;_&amp;#039; then&lt;br /&gt;
			error((&amp;quot;AttributeError: unauthorized write attempt of nonpublic {%s: %s}&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		elseif cls.__normalmethods[key] then&lt;br /&gt;
			error((&amp;quot;AttributeError: forbidden write attempt {%s: %s} to immutable method&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if self[key] == nil and not cls.__slots[key] then -- if instance and __slots are valid, no danger of creating invalid attributes&lt;br /&gt;
		libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;, &amp;#039;number&amp;#039;}) -- otherwise error message would not make sense&lt;br /&gt;
		error((&amp;quot;AttributeError: public attribute creation attempt {%s: %s} not expected by __slots&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
	end&lt;br /&gt;
	self[key] = value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function public_write_custom(self_public, key, value)&lt;br /&gt;
	local self = _instances[instances[self_public]]&lt;br /&gt;
	local cls = _classes[self.__class]&lt;br /&gt;
	if type(key) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		if key:sub(1,1) == &amp;#039;_&amp;#039; then&lt;br /&gt;
			error((&amp;quot;AttributeError: unauthorized write attempt of nonpublic {%s: %s}&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		elseif cls.__normalmethods[key] then&lt;br /&gt;
			error((&amp;quot;AttributeError: forbidden write attempt {%s: %s} to immutable method&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if cls.__newindex(instances[self_public], key, value) == false then&lt;br /&gt;
		if self[key] == nil and not cls.__slots[key] then&lt;br /&gt;
			libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;, &amp;#039;number&amp;#039;}) -- otherwise error message...&lt;br /&gt;
			error((&amp;quot;AttributeError: public attribute creation attempt {%s: %s} not expected by __slots&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		end&lt;br /&gt;
		self[key] = value&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function constructor(wrapper, ...)&lt;br /&gt;
	if select(&amp;#039;#&amp;#039;, ...) ~= 1 or type(...) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		error(&amp;quot;SyntaxError: incorrect instance constructor syntax, should be: Class{arg1, arg2..., kw1=kwarg1, kw2=kwarg2...}&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	local self = {} -- __new&lt;br /&gt;
	local cls_private = classes[wrapper] or wrapper&lt;br /&gt;
	self.__class = cls_private&lt;br /&gt;
	setmetatable(self, inst_mt)&lt;br /&gt;
&lt;br /&gt;
	local self_private = {} -- wrapper&lt;br /&gt;
	local cls = _classes[cls_private]&lt;br /&gt;
&lt;br /&gt;
	local mt = inst_private_mts[cls]&lt;br /&gt;
	if not mt then&lt;br /&gt;
		mt = {}&lt;br /&gt;
		mt.__index = cls.__index and private_read_custom or private_read&lt;br /&gt;
		mt.__newindex = cls.__newindex and private_write_custom or private_write&lt;br /&gt;
		for key in pairs(una_metamethods) do&lt;br /&gt;
			mt[key] = cls[key]&lt;br /&gt;
		end&lt;br /&gt;
		mt.__call = cls.__call&lt;br /&gt;
		mt.__metatable = &amp;quot;unauthorized access attempt of wrapper object metatable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
		inst_private_mts[cls] = mt&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	setmetatable(self_private, mt)&lt;br /&gt;
	_instances[self_private] = self&lt;br /&gt;
&lt;br /&gt;
	local __init = cls.__init&lt;br /&gt;
	if __init and __init(self_private, ...) then&lt;br /&gt;
		error(&amp;quot;TypeError: __init must not return a var-list&amp;quot;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for key in pairs(cls.__methods) do&lt;br /&gt;
		local func = cls[key] -- index once to save time in future calls&lt;br /&gt;
		self[key] = function (...) return func(self_private, ...) end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if cls._hash then -- not inheritable&lt;br /&gt;
		self.hash = function () return cls._hash(self_private) end&lt;br /&gt;
		self.hash() -- construction of self is finalized at this point, so immutable hash can be safely set&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local self_public = {}&lt;br /&gt;
&lt;br /&gt;
	mt = inst_public_mts[cls]&lt;br /&gt;
	if not mt then&lt;br /&gt;
		mt = {}&lt;br /&gt;
		mt.__index = cls.__index and public_read_custom or public_read&lt;br /&gt;
		mt.__newindex = cls.__newindex and public_write_custom or public_write&lt;br /&gt;
		for key in pairs(una_metamethods) do&lt;br /&gt;
			if cls[key] then&lt;br /&gt;
				local func = cls[key]&lt;br /&gt;
				mt[key] = function (a) return func(instances[a]) end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for key in pairs(bin_metamethods) do&lt;br /&gt;
			if cls[key] then&lt;br /&gt;
				local func = cls[key]&lt;br /&gt;
				mt[key] = function (a, b) return func(instances[a], instances[b]) end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if cls.__call then&lt;br /&gt;
			local func = cls.__call&lt;br /&gt;
			mt.__call = function (self_public, ...) return func(instances[self_public], ...) end&lt;br /&gt;
		end&lt;br /&gt;
		mt.__metatable = &amp;quot;unauthorized access attempt of wrapper object metatable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
		inst_public_mts[cls] = mt&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	setmetatable(self_public, mt)&lt;br /&gt;
	instances[self_public] = self_private&lt;br /&gt;
	return self_public, not classes[wrapper] and self_private or nil -- so that constructions in private scopes have access to private instances&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function multi_inheritance(cls, key)&lt;br /&gt;
	for _, base in ipairs(cls.__bases) do&lt;br /&gt;
		if key:sub(1,1) ~= &amp;#039;_&amp;#039; or base.__protected[key] or key:sub(1,2) == &amp;#039;__&amp;#039; and key ~= &amp;#039;__name&amp;#039; and key ~= &amp;#039;__hash&amp;#039; then&lt;br /&gt;
			local value = base[key]&lt;br /&gt;
			if value ~= nil then&lt;br /&gt;
				return value&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local cls_mt = {&lt;br /&gt;
	__index = multi_inheritance,&lt;br /&gt;
	__tostring = objtostr--&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local cls_private_mt = {&lt;br /&gt;
	__call = constructor,&lt;br /&gt;
	__index = function (cls_private, key)&lt;br /&gt;
		if type(key) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
			warn((&amp;quot;AttributeWarning: index &amp;#039;%s&amp;#039; type should be string, %s given&amp;quot;):format(tostring(key), type(key)), 2)&lt;br /&gt;
		elseif not_metamethods[key] then&lt;br /&gt;
			error((&amp;quot;AttributeError: unauthorized read attempt of internal &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
		elseif key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
			warn((&amp;quot;AttributeWarning: index &amp;#039;%s&amp;#039; should be a valid Lua name&amp;quot;):format(key), 2)&lt;br /&gt;
		end&lt;br /&gt;
		local cls = _classes[cls_private]&lt;br /&gt;
		local value = cls[key]&lt;br /&gt;
		if not cls.__slots[key] then&lt;br /&gt;
			local valueType = type(value)&lt;br /&gt;
			if valueType == &amp;#039;table&amp;#039; then&lt;br /&gt;
				return mw.clone(value) -- because class attributes are immutable by default&lt;br /&gt;
			elseif valueType == &amp;#039;set&amp;#039; then --should list be clone or deep copy?&lt;br /&gt;
				return value.copy()&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return value&lt;br /&gt;
	end,&lt;br /&gt;
	__newindex = function (cls_private, key, value)&lt;br /&gt;
		local cls = _classes[cls_private]&lt;br /&gt;
		if not cls.__slots[key] and key ~= &amp;#039;__hash&amp;#039; then -- __slots should be valid, so no need to check key validity before&lt;br /&gt;
			libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;}) -- otherwise error message would not make sense&lt;br /&gt;
			error((&amp;quot;AttributeError: write attempt {%s: %s} not expected by __slots&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
		elseif key == &amp;#039;__hash&amp;#039; and cls.__hash ~= nil then&lt;br /&gt;
			error(&amp;quot;AttributeError: forbidden update attempt to immutable __hash&amp;quot;, 2)&lt;br /&gt;
		end&lt;br /&gt;
		cls[key] = value&lt;br /&gt;
	end,&lt;br /&gt;
	__metatable = &amp;quot;unauthorized access attempt of wrapper object metatable&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local cls_public_mt = {&lt;br /&gt;
	__call = constructor,&lt;br /&gt;
	__index = function (cls_public, key)&lt;br /&gt;
		if type(key) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
			warn((&amp;quot;AttributeWarning: index &amp;#039;%s&amp;#039; type should be string, %s given&amp;quot;):format(tostring(key), type(key)), 2)&lt;br /&gt;
		elseif key:sub(1,1) == &amp;#039;_&amp;#039; then&lt;br /&gt;
			error((&amp;quot;AttributeError: unauthorized read attempt of nonpublic &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
		elseif key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
			warn((&amp;quot;AttributeWarning: index &amp;#039;%s&amp;#039; should be a valid Lua name&amp;quot;):format(key), 2)&lt;br /&gt;
		end&lt;br /&gt;
		local value = _classes[classes[cls_public]][key]&lt;br /&gt;
		local valueType = type(value)&lt;br /&gt;
		if valueType == &amp;#039;table&amp;#039; then&lt;br /&gt;
			return mw.clone(value) -- all class attributes are immutable in the public scope&lt;br /&gt;
		elseif valueType == &amp;#039;set&amp;#039; then&lt;br /&gt;
			return value.copy()&lt;br /&gt;
		end&lt;br /&gt;
		return value&lt;br /&gt;
	end,&lt;br /&gt;
	__newindex = function (cls_public, key, value)&lt;br /&gt;
		libraryUtil.checkTypeMultiForIndex(key, {&amp;#039;string&amp;#039;}) -- otherwise error message...&lt;br /&gt;
		error((&amp;quot;AttributeError: forbidden write attempt of {%s: %s}; a class is immutable in public scope&amp;quot;):format(key, tostring(value)), 2)&lt;br /&gt;
	end,&lt;br /&gt;
	__metatable = &amp;quot;unauthorized access attempt of wrapper object metatable&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function default_hash(obj_private)&lt;br /&gt;
	if obj_private.__hash == nil then -- not inheritable&lt;br /&gt;
		obj_private.__hash = tonumber(&amp;#039;0x&amp;#039; .. mw.hash.hashValue(&amp;#039;fnv1a32&amp;#039;, tostring(os.time() + math.random())))&lt;br /&gt;
	end&lt;br /&gt;
	return obj_private.__hash&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function class(...)&lt;br /&gt;
	local args = {...}&lt;br /&gt;
	local cls = {} -- internal&lt;br /&gt;
&lt;br /&gt;
	local idx&lt;br /&gt;
	if type(args[1]) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		local __name = args[1]&lt;br /&gt;
		if __name:find(&amp;#039;%W&amp;#039;) or __name:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
			error((&amp;quot;ValueError: class &amp;#039;%s&amp;#039; must be a valid Lua name without &amp;#039;_&amp;#039;s&amp;quot;):format(__name), 2)&lt;br /&gt;
		end&lt;br /&gt;
		cls.__name = __name&lt;br /&gt;
		idx = 2&lt;br /&gt;
	else&lt;br /&gt;
		idx = 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__bases = {}&lt;br /&gt;
	for i = idx, #args-1 do&lt;br /&gt;
		libraryUtil.checkType(&amp;#039;class&amp;#039;, i, args[i], &amp;#039;class&amp;#039;)&lt;br /&gt;
		cls.__bases[#cls.__bases+1] = _classes[classes[args[i]]]&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable(cls, cls_mt)&lt;br /&gt;
&lt;br /&gt;
	local kwargs = args[#args]&lt;br /&gt;
	libraryUtil.checkType(&amp;#039;class&amp;#039;, #args, kwargs, &amp;#039;table&amp;#039;)&lt;br /&gt;
	if kwargs.__name ~= nil or kwargs.__bases ~= nil then&lt;br /&gt;
		error(&amp;quot;ValueError: __name and unpacked __bases must be passed as optional first args to &amp;#039;class&amp;#039;&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__slots = {}&lt;br /&gt;
	local mt = {&lt;br /&gt;
		__index = function (__slots, key) -- multi_inheritance&lt;br /&gt;
			for _, base in ipairs(cls.__bases) do&lt;br /&gt;
				if (key:sub(1,1) ~= &amp;#039;_&amp;#039; or base.__protected[key]) and base.__slots[key] then&lt;br /&gt;
					return true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	}&lt;br /&gt;
	setmetatable(cls.__slots, mt)&lt;br /&gt;
	if kwargs.__slots ~= nil then&lt;br /&gt;
		libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, &amp;#039;__slots&amp;#039;, kwargs.__slots, &amp;#039;table&amp;#039;)&lt;br /&gt;
		for i, slot in ipairs(kwargs.__slots) do&lt;br /&gt;
			libraryUtil.checkType(&amp;#039;__slots&amp;#039;, i, slot, &amp;#039;string&amp;#039;)&lt;br /&gt;
			if slot:find(&amp;#039;[^_%w]&amp;#039;) or slot:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
				error((&amp;quot;ValueError: invalid slot name &amp;#039;%s&amp;#039;&amp;quot;):format(slot), 2)&lt;br /&gt;
			elseif slot:sub(1,2) == &amp;#039;__&amp;#039; then&lt;br /&gt;
				error((&amp;quot;ValueError: slot &amp;#039;%s&amp;#039; has forbidden namespace&amp;quot;):format(slot), 2)&lt;br /&gt;
			elseif rawget(cls.__slots, slot) then&lt;br /&gt;
				warn((&amp;quot;ValueWarning: duplicated slot &amp;#039;%s&amp;#039;&amp;quot;):format(slot), 2)&lt;br /&gt;
			elseif kwargs[slot] ~= nil or cls.__slots[slot] then&lt;br /&gt;
				error((&amp;quot;ValueError: slot &amp;#039;%s&amp;#039; is predefined in class or allocated in __slots of bases&amp;quot;):format(slot), 2)&lt;br /&gt;
			end&lt;br /&gt;
			cls.__slots[slot] = true&lt;br /&gt;
		end&lt;br /&gt;
		kwargs.__slots = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__protected = {}&lt;br /&gt;
	mt = {&lt;br /&gt;
		__index = function (__protected, key)&lt;br /&gt;
			for _, base in ipairs(cls.__bases) do&lt;br /&gt;
				if base.__protected[key] then&lt;br /&gt;
					return true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	}&lt;br /&gt;
	setmetatable(cls.__protected, mt)&lt;br /&gt;
	if kwargs.__protected ~= nil then&lt;br /&gt;
		libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, &amp;#039;__protected&amp;#039;, kwargs.__protected, &amp;#039;table&amp;#039;)&lt;br /&gt;
		for i, key in ipairs(kwargs.__protected) do&lt;br /&gt;
			libraryUtil.checkType(&amp;#039;__protected&amp;#039;, i, key, &amp;#039;string&amp;#039;)&lt;br /&gt;
			if key:sub(1,1) ~= &amp;#039;_&amp;#039; or key:sub(2,2) == &amp;#039;_&amp;#039; then&lt;br /&gt;
				error((&amp;quot;ValueError: the namespace of &amp;#039;%s&amp;#039; is not manually protectable&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif key == &amp;#039;_hash&amp;#039; then&lt;br /&gt;
				error(&amp;quot;ValueError: forbidden attempt to protect _hash which is not inheritable&amp;quot;, 2)&lt;br /&gt;
			elseif rawget(cls.__protected, key) then&lt;br /&gt;
				warn((&amp;quot;ValueWarning: duplicated &amp;#039;%s&amp;#039; in __protected&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif cls.__protected[key] then&lt;br /&gt;
				error((&amp;quot;ValueError: &amp;#039;%s&amp;#039; is already allocated in __protected of bases&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif kwargs[key] == nil then -- key validity will be checked further ahead&lt;br /&gt;
				error((&amp;quot;ValueError: attempt to protect undefined &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
			end&lt;br /&gt;
			cls.__protected[key] = true&lt;br /&gt;
		end&lt;br /&gt;
		kwargs.__protected = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if kwargs.__methods ~= nil then&lt;br /&gt;
		error(&amp;quot;ValueError: __classmethods and __staticmethods should be passed as optional attributes instead of __methods&amp;quot;, 2)&lt;br /&gt;
	elseif kwargs.hash ~= nil or kwargs.__hash ~= nil then&lt;br /&gt;
		error(&amp;quot;ValueError: forbidden attempt to define hash or __hash which are set internally&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__normalmethods = {} -- used in instance write methods&lt;br /&gt;
	mt = {&lt;br /&gt;
		__index = function (__normalmethods, key)&lt;br /&gt;
			return cls.__methods[key] or cls.__classmethods[key] or cls.__staticmethods[key]&lt;br /&gt;
		end&lt;br /&gt;
	}&lt;br /&gt;
	setmetatable(cls.__normalmethods, mt)&lt;br /&gt;
&lt;br /&gt;
	local cls_private = {} -- wrapper&lt;br /&gt;
	setmetatable(cls_private, cls_private_mt)&lt;br /&gt;
	_classes[cls_private] = cls&lt;br /&gt;
&lt;br /&gt;
	cls.__classmethods = {}&lt;br /&gt;
	mt = {&lt;br /&gt;
		__index = function (__classmethods, key)&lt;br /&gt;
			for _, base in ipairs(cls.__bases) do&lt;br /&gt;
				if (key:sub(1,1) ~= &amp;#039;_&amp;#039; or base.__protected[key]) and base.__classmethods[key] then&lt;br /&gt;
					return true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	}&lt;br /&gt;
	setmetatable(cls.__classmethods, mt)&lt;br /&gt;
	if kwargs.__classmethods ~= nil then&lt;br /&gt;
		libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, &amp;#039;__classmethods&amp;#039;, kwargs.__classmethods, &amp;#039;table&amp;#039;)&lt;br /&gt;
		for i, key in ipairs(kwargs.__classmethods) do&lt;br /&gt;
			libraryUtil.checkType(&amp;#039;__classmethods&amp;#039;, i, key, &amp;#039;string&amp;#039;)&lt;br /&gt;
			if key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
				error((&amp;quot;ValueError: invalid classmethod name &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif key:sub(1,2) == &amp;#039;__&amp;#039; then&lt;br /&gt;
				error((&amp;quot;ValueError: classmethod &amp;#039;%s&amp;#039; has forbidden namespace&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif key == &amp;#039;_hash&amp;#039; then&lt;br /&gt;
				error(&amp;quot;ValueError: invalid classmethod _hash, classes have their own hash classmethod&amp;quot;, 2)&lt;br /&gt;
			elseif rawget(cls.__classmethods, key) then&lt;br /&gt;
				error((&amp;quot;ValueError: duplicated &amp;#039;%s&amp;#039; in __classmethods&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif not cls.__classmethods[key] and cls[key] ~= nil then&lt;br /&gt;
				error((&amp;quot;ValueError: forbidden attempt to convert &amp;#039;%s&amp;#039; non-classmethod to classmethod&amp;quot;):format(key), 2)&lt;br /&gt;
			end&lt;br /&gt;
			libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, key, kwargs[key], &amp;#039;function&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
			cls.__classmethods[key] = true&lt;br /&gt;
			local func = kwargs[key]&lt;br /&gt;
			cls[key] = function (...) return func(cls_private, ...) end&lt;br /&gt;
			kwargs[key] = nil&lt;br /&gt;
		end&lt;br /&gt;
		kwargs.__classmethods = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__normalmethods.hash = true&lt;br /&gt;
	cls.hash = function () return default_hash(cls_private) end -- classes are always hashable so this is independent from _hash&lt;br /&gt;
	cls.hash()&lt;br /&gt;
&lt;br /&gt;
	-- see https://docs.python.org/3/reference/datamodel.html#object.__hash__&lt;br /&gt;
	if kwargs.__eq == nil then&lt;br /&gt;
		if kwargs._hash then&lt;br /&gt;
			warn(&amp;quot;ValueWarning: _hash is defined but not __eq, which is expected&amp;quot;, 2)&lt;br /&gt;
		elseif kwargs._hash == false then&lt;br /&gt;
			kwargs._hash = nil&lt;br /&gt;
		else&lt;br /&gt;
			kwargs._hash = default_hash&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if kwargs._hash ~= nil then&lt;br /&gt;
		libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, &amp;#039;_hash&amp;#039;, kwargs._hash, &amp;#039;function&amp;#039;)&lt;br /&gt;
		cls.__normalmethods._hash = true&lt;br /&gt;
		cls._hash = kwargs._hash&lt;br /&gt;
		kwargs._hash = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__staticmethods = {}&lt;br /&gt;
	mt = {&lt;br /&gt;
		__index = function (__staticmethods, key)&lt;br /&gt;
			for _, base in ipairs(cls.__bases) do&lt;br /&gt;
				if (key:sub(1,1) ~= &amp;#039;_&amp;#039; or base.__protected[key]) and base.__staticmethods[key] then&lt;br /&gt;
					return true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	}&lt;br /&gt;
	setmetatable(cls.__staticmethods, mt)&lt;br /&gt;
	if kwargs.__staticmethods ~= nil then&lt;br /&gt;
		libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, &amp;#039;__staticmethods&amp;#039;, kwargs.__staticmethods, &amp;#039;table&amp;#039;)&lt;br /&gt;
		for i, key in ipairs(kwargs.__staticmethods) do&lt;br /&gt;
			libraryUtil.checkType(&amp;#039;__staticmethods&amp;#039;, i, key, &amp;#039;string&amp;#039;)&lt;br /&gt;
			if key:sub(1,2) == &amp;#039;__&amp;#039; then&lt;br /&gt;
				error((&amp;quot;ValueError: staticmethod &amp;#039;%s&amp;#039; has forbidden namespace&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif rawget(cls.__staticmethods, key) then&lt;br /&gt;
				warn((&amp;quot;ValueWarning: duplicated staticmethod &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
			elseif not cls.__staticmethods[key] and cls[key] ~= nil then&lt;br /&gt;
				error((&amp;quot;ValueError: forbidden attempt to convert &amp;#039;%s&amp;#039; non-staticmethod to staticmethod&amp;quot;):format(key), 2)&lt;br /&gt;
			end&lt;br /&gt;
			libraryUtil.checkTypeForNamedArg(&amp;#039;class&amp;#039;, key, kwargs[key], &amp;#039;function&amp;#039;)&lt;br /&gt;
			cls.__staticmethods[key] = true&lt;br /&gt;
		end&lt;br /&gt;
		kwargs.__staticmethods = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	cls.__methods = {}&lt;br /&gt;
	for _, base in ipairs(cls.__bases) do&lt;br /&gt;
		for key in pairs(base.__methods) do&lt;br /&gt;
			if key:sub(1,1) ~= &amp;#039;_&amp;#039; or base.__protected[key] then&lt;br /&gt;
				cls.__methods[key] = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local valid = false&lt;br /&gt;
	for key, val in pairs(kwargs) do&lt;br /&gt;
		if type(key) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
			error((&amp;quot;TypeError: invalid attribute name &amp;#039;%s&amp;#039; (string expected, got %s)&amp;quot;):format(tostring(key), type(key)), 2)&lt;br /&gt;
		elseif key:find(&amp;#039;[^_%w]&amp;#039;) or key:find(&amp;#039;^%d&amp;#039;) then&lt;br /&gt;
			error((&amp;quot;ValueError: invalid attribute name &amp;#039;%s&amp;#039;&amp;quot;):format(key), 2)&lt;br /&gt;
		elseif key:sub(1,2) == &amp;#039;__&amp;#039; and not una_metamethods[key] and not bin_metamethods[key] and not oth_metamethods[key] then&lt;br /&gt;
			error((&amp;quot;ValueError: unrecognized metamethod or unauthorized internal attribute {%s: %s}&amp;quot;):format(key, tostring(val)), 2)&lt;br /&gt;
		end&lt;br /&gt;
		cls[key] = val&lt;br /&gt;
		if type(val) == &amp;#039;function&amp;#039; then&lt;br /&gt;
			if not cls.__staticmethods[key] and key:sub(1,2) ~= &amp;#039;__&amp;#039; then -- classmethods and _hash were already removed from kwargs&lt;br /&gt;
				cls.__methods[key] = true&lt;br /&gt;
			end&lt;br /&gt;
			if key ~= &amp;#039;__init&amp;#039; then -- __init does not qualify to a functional/proper class&lt;br /&gt;
				valid = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if not valid then&lt;br /&gt;
		error(&amp;quot;ValueError: a (sub)class must have at least one functional method&amp;quot;, 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local cls_public = {}&lt;br /&gt;
	setmetatable(cls_public, cls_public_mt)&lt;br /&gt;
	classes[cls_public] = cls_private&lt;br /&gt;
	return cls_public, cls_private&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function rissubclass2(class, classinfo)&lt;br /&gt;
	if class == classinfo then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	for _, base in ipairs(class.__bases) do&lt;br /&gt;
		if rissubclass2(base, classinfo) then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function rissubclass1(class, classinfo, parent, level)&lt;br /&gt;
	libraryUtil.checkTypeMulti(parent, 2, classinfo, {&amp;#039;class&amp;#039;, &amp;#039;table&amp;#039;}, level)&lt;br /&gt;
	if classes[classinfo] then&lt;br /&gt;
		return rissubclass2(class, _classes[classes[classinfo]])&lt;br /&gt;
	elseif _classes[classinfo] then&lt;br /&gt;
		return rissubclass2(class, _classes[classinfo])&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, #classinfo do&lt;br /&gt;
		if rissubclass1(class, classinfo[i], parent, level+1) then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function issubclass(class, classinfo)&lt;br /&gt;
	libraryUtil.checkType(&amp;#039;issubclass&amp;#039;, 1, class, &amp;#039;class&amp;#039;)&lt;br /&gt;
	class = classes[class] or class&lt;br /&gt;
	return rissubclass1(_classes[class], classinfo, &amp;#039;issubclass&amp;#039;, 4)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function isinstance(instance, classinfo)&lt;br /&gt;
	if not instances[instance] and not _instances[instance] then -- because named (ClassName) instances would fail with checkType&lt;br /&gt;
		if classinfo == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
		error((&amp;quot;TypeError: bad argument #1 to &amp;#039;isinstance&amp;#039; (instance expected, got %s)&amp;quot;):format(type(instance)), 2)&lt;br /&gt;
	end&lt;br /&gt;
	if classinfo == nil then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	instance = instances[instance] or instance&lt;br /&gt;
	return rissubclass1(_classes[instance.__class], classinfo, &amp;#039;isinstance&amp;#039;, 4)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local _type = type&lt;br /&gt;
type = function (value)&lt;br /&gt;
	local t = _type(value)&lt;br /&gt;
	if t == &amp;#039;table&amp;#039; then&lt;br /&gt;
		if classes[value] or _classes[value] then&lt;br /&gt;
			return &amp;#039;class&amp;#039;&lt;br /&gt;
		elseif instances[value] or _instances[value] then&lt;br /&gt;
			value = instances[value] or value&lt;br /&gt;
			return _classes[value.__class].__name or &amp;#039;instance&amp;#039; -- should __name be directly readable instead?&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return t&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkType = function (name, argIdx, arg, expectType, nilOk, level)&lt;br /&gt;
	if arg == nil and nilOk then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	if type(arg) ~= expectType then&lt;br /&gt;
		error((&amp;quot;TypeError: bad argument #%d to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;):format(argIdx, name, expectType, type(arg)), level or 3)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkTypeMulti = function (name, argIdx, arg, expectTypes, level)&lt;br /&gt;
	local argType = type(arg)&lt;br /&gt;
	for _, expectType in ipairs(expectTypes) do&lt;br /&gt;
		if argType == expectType then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local n = #expectTypes&lt;br /&gt;
	local typeList&lt;br /&gt;
	if n &amp;gt; 1 then&lt;br /&gt;
		typeList = table.concat(expectTypes, &amp;#039;, &amp;#039;, 1, n-1) .. &amp;#039; or &amp;#039; .. expectTypes[n]&lt;br /&gt;
	else&lt;br /&gt;
		typeList = expectTypes[1]&lt;br /&gt;
	end&lt;br /&gt;
	error((&amp;quot;TypeError: bad argument #%d to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;):format(argIdx, name, typeList, type(arg)), level or 3)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkTypeForIndex = function (index, value, expectType, level)&lt;br /&gt;
	if type(value) ~= expectType then&lt;br /&gt;
		error((&amp;quot;TypeError: value for index &amp;#039;%s&amp;#039; must be %s, %s given&amp;quot;):format(index, expectType, type(value)), level or 3)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkTypeMultiForIndex = function (index, expectTypes, level)&lt;br /&gt;
	local indexType = type(index)&lt;br /&gt;
	for _, expectType in ipairs(expectTypes) do&lt;br /&gt;
		if indexType == expectType then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local n = #expectTypes&lt;br /&gt;
	local typeList&lt;br /&gt;
	if n &amp;gt; 1 then&lt;br /&gt;
		typeList = table.concat(expectTypes, &amp;#039;, &amp;#039;, 1, n-1) .. &amp;#039; or &amp;#039; .. expectTypes[n]&lt;br /&gt;
	else&lt;br /&gt;
		typeList = expectTypes[1]&lt;br /&gt;
	end&lt;br /&gt;
	error((&amp;quot;TypeError: index &amp;#039;%s&amp;#039; must be %s, %s given&amp;quot;):format(index, typeList, type(index)), level or 3)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkTypeForNamedArg = function (name, argName, arg, expectType, nilOk, level)&lt;br /&gt;
	if arg == nil and nilOk then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	if type(arg) ~= expectType then&lt;br /&gt;
		error((&amp;quot;TypeError: bad named argument %s to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;):format(argName, name, expectType, type(arg)), level or 3)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
libraryUtil.checkTypeMultiForNamedArg = function (name, argName, arg, expectTypes, level)&lt;br /&gt;
	local argType = type(arg)&lt;br /&gt;
	for _, expectType in ipairs(expectTypes) do&lt;br /&gt;
		if argType == expectType then&lt;br /&gt;
			return&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local n = #expectTypes&lt;br /&gt;
	local typeList&lt;br /&gt;
	if n &amp;gt; 1 then&lt;br /&gt;
		typeList = table.concat(expectTypes, &amp;#039;, &amp;#039;, 1, n-1) .. &amp;#039; or &amp;#039; .. expectTypes[n]&lt;br /&gt;
	else&lt;br /&gt;
		typeList = expectTypes[1]&lt;br /&gt;
	end&lt;br /&gt;
	error((&amp;quot;TypeError: bad named argument %s to &amp;#039;%s&amp;#039; (%s expected, got %s)&amp;quot;):format(argName, name, typeList, type(arg)), level or 3)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function try_parser(...)&lt;br /&gt;
	local args = {...}&lt;br /&gt;
	libraryUtil.checkType(&amp;#039;try&amp;#039;, 1, args[1], &amp;#039;function&amp;#039;, nil, 4)&lt;br /&gt;
	local try_clause = args[1]&lt;br /&gt;
&lt;br /&gt;
	if args[2] ~= &amp;#039;except&amp;#039; then&lt;br /&gt;
		error(&amp;quot;SyntaxError: missing required except clause&amp;quot;, 3)&lt;br /&gt;
	end&lt;br /&gt;
	local except_clauses = {}&lt;br /&gt;
	local i = 3&lt;br /&gt;
	local argType, exceptionTypes = nil, {string=1, table=1}&lt;br /&gt;
	repeat&lt;br /&gt;
		libraryUtil.checkTypeMulti(&amp;#039;try&amp;#039;, i, args[i], {&amp;#039;string&amp;#039;, &amp;#039;table&amp;#039;, &amp;#039;function&amp;#039;}, 4)&lt;br /&gt;
		argType = type(args[i])&lt;br /&gt;
		if exceptionTypes[argType] then&lt;br /&gt;
			libraryUtil.checkType(&amp;#039;try&amp;#039;, i+1, args[i+1], &amp;#039;function&amp;#039;, nil, 4)&lt;br /&gt;
			except_clauses[#except_clauses+1] = {exceptions={}, handler=args[i+1]}&lt;br /&gt;
			if argType == &amp;#039;string&amp;#039; then&lt;br /&gt;
				except_clauses[#except_clauses].exceptions[args[i]] = true&lt;br /&gt;
			else&lt;br /&gt;
				for _, exception in ipairs(args[i]) do&lt;br /&gt;
					if type(exception) ~= &amp;#039;string&amp;#039; then&lt;br /&gt;
						error((&amp;quot;TypeError: invalid exception type in except (string expected, got %s)&amp;quot;):format(type(exception)), 3)&lt;br /&gt;
					end&lt;br /&gt;
					except_clauses[#except_clauses].exceptions[exception] = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			i = i + 3&lt;br /&gt;
		else&lt;br /&gt;
			except_clauses[#except_clauses+1] = {exceptions={}, handler=args[i]}&lt;br /&gt;
			i = i + 2&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	until args[i-1] ~= &amp;#039;except&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	local else_clause, finally_clause&lt;br /&gt;
	if args[i-1] == &amp;#039;except&amp;#039; then&lt;br /&gt;
		error(&amp;quot;SyntaxError: except after except clause without specific exceptions, which should be the last&amp;quot;, 3)&lt;br /&gt;
	elseif args[i-1] == &amp;#039;else&amp;#039; then&lt;br /&gt;
		libraryUtil.checkType(&amp;#039;try&amp;#039;, i, args[i], &amp;#039;function&amp;#039;, nil, 4)&lt;br /&gt;
		else_clause = args[i]&lt;br /&gt;
		i = i + 2&lt;br /&gt;
	end&lt;br /&gt;
	if args[i-1] == &amp;#039;finally&amp;#039; then&lt;br /&gt;
		libraryUtil.checkType(&amp;#039;try&amp;#039;, i, args[i], &amp;#039;function&amp;#039;, nil, 4)&lt;br /&gt;
		finally_clause = args[i]&lt;br /&gt;
		i = i + 2&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if args[i-1] ~= nil then&lt;br /&gt;
		error((&amp;quot;SyntaxError: unexpected arguments #%d–#%d to &amp;#039;try&amp;#039;&amp;quot;):format(i-1, #args), 3)&lt;br /&gt;
	end&lt;br /&gt;
	return try_clause, except_clauses, else_clause, finally_clause&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function try(...)&lt;br /&gt;
	local try_clause, except_clauses, else_clause, finally_clause = try_parser(...)&lt;br /&gt;
&lt;br /&gt;
	local function errhandler(message)&lt;br /&gt;
		local errtype = mw.text.split(message, &amp;#039;:&amp;#039;)[1]&lt;br /&gt;
		local handled = false&lt;br /&gt;
		for _, except in ipairs(except_clauses) do&lt;br /&gt;
			if except.exceptions[errtype] or #except.exceptions == 0 then&lt;br /&gt;
				handled, message = pcall(except.handler)&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		if not handled then&lt;br /&gt;
			return message&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local success, message = xpcall(try_clause, errhandler)&lt;br /&gt;
	if else_clause and success then&lt;br /&gt;
		success, message = pcall(else_clause)&lt;br /&gt;
	end&lt;br /&gt;
	if finally_clause then&lt;br /&gt;
		finally_clause()&lt;br /&gt;
	end&lt;br /&gt;
	if not success and message then&lt;br /&gt;
		error(message, 0) -- what should be the level?&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local classes_proxy, instances_proxy = {}, {}&lt;br /&gt;
&lt;br /&gt;
setmetatable(classes_proxy, {&lt;br /&gt;
	__index = classes, -- create function to limit access only to modules which define the requested classes and testcases pages&lt;br /&gt;
	__newindex = function () error(&amp;quot;KeyError: forbidden write attempt to classes proxy&amp;quot;, 2) end,&lt;br /&gt;
	__metatable = &amp;quot;unauthorized access attempt of classes proxy metatable&amp;quot;&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
setmetatable(instances_proxy, {&lt;br /&gt;
	__index = instances, -- create function to limit access only to testcases pages&lt;br /&gt;
	__newindex = function () error(&amp;quot;KeyError: forbidden write attempt to instances proxy&amp;quot;, 2) end,&lt;br /&gt;
	__metatable = &amp;quot;unauthorized access attempt of instances proxy metatable&amp;quot;&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
return {classes_proxy, instances_proxy}&lt;/div&gt;</summary>
		<author><name>wikipedia:en&gt;Pppery</name></author>
	</entry>
</feed>