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

Class decorator version of renpy.register_statement #4846

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion renpy/exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def renpy_pure(fn):
import renpy.audio.sound as sound
import renpy.audio.music as music

from renpy.statements import register as register_statement
from renpy.statements import register as register_statement, register_decorator
from renpy.text.extras import check_text_tags

from renpy.memory import profile_memory, diff_memory, profile_rollback
Expand Down
59 changes: 59 additions & 0 deletions renpy/statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,65 @@ def parse_data(l):

parsers.add(name, parse_data)

# import inspect # only works in py3
# register_params = frozenset(inspect.signature(register).parameters) - {"name", "parse", "execute"}
register_params = frozenset((
# "name", # special-cased
# "parse", # special-cased
"lint",
# "execute", # special-cased
"predict",
"next",
"scry",
"block",
"init",
"translatable",
"execute_init",
"init_priority",
"label",
"warp",
"translation_strings",
"force_begin_rollback",
"post_execute",
"post_label",
"predict_all",
"predict_next",
"execute_default",
"reachable",
))
def register_decorator(cls):
"""
:doc: statement_register decorator
:args:

A class decorator which registers a new statement.

The name of the statement will be the class name unless a ``name``
class attribute is present, which should be a string.

The `parse` parameter to :func:`renpy.register_statement` should
either be the class constructor itself, or a method named ``parse``
(likely a class method or static method) returning an instance of
the class.

For the `execute` parameter, Ren'Py will look for a method named
``execute`` on the class, or if it is not found, will use the class's
``__call__`` method to call like a function the object created by `parse`.

All other parameters to :func:`renpy.register_statement` should be set as
class attributes or methods with the same name.
"""
name = getattr(cls, "name", cls.__name__)
parse = getattr(cls, "parse", cls)
execute = getattr(cls, "execute", None) or cls.__call__
register(
name,
parse=parse,
execute=execute,
**{k:getattr(cls, k) for k in register_params.intersection(vars(cls))}
)
return cls


def parse(node, line, subblock):
"""
Expand Down