Mercurial > prosody-hg
view util/error.lua @ 11148:1dc49accb58e
core.moduleapi: Return resource path from module:get_directory() (API BC)
:get_directory has so far returned the base directory of the current
module source code. This has worked well so far to load resources which
tend to be included in the same directory, but with the plugin installer
using LuaRocks, extra resources (e.g. templates and other assets) these
are saved in a completely different directory.
In be73df6765b9 core.modulemanager gained some code for finding that
directory and saving it in module.resource_path but now the question is
how this should be reflected in the API.
A survey of community modules suggest the vast majority use the
:get_directory method for locating templates and other assets, rather
than the code (which would use module:require instead).
Therefore this commit changes :get_directory to return the resource_path
when available. This should work for most modules.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Fri, 09 Oct 2020 16:37:15 +0200 |
| parents | 5a0ff475ecfd |
| children | f51ed2652602 |
line wrap: on
line source
local id = require "util.id"; -- Library configuration (see configure()) local auto_inject_traceback = false; local display_tracebacks = false; local error_mt = { __name = "error" }; function error_mt:__tostring() if display_tracebacks and self.context.traceback then return ("error<%s:%s:%s:%s>"):format(self.type, self.condition, self.text or "", self.context.traceback); end return ("error<%s:%s:%s>"):format(self.type, self.condition, self.text or ""); end local function is_err(e) return getmetatable(e) == error_mt; end local function configure(opt) if opt.display_tracebacks ~= nil then display_tracebacks = opt.display_tracebacks; end if opt.auto_inject_traceback ~= nil then auto_inject_traceback = opt.auto_inject_traceback; end end -- Do we want any more well-known fields? -- Or could we just copy all fields from `e`? -- Sometimes you want variable details in the `text`, how to handle that? -- Translations? -- Should the `type` be restricted to the stanza error types or free-form? -- What to set `type` to for stream errors or SASL errors? Those don't have a 'type' attr. local function new(e, context, registry, source) local template = registry and registry[e]; if not template then if type(e) == "table" then template = { code = e.code; type = e.type; condition = e.condition; text = e.text; extra = e.extra; }; else template = {}; end end context = context or {}; if auto_inject_traceback then context.traceback = debug.traceback("error stack", 2); end local error_instance = setmetatable({ instance_id = id.short(); type = template.type or "cancel"; condition = template.condition or "undefined-condition"; text = template.text; code = template.code; extra = template.extra; context = context; source = source; }, error_mt); return error_instance; end -- compact --> normal form local function expand_registry(namespace, registry) local mapped = {} for err,template in pairs(registry) do local e = { type = template[1]; condition = template[2]; text = template[3]; }; if namespace and template[4] then e.extra = { namespace = namespace, condition = template[4] }; end mapped[err] = e; end return mapped; end local function init(source, namespace, registry) if type(namespace) == "table" then -- registry can be given as second argument if namespace is either not used registry, namespace = namespace, nil; end local _, protoerr = next(registry, nil); if protoerr and type(next(protoerr)) == "number" then registry = expand_registry(namespace, registry); end return { source = source; registry = registry; new = function (e, context) return new(e, context, registry, source); end; }; end local function coerce(ok, err, ...) if ok or is_err(err) then return ok, err, ...; end local new_err = new({ type = "cancel", condition = "undefined-condition" }, { wrapped_error = err }); return ok, new_err, ...; end local function from_stanza(stanza, context, source) local error_type, condition, text, extra_tag = stanza:get_error(); local error_tag = stanza:get_child("error"); context = context or {}; context.stanza = stanza; context.by = error_tag.attr.by or stanza.attr.from; local uri; if condition == "gone" or condition == "redirect" then uri = error_tag:get_child_text(condition, "urn:ietf:params:xml:ns:xmpp-stanzas"); end return new({ type = error_type or "cancel"; condition = condition or "undefined-condition"; text = text; extra = (extra_tag or uri) and { uri = uri; tag = extra_tag; } or nil; }, context, nil, source); end return { new = new; init = init; coerce = coerce; is_err = is_err; from_stanza = from_stanza; configure = configure; }
