Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

template.name.matches for Scribunto modules #287

Open
BryghtShadow opened this issue Jun 8, 2022 · 2 comments
Open

template.name.matches for Scribunto modules #287

BryghtShadow opened this issue Jun 8, 2022 · 2 comments

Comments

@BryghtShadow
Copy link
Contributor

Would it be possible to add support for matching Scribunto modules that are invoked on a page?

  • Note: An invoked module looks like {{#invoke:Foo|bar}}, which executes the function of the module (currently only Lua); rather than {{Module:Foo}}, which would transclude the content of the module as wikitext.
import mwparserfromhell

code = mwparserfromhell.parse('{{Module:Foo}}')
template = code.filter_templates()[0]
print(template.name)  # 'Module:Foo'
name = str(template.name)
assert template.name.get(0) == name  # ok
assert template.name.matches(name)  # ok

code = mwparserfromhell.parse('{{#invoke:Foo|bar}}')
module = code.filter_templates()[0]
print(module.name)  # '#invoke:Foo'
name = str(module.name)
assert module.name.get(0) == name  # ok
assert module.name.matches(name)  # fail :(

The current workaround I'm using is to copy.deepcopy the name and replace the namespace in the copy:

from copy import deepcopy
import mwparserfromhell

wikitext = '{{#invoke:Foo|bar}}'

# option 1 ("safe")
code = mwparserfromhell.parse(wikitext)
module = code.filter_templates()[0]
if module.name.startswith('#invoke:'):
    name = deepcopy(module.name)
    name.replace('#invoke:', 'Module:') # rename the copy
    has_match = name.matches('Module:Foo')
    print(has_match)  # True
    assert str(module.name) == '#invoke:Foo'  # ok
    assert module.name.get(0) == '#invoke:Foo'  # ok, name is ['#invoke:Foo']

# option 2 ("destructive")
code = mwparserfromhell.parse(wikitext)
module = code.filter_templates()[0]
if module.name.startswith('#invoke:'):
    print(module.name.get(0))  # '#invoke:Foo'
    module.name.set(0, 'Module:Foo')  # temp rename (safe)
    has_match = module.name.matches('Module:Foo')
    module.name.replace('Module:', '#invoke:')  # undo (destructive, see assertion below)
    print(has_match)  # True
    assert str(module.name) == '#invoke:Foo'  # ok
    assert module.name.get(0) == '#invoke:Foo'  # fail, name is ['#', 'invoke:Foo']
@earwig
Copy link
Owner

earwig commented Jun 30, 2022

Thanks for the bug report! (At the very least we should add a distinct node type for module invocations, in the same vein as parser functions, c.f. #10.)

To clarify, the expectation is that both of these would return True? Or only the second one?

code = mwparserfromhell.parse("{{#invoke:Foo}}")
t = code.filter_templates()[0]
t.name.matches("#invoke:Foo")
t.name.matches("Module:Foo")

@BryghtShadow
Copy link
Contributor Author

The distinct node type would allow differentiation between {{Module:Foo}} and {{#invoke:Foo}}, I presume?

I'd expect just the second option to return True. It makes sense in terms of valid namespaces (#invoke: is not valid) and orthodox module usage (transclusions are unorthodox, and the node type should hopefully cover such use cases).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants