Skip to content

Commit

Permalink
Work towards satisfying pylint, part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
wallabra committed Aug 24, 2023
1 parent 50d9b3b commit 558cd65
Show file tree
Hide file tree
Showing 28 changed files with 618 additions and 468 deletions.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-debug-asset.pk3
Binary file not shown.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-debug-code.pk3
Binary file not shown.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-release-asset.pk3
Binary file not shown.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-release-code.pk3
Binary file not shown.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-release-foes-asset.pk3
Binary file not shown.
Binary file modified example/out/ZDWorld-2.13.6-zdw1-release-foes-code.pk3
Binary file not shown.
22 changes: 9 additions & 13 deletions zdcode/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,23 +149,19 @@ def store_collected(self, out_zip: zipfile.ZipFile, target: str, data: bytes):
def assemble(self):
"""Internally assemble a zip file to then store at an output path."""

zips: dict[str, zipfile.ZipFile] = {}
zipfiles = set()

for oname, out in self.bundle.outputs.items():
oname = oname.lower()

zipf = zipfile.ZipFile(out.output, mode="w")
zips[oname] = zipf
zipfiles.add(zipf)
routing = {}

while self.collected:
target, oname, data = self.collected.popleft()
out_zip = zips[oname.lower()]
self.store_collected(out_zip, target, data)
oname = oname.lower()
routing.setdefault(oname, []).append((target, data))

for oname, out in self.bundle.outputs.items():
oname = oname.lower()

for zipf in zips.values():
zipf.close()
with zipfile.ZipFile(out.output, mode="w") as zipf:
for item in routing[oname]:
self.store_collected(zipf, *item)

def scan_dep(self, url: pathlib.Path, target: pathlib.PurePath):
"""Scan for a single dependency."""
Expand Down
55 changes: 36 additions & 19 deletions zdcode/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def _parse_parameter(self, parm, context, name=None):
return self._parse_anonym_macro(*pval, context, name)

def _parse_anonym_macro(self, args, body, context, name=None):
name = name or f"ANONYMMACRO_{self.id.upper()}_{self.num_anonym_macros}"
name = name or f"ANONYMMACRO_{self.identifier.upper()}_{self.num_anonym_macros}"
self.num_anonym_macros += 1

context.macros[name.upper()] = (args, body)
Expand All @@ -167,11 +167,13 @@ def _parse_literal_numeric(self, literal, context):
return float(context.replacements[literal[1].upper()])

raise CompilerError(
f"Cannot get compile-time variable for evaluation, {repr(literal[1])}, in {context.describe()}"
"Cannot get compile-time variable for evaluation, "
f"{repr(literal[1])}, in {context.describe()}"
)

raise CompilerError(
f"Could not parse numeric expression {repr(literal)} at {context.describe()}"
"Could not parse numeric expression "
f"{repr(literal)} at {context.describe()}"
)

def _parse_literal(self, literal, context):
Expand Down Expand Up @@ -239,7 +241,9 @@ def _parse_template_derivation(

if len(template_parms) != len(template.template_parameters):
raise CompilerError(
f"Bad number of template parameters for '{template_name}' in {context.describe()}: expected {len(template.template_parameters)}, got {len(template_parms)}"
f"Bad number of template parameters for '{template_name}' "
f"in {context.describe()}: expected "
f"{len(template.template_parameters)}, got {len(template_parms)}"
)

template_parms = [
Expand Down Expand Up @@ -360,7 +364,8 @@ def _parse_formatted_string(self, cval, context: ZDCodeParseContext):

else:
raise CompilerError(
f"Replacement {pval} not found while formatting string in {context.describe()}"
f"Replacement {pval} not found "
f"while formatting string in {context.describe()}"
)

return "".join(unstringify(x) for x in res)
Expand All @@ -385,7 +390,8 @@ def _parse_replaceable_number(self, cval, context: ZDCodeParseContext):

except ValueError:
raise CompilerError(
f"Invalid repeat count in {context.describe()}: expected valid integer, got {repr(cval)}"
f"Invalid repeat count in {context.describe()}: "
f"expected valid integer, got {repr(cval)}"
)

else:
Expand Down Expand Up @@ -483,7 +489,8 @@ def recurse(modifier_chars):

except KeyError:
raise CompilerError(
f"No parameter {cval} for replacement within modifier, in {context.describe()}!"
f"No parameter {cval} for replacement within modifier, "
f"in {context.describe()}!"
)

elif ctype == "recurse":
Expand Down Expand Up @@ -526,14 +533,16 @@ def _parse_state_sprite(self, context: ZDCodeParseContext, sprite):

else:
raise CompilerError(
f"Parametrized sprite '{sprite_name}' in {context.describe()} needs to be passed a string; got {repr(new_name)}"
f"Parametrized sprite '{sprite_name}' in {context.describe()} "
f"needs to be passed a string; got {repr(new_name)}"
)

name = new_name

except KeyError:
raise CompilerError(
f"No parameter {repr(sprite_name)} for parametrized sprite name, in {context.describe()}!"
f"No parameter {repr(sprite_name)} for parametrized sprite name, "
f"in {context.describe()}!"
)

return name
Expand Down Expand Up @@ -628,7 +637,8 @@ def clear_remotes(target=context):

elif s[0] == "call":
raise CompilerError(
f"Functions and calls have been removed since ZDCode 2.11.0! ({context.describe()})"
"Functions and calls have been removed since ZDCode 2.11.0! "
f"({context.describe()})"
)

elif s[0] == "flow":
Expand Down Expand Up @@ -682,7 +692,8 @@ def clear_remotes(target=context):

except KeyError:
raise CompilerError(
f"Tried to apply unkown state mod {repr(apply_mod)} in apply statement inside {context.describe()}!"
f"Tried to apply unkown state mod {repr(apply_mod)} "
f"in apply statement inside {context.describe()}!"
)

apply_ctx = context.derive("apply block")
Expand Down Expand Up @@ -962,7 +973,7 @@ def _parse_anonym_class(self, anonym_class, context) -> str:
a = dict(anonym_class)
new_context = context.derive("anonymous class")

classname = f"_AnonymClass_{self.id}_{len(self.anonymous_classes)}"
classname = f"_AnonymClass_{self.identifier}_{len(self.anonymous_classes)}"

if a["group"]:
g = unstringify(a["group"])
Expand Down Expand Up @@ -994,7 +1005,7 @@ def _parse_anonym_class(self, anonym_class, context) -> str:

def _derive_class_from_template(
self,
template,
template: ZDClassTemplate,
param_values,
context,
labels=(),
Expand All @@ -1012,7 +1023,6 @@ def _derive_class_from_template(
body = list(body)

needs_init, actor = template.generate_init_class(
self,
context,
param_values,
{l.upper() for l in labels.keys()},
Expand Down Expand Up @@ -1205,6 +1215,15 @@ def do_else():
else:
yield from do_else()

def assert_group_exists(
self, groupname: str, ctx_str: str, context: "ZDCodeParseContext"
):
"""Raises an error if this group does not exist."""
if groupname not in self.groups:
raise CompilerError(
f"No such group '{groupname}' {ctx_str} (in f{context.describe()})!"
)

def _parse(self, actors, debug=False):
parsed_actors = []

Expand Down Expand Up @@ -1391,21 +1410,19 @@ def pending_oper():
self.actors.extend(parsed_actors)

self.actors.sort(key=lambda actor: actor.name) # predominantly alphabetic sort
reorders = self.reorder_inherits()
self.reorder_inherits()

if debug:
context.print_state_tree()

# print("(Reordered {} actors)".format(reorders))

def __init__(self):
self.includes = {}
self.inventories = []
self.anonymous_classes = []
self.actors = []
self.actor_names = {}
self.groups = {}
self.id = make_id(35)
self.identifier = make_id(35)
self.num_anonym_macros = 0

def reorder_inherits(self) -> int:
Expand Down Expand Up @@ -1433,7 +1450,7 @@ def reorder_inherits(self) -> int:
def to_decorate(self):
res = TextNode(indent=0)

res.add_line(f"// :ZDCODE version='{__VERSION__}' id='{self.id}' ")
res.add_line(f"// :ZDCODE version='{__VERSION__}' id='{self.identifier}' ")

if self.inventories:
for i in self.inventories:
Expand Down
67 changes: 47 additions & 20 deletions zdcode/compiler/context.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""ZDCode processing context."""
import collections
import itertools
from typing import TYPE_CHECKING
Expand All @@ -11,6 +12,8 @@


class ZDCtxDescBlock:
"""ZDCode context description block."""

def __init__(self, ctx: "ZDCodeParseContext", desc: str):
self.ctx = ctx
self.desc = desc
Expand All @@ -22,7 +25,12 @@ def __exit__(self, _1, _2, _3):
assert self.ctx.desc_stack.pop() == self.desc


class ZDCodeParseContext(object):
class ZDCodeParseContext:
"""A ZDCode processing and transform context.
Used to group states and other objects, to count relevant gruopings of states,
and to help with debugging."""

def __init__(
self,
replacements=None,
Expand Down Expand Up @@ -65,16 +73,18 @@ def __init__(
self.add_description(description)

def add_description(self, desc):
"""Appends to the description stack of this context."""
self.desc_stack.append(desc)

def get_applied_mods(self):
"""Returns an iterator on the state modifiers active in this context."""
if self.always_applied_mods is None:
return iter(self.applied_mods)

else:
return itertools.chain(self.always_applied_mods, self.applied_mods)
return itertools.chain(self.always_applied_mods, self.applied_mods)

def print_state_tree(self, _print_low=print, _print=print, prefix="+ "):
"""Print a tree of everything in this context."""
ended = 0

_print_low = _print_low or print
Expand Down Expand Up @@ -108,16 +118,16 @@ def _print_next(line=""):

imax = len(self.states)

for i, s in enumerate(self.states):
ended = 1 if i >= imax - 1 else 0
for index, state in enumerate(self.states):
ended = 1 if index >= imax - 1 else 0

if isinstance(s, ZDCodeParseContext):
s.print_state_tree(
if isinstance(state, ZDCodeParseContext):
state.print_state_tree(
_print, _print_next, "'---+ " if ended > 0 else "+---+ "
)

else:
_branch(f"{type(s).__name__} ({s.num_states()})", ended)
_branch(f"{type(state).__name__} ({state.num_states()})", ended)

if not ended:
_print("|")
Expand All @@ -128,10 +138,10 @@ def _print_next(line=""):

imax = len(self.remote_children)

for i, ch in enumerate(self.remote_children):
ended = 2 if i >= imax - 1 else 1
for index, child in enumerate(self.remote_children):
ended = 2 if index >= imax - 1 else 1

ch.print_state_tree(
child.print_state_tree(
_print,
_print_next,
"^---* (remote) " if ended > 1 else "%---* (remote) ",
Expand All @@ -141,16 +151,18 @@ def _print_next(line=""):
_print(":")

def num_states(self):
"""Counts every state in this context and children, except remotely derived."""
return sum(s.num_states() for s in self.states)

def remote_num_states(self):
"""Counts every state in this context and its children."""
return (
self.remote_offset
+ sum(
s.remote_num_states()
if isinstance(s, ZDCodeParseContext)
else s.num_states()
for s in self.states
state.remote_num_states()
if isinstance(state, ZDCodeParseContext)
else state.num_states()
for state in self.states
)
+ sum(c.remote_num_states() for c in self.remote_children)
)
Expand All @@ -162,6 +174,13 @@ def remote_derive(
break_ctx: "ZDCodeParseContext" | Literal["self"] | None = None,
loop_ctx: "ZDCodeParseContext" | Literal["self"] | None = None,
) -> "ZDCodeParseContext":
"""Creates a new context, which 'remotely' derives from this one.
Remote derivation is special in that a remotely derived context does not
actually count as a child of the current one. Its states are not counted
towards this one's total, unless using [remote_num_states].
"""

# derives without adding to states
res = ZDCodeParseContext(
self.replacements,
Expand Down Expand Up @@ -189,6 +208,7 @@ def derive(
break_ctx: "ZDCodeParseContext" | Literal["self"] | None = None,
loop_ctx: "ZDCodeParseContext" | Literal["self"] | None = None,
) -> "ZDCodeParseContext":
"""Creates a child context deriving from this one, and returns it."""
res = ZDCodeParseContext(
self.replacements,
self.macros,
Expand All @@ -212,25 +232,31 @@ def __repr__(self):
return f"ZDCodeParseContext({self.repr_describe()})"

def desc_block(self, desc: str):
"""Returns a context description block to use with 'with'."""
return ZDCtxDescBlock(self, desc)

def update(self, other_ctx: "ZDCodeParseContext"):
"""Update ChainMaps to also point to the other context's information."""
self.macros.maps.insert(-1, other_ctx.macros)
self.replacements.maps.insert(-1, other_ctx.replacements)
self.templates.maps.insert(-1, other_ctx.templates)
self.mods.maps.insert(-1, other_ctx.mods)

def add_actor(self, ac: "ZDActor"):
for al in self.actor_lists:
al.append(ac)
"""Append an actor to every actor list tracked by this context."""
for actor_list in self.actor_lists:
actor_list.append(ac)

def describe(self):
def describe(self) -> str:
"""Describes this context."""
return " at ".join(self.desc_stack[::-1])

def repr_describe(self):
def repr_describe(self) -> str:
"""Describes this context, but comma separated. Used in __repr__."""
return ", ".join(self.desc_stack[::-1])

def resolve(self, name, desc="a parametrizable name"):
"""Resolve a name, applying replacements in this context when applicable."""
while name[0] == "@":
resolves = len(name) - len(name.lstrip("@"))
casename = name[resolves:]
Expand All @@ -245,7 +271,8 @@ def resolve(self, name, desc="a parametrizable name"):

else:
raise CompilerError(
f"No such replacement {repr(name)} while trying to resolve {repr(casename)} in {self.describe()}!"
f"No such replacement {repr(name)} "
f"while trying to resolve {repr(casename)} in {self.describe()}!"
)

return name
5 changes: 4 additions & 1 deletion zdcode/compiler/error.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
"""ZDCode compiler errors."""


class CompilerError(Exception):
pass
"""An error encountered during compilation."""
Loading

0 comments on commit 558cd65

Please sign in to comment.