# Extending SkoolKit

## Extension modules

While creating a disassembly of a game, you may find that SkoolKit’s suite of skool macros is inadequate for certain tasks. For example, the game might have large tile-based sprites that you want to create images of for the HTML disassembly, and composing long `#UDGARRAY` macros for them or defining a new sprite-building macro with the #DEF macro would be too tedious or impractical. Or you might want to insert a timestamp somewhere in the ASM disassembly so that you (or others) can keep track of when your ASM files were written.

One way to solve these problems is to add custom methods that could be called by a #CALL macro. But where to add the methods? SkoolKit’s core HTML writer and ASM writer classes are skoolkit.skoolhtml.HtmlWriter and skoolkit.skoolasm.AsmWriter, so you could add the methods to those classes. But a better way is to subclass HtmlWriter and AsmWriter in a separate extension module, and add the methods there; then that extension module can be easily used with different versions of SkoolKit, and shared with other people.

A minimal extension module would look like this:

    from skoolkit.skoolhtml import HtmlWriter
    from skoolkit.skoolasm import AsmWriter

    class GameHtmlWriter(HtmlWriter):
        pass

    class GameAsmWriter(AsmWriter):
        pass

The next step is to get SkoolKit to use the extension module for your game. First, place the extension module (let’s call it game.py) in the skoolkit package directory; to locate this directory, run skool2html.py with the `-p` option:

    $ skool2html.py -p
    /usr/lib/python3/dist-packages/skoolkit

(The package directory may be different on your system.) With game.py in place, add the following line to the [Config] section of your disassembly’s ref file:

    HtmlWriterClass=skoolkit.game.GameHtmlWriter

If you don’t have a ref file yet, create one (ideally named game.ref, assuming the skool file is game.skool); if the ref file doesn’t have a [Config] section yet, add one.

Now whenever skool2html.py is run on your skool file (or ref file), SkoolKit will use the GameHtmlWriter class instead of the core HtmlWriter class.

To get skool2asm.py to use GameAsmWriter instead of the core AsmWriter class when it’s run on your skool file, add the following @writer ASM directive somewhere after the `@start` directive, and before the `@end` directive (if there is one):

    @writer=skoolkit.game.GameAsmWriter

The skoolkit package directory is a reasonable place for an extension module, but it could be placed in another package, or somewhere else as a standalone module. For example, if you wanted to keep a standalone extension module named game.py in ~/.skoolkit, you should set the `HtmlWriterClass` parameter thus:

    HtmlWriterClass=~/.skoolkit:game.GameHtmlWriter

and the `@writer` directive thus:

    @writer=~/.skoolkit:game.GameAsmWriter

The HTML writer or ASM writer class can also be specified on the command line by using the `-W`/`--writer` option of skool2html.py or skool2asm.py. For example:

    $ skool2html.py -W ~/.skoolkit:game.GameHtmlWriter game.skool

Specifying the writer class this way will override any `HtmlWriterClass` parameter in the ref file or `@writer` directive in the skool file.

Note that if the writer class is specified with a blank module path (e.g. `:game.GameHtmlWriter`), SkoolKit will search for the module in both the current working directory and the directory containing the skool file named on the command line.

## #CALL methods

Implementing a method that can be called by a #CALL macro is done by adding the method to the HtmlWriter or AsmWriter subclass in the extension module.

One thing to be aware of when adding a `#CALL` method to a subclass of HtmlWriter is that the method must accept an extra parameter in addition to those passed from the `#CALL` macro itself: cwd. This parameter is set to the current working directory of the file from which the `#CALL` macro is executed, which may be useful if the method needs to provide a hyperlink to some other part of the disassembly (as in the case where an image is being created).

Let’s say your sprite-image-creating method will accept two parameters (in addition to cwd): sprite_id (the sprite identifier) and fname (the image filename). The method (let’s call it sprite) would look something like this:

    from skoolkit.graphics import Frame
    from skoolkit.skoolhtml import HtmlWriter

    class GameHtmlWriter(HtmlWriter):
        def sprite(self, cwd, sprite_id, fname):
            udgs = self.build_sprite(sprite_id)
            return self.handle_image(Frame(udgs), fname, cwd)

With this method (and an appropriate implementation of the build_sprite method) in place, it’s possible to use a `#CALL` macro like this:

    #UDGTABLE
    { #CALL(sprite(3,jumping)) }
    { Sprite 3 (jumping) }
    TABLE#

Adding a `#CALL` method to the AsmWriter subclass is equally simple. The timestamp-creating method (let’s call it timestamp) would look something like this:

    import time
    from skoolkit.skoolasm import AsmWriter

    class GameAsmWriter(AsmWriter):
        def timestamp(self):
            return time.strftime("%a %d %b %Y %H:%M:%S %Z")

With this method in place, it’s possible to use a `#CALL` macro like this:

    ; This ASM file was generated on #CALL(timestamp())

Note that if the return value of a `#CALL` method contains skool macros, then they will be expanded.

## #CALL functions

The #CALL macro can be used not only to call a method on an HtmlWriter or AsmWriter subclass, but also to call an arbitrary function. This approach might be preferable if you don’t need to make use of any of the methods or attributes on the HtmlWriter/AsmWriter object, and the desired output is the same regardless of the output mode (HTML or ASM).

Suppose you have the following string-reversing function defined in mods/custom.py:

    def rev(s):
        return s[::-1]

Then you could call the rev function like this:

    ; This string reversed is "#CALL(mods:custom.rev(#STR40000))".
    t40000 DEFM "hello",0

Note that unlike when calling a method on an HtmlWriter subclass, no cwd parameter is passed to the function.

## Skool macros

Another way to add a custom method is to implement it as a skool macro. The main differences between a skool macro and a `#CALL` method are:

- a `#CALL` macro’s parameters are automatically evaluated and passed to the `#CALL` method; a skool macro’s parameters must be parsed and evaluated manually (typically by using one or more of the macro-parsing utility functions)

- numeric parameters in a `#CALL` macro are automatically converted to numbers before being passed to the `#CALL` method; no automatic conversion is done on the parameters of a skool macro

In summary: a `#CALL` method is generally simpler to implement than a skool macro, but skool macros are more flexible.

Implementing a skool macro is done by adding a method named expand_macroname to the HtmlWriter or AsmWriter subclass in the extension module. So, to implement a `#SPRITE` or `#TIMESTAMP` macro, we would add a method named expand_sprite or expand_timestamp.

A skool macro method must accept either two or three parameters, depending on whether it is implemented on a subclass of AsmWriter or HtmlWriter:

- `text` - the text that contains the skool macro

- `index` - the index of the character after the last character of the macro name (that is, where to start looking for the macro’s parameters)

- `cwd` - the current working directory of the file from which the macro is being executed; this parameter must be supported by skool macro methods on an HtmlWriter subclass

A skool macro method must return a 2-tuple of the form `(end, string)`, where `end` is the index of the character after the last character of the macro’s parameter string, and `string` is the HTML or text to which the macro will be expanded. Note that if `string` itself contains skool macros, then they will be expanded.

The expand_sprite method on GameHtmlWriter may therefore look something like this:

    from skoolkit.graphics import Frame
    from skoolkit.skoolhtml import HtmlWriter
    from skoolkit.skoolmacro import parse_image_macro

    class GameHtmlWriter(HtmlWriter):
        # #SPRITEid[{x,y,width,height}](fname)
        def expand_sprite(self, text, index, cwd):
            end, crop_rect, fname, frame, alt, (sprite_id,) = parse_image_macro(text, index, names=['id'])
            udgs = self.build_sprite(sprite_id)
            frame = Frame(udgs, 2, 0, *crop_rect, name=frame)
            return end, self.handle_image(frame, fname, cwd, alt)

With this method (and an appropriate implementation of the build_sprite method) in place, the `#SPRITE` macro might be used like this:

    #UDGTABLE
    { #SPRITE3(jumping) }
    { Sprite 3 (jumping) }
    TABLE#

The expand_timestamp method on GameAsmWriter would look something like this:

    import time
    from skoolkit.skoolasm import AsmWriter

    class GameAsmWriter(AsmWriter):
        def expand_timestamp(self, text, index):
            return index, time.strftime("%a %d %b %Y %H:%M:%S %Z")

## Parsing skool macros

The skoolkit.skoolmacro module provides some utility functions that may be used to parse the parameters of a skool macro.

skoolkit.skoolmacro.parse_ints(text, index=0, num=0, defaults=(), names=(), fields=None)

  Parse a sequence of comma-separated integer parameters, optionally enclosed in parentheses. If parentheses are used, the parameters may be expressed using arithmetic operators and skool macros. See Numeric parameters for more details.

  Parameters:

    - text – The text to parse.

    - index – The index at which to start parsing.

    - num – The maximum number of parameters to parse; this is set to the number of elements in names if that list is not empty.

    - defaults – The default values of the optional parameters.

    - names – The names of the parameters; if not empty, keyword arguments are parsed. Parameter names are restricted to lower case letters (a-z).

    - fields – A dictionary of replacement field names and values. The fields named in this dictionary are replaced by their values wherever they appear in the parameter string.

  Returns:

    A list of the form `[end, value1, value2...]`, where:

    - `end` is the index at which parsing terminated

    - `value1`, `value2` etc. are the parameter values

  Changed in version 6.0: Added the fields parameter.

  Changed in version 5.1: Added support for parameters expressed using arithmetic operators and skool macros.

  Changed in version 4.0: Added the names parameter and support for keyword arguments; index defaults to 0.

skoolkit.skoolmacro.parse_strings(text, index=0, num=0, defaults=())

  Parse a sequence of comma-separated string parameters. The sequence must be enclosed in parentheses, square brackets or braces. If the sequence itself contains commas or unmatched brackets, then an alternative delimiter and separator may be used; see String parameters for more details.

  Parameters:

    - text – The text to parse.

    - index – The index at which to start parsing.

    - num – The maximum number of parameters to parse. If 0, all parameters are parsed; if 1, the entire parameter string is parsed as a single parameter, regardless of commas.

    - defaults – The default values of the optional parameters.

  Returns:

    A tuple of the form `(end, result)`, where:

    - `end` is the index at which parsing terminated

    - `result` is either the single parameter itself (when num is 1), or a list of the parameters

  Added in version 5.1.

skoolkit.skoolmacro.parse_brackets(text, index=0, default=None, opening='(', closing=')')

  Parse a single string parameter enclosed either in parentheses or by an arbitrary pair of delimiters.

  Parameters:

    - text – The text to parse.

    - index – The index at which to start parsing.

    - default – The default value if no string parameter is found.

    - opening – The opening delimiter.

    - closing – The closing delimiter.

  Returns:

    A tuple of the form `(end, param)`, where:

    - `end` is the index at which parsing terminated

    - `param` is the string parameter (or default if none is found)

  Added in version 5.1.

skoolkit.skoolmacro.parse_image_macro(text, index=0, defaults=(), names=(), fname='', fields=None, xparse=None, xpargs=())

  Parse a string of the form:

  `[params][xparams][{x,y,width,height}][(fname[*frame][|alt])]`

  The parameter string `params` may contain comma-separated integer values, and may optionally be enclosed in parentheses. Parentheses are required if any parameter is expressed using arithmetic operations or skool macros. The extra parameter string `xparams` is parsed only if the parsing function xparse is specified.

  Parameters:

    - text – The text to parse.

    - index – The index at which to start parsing.

    - defaults – The default values of the optional parameters.

    - names – The names of the parameters.

    - fname – The default base name of the image file.

    - fields – A dictionary of replacement field names and values. The fields named in this dictionary are replaced by their values wherever they appear in `params` or `{x,y,width,height}`.

    - xparse – A function that can parse `xparams`. It must accept at least three arguments: text, index and pvals, where text is the same as the argument passed to parse_image_macro, index indicates where to start parsing text, and pvals is a list of the parameter values from `params`. The return value must be of the form `(end, xpvals)`, where `end` is the index at which parsing terminated, and `xpvals` is a list of the parameter values from `xparams`.

    - xpargs – Additional arguments to pass to xparse.

  Returns:

    A tuple of the form `(end, crop_rect, fname, frame, alt, values)`, where:

    - `end` is the index at which parsing terminated

    - `crop_rect` is `(x, y, width, height)`

    - `fname` is the base name of the image file

    - `frame` is the frame name (None if no frame is specified)

    - `alt` is the alt text (None if no alt text is specified)

    - `values` is a list of the parameter values, including those returned by xparse (if specified)

  Changed in version 9.5: Added the xparse and xpargs parameters.

  Changed in version 8.3: Added the fields parameter.

  Added in version 5.1.

## Expanding skool macros

Both AsmWriter and HtmlWriter provide methods for expanding skool macros. These are useful for immediately expanding macros in a `#CALL` method or custom macro method.

AsmWriter.expand(text)

  Return text with skool macros expanded.

HtmlWriter.expand(text, cwd=None)

  Return text with skool macros expanded. cwd is the current working directory, which is required by macros that create images or hyperlinks.

  Changed in version 5.1: The cwd parameter is optional.

## Parsing ref files

HtmlWriter provides some convenience methods for extracting text and data from ref files. These methods are described below.

HtmlWriter.get_section(section_name, paragraphs=False, lines=False, trim=True)

  Return the contents of a ref file section.

  Parameters:

    - section_name – The section name.

    - paragraphs – If True, return the contents as a list of paragraphs.

    - lines – If True, return the contents (or each paragraph) as a list of lines; otherwise return the contents (or each paragraph) as a single string.

    - trim – If True, remove leading whitespace from each line.

  Changed in version 5.3: Added the trim parameter.

HtmlWriter.get_sections(section_type, paragraphs=False, lines=False, trim=True)

  Return a list of 2-tuples of the form `(suffix, contents)` or 3-tuples of the form `(infix, suffix, contents)` derived from ref file sections whose names start with section_type followed by a colon. `suffix` is the part of the section name that follows either the first colon (when there is only one) or the second colon (when there is more than one); `infix` is the part of the section name between the first and second colons (when there is more than one).

  Parameters:

    - section_type – The section name prefix.

    - paragraphs – If True, return the contents of each section as a list of paragraphs.

    - lines – If True, return the contents (or each paragraph) of each section as a list of lines; otherwise return the contents (or each paragraph) as a single string.

    - trim – If True, remove leading whitespace from each line.

  Changed in version 5.3: Added the trim parameter.

HtmlWriter.get_dictionary(section_name)

  Return a dictionary built from the contents of a ref file section. Each line in the section should be of the form `X=Y`.

HtmlWriter.get_dictionaries(section_type)

  Return a list of 2-tuples of the form `(suffix, dict)` derived from ref file sections whose names start with section_type followed by a colon. `suffix` is the part of the section name that follows the first colon, and `dict` is a dictionary built from the contents of that section; each line in the section should be of the form `X=Y`.

## Formatting templates

HtmlWriter provides a method for formatting a template defined by a [Template:*] section.

HtmlWriter.format_template(name, fields)

  Format a template with a set of replacement fields.

  Parameters:

    - name – The name of the template.

    - fields – A dictionary of replacement field names and values.

  Returns:

    The formatted string.

  Changed in version 8.0: Removed the default parameter.

  Added in version 4.0.

Note that if name is ‘Layout’, the template whose name matches the current page ID will be used, if it exists; if no such template exists, the Layout template will be used. If name is not ‘Layout’, the template named `PageID-name` (where `PageID` is the current page ID) will be used, if it exists; if no such template exists, the `name` template will be used. This is in accordance with SkoolKit’s rules for preferring page-specific templates.

## Base, case and fields

The base and case attributes on AsmWriter and HtmlWriter can be inspected to determine the mode in which skool2asm.py or skool2html.py is running.

The base attribute has one of the following values:

- 0 - default (neither `--decimal` nor `--hex`)

- 10 - decimal (`--decimal`)

- 16 - hexadecimal (`--hex`)

Added in version 6.1.

The case attribute has one of the following values:

- 0 - default (neither `--lower` nor `--upper`)

- 1 - lower case (`--lower`)

- 2 - upper case (`--upper`)

Added in version 6.1.

The fields attribute on AsmWriter and HtmlWriter is a dictionary of replacement field names and values (see Replacement fields). It can be used with the `parse_ints()` and `parse_image_macro()` functions.

Added in version 6.0.

## Memory snapshots

The snapshot attribute on HtmlWriter and AsmWriter is a list-like object that represents the Spectrum’s memory. It supports both indexing and slicing for addresses 0-65535 ($0000-$FFFF), and reports a length (via the len function) of either 65536 (for a 48K Spectrum) or 131072 (for a 128K Spectrum).

Changed in version 9.1: The snapshot attribute is no longer a plain list object.

HtmlWriter and AsmWriter also provide methods for saving and restoring memory snapshots, which can be useful for temporarily changing graphic data or the contents of data tables.

HtmlWriter.push_snapshot(name='')

  Save a copy of the current memory snapshot for later retrieval (by `pop_snapshot()`).

  Parameters:

    name – An optional name for the snapshot.

HtmlWriter.pop_snapshot()

  Replace the current memory snapshot with the one most recently saved by `push_snapshot()`.

In addition, HtmlWriter (but not AsmWriter) provides a method for retrieving the snapshot name.

HtmlWriter.get_snapshot_name()

  Return the name of the current memory snapshot.

## Graphics

If you are going to implement a custom image-creating `#CALL` method or skool macro, you will need to make use of the skoolkit.graphics.Udg and skoolkit.graphics.Frame classes.

The Udg class represents an 8x8 graphic (8 bytes) with a single attribute byte, and an optional mask.

class skoolkit.graphics.Udg(attr, data, mask=None)

  Initialise the UDG.

  Parameters:

    - attr – The attribute byte.

    - data – The graphic data (sequence of 8 bytes).

    - mask – The mask data (sequence of 8 bytes).

  Changed in version 5.4: The Udg class moved from skoolkit.skoolhtml to skoolkit.graphics.

An `#INVERSE` macro that creates an inverse image of a UDG with scale 2 might be implemented like this:

    from skoolkit.graphics import Frame, Udg
    from skoolkit.skoolhtml import HtmlWriter
    from skoolkit.skoolmacro import parse_ints

    class GameHtmlWriter(HtmlWriter):
        # #INVERSEaddress,attr
        def expand_inverse(self, text, index, cwd):
            end, address, attr = parse_ints(text, index, 2)
            udg_data = [b ^ 255 for b in self.snapshot[address:address + 8]]
            frame = Frame([[Udg(attr, udg_data)]], 2)
            fname = 'inverse{}_{}'.format(address, attr)
            return end, self.handle_image(frame, fname, cwd)

The Udg class provides two methods for manipulating an 8x8 graphic: flip and rotate.

Udg.flip(flip=1)

  Flip the UDG.

  Parameters:

    flip – 1 to flip horizontally, 2 to flip vertically, or 3 to flip horizontally and vertically.

Udg.rotate(rotate=1)

  Rotate the UDG 90 degrees clockwise.

  Parameters:

    rotate – The number of rotations to perform.

The Udg class also provides a method for creating a copy of a UDG.

Udg.copy()

  Return a deep copy of the UDG.

The Frame class represents a single frame of a still or animated image.

class skoolkit.graphics.Frame(udgs, scale=1, mask=0, x=0, y=0, width=None, height=None, delay=32, name='', tindex=0, alpha=-1, x_offset=0, y_offset=0)

  Create a frame of a still or animated image.

  Parameters:

    - udgs – The two-dimensional array of tiles (instances of `Udg`) from which to build the frame, or a function that returns the array of tiles.

    - scale – The scale of the frame.

    - mask – The type of mask to apply to the tiles in the frame: 0 (no mask), 1 (OR-AND mask), or 2 (AND-OR mask).

    - x – The x-coordinate of the top-left pixel to include in the frame.

    - y – The y-coordinate of the top-left pixel to include in the frame.

    - width – The width of the frame; if None, the maximum width (derived from x and the width of the array of tiles) is used.

    - height – The height of the frame; if None, the maximum height (derived from y and the height of the array of tiles) is used.

    - delay – The delay between this frame and the next in 1/100ths of a second.

    - name – The name of this frame.

    - tindex – The index of the entry in the palette to use as the transparent colour.

    - alpha – The alpha value to use for the transparent colour. If -1, the value of the `PNGAlpha` parameter in the [ImageWriter] section is used.

    - x_offset – The x-coordinate at which to render the frame.

    - y_offset – The y-coordinate at which to render the frame.

  Changed in version 8.3: Added the x_offset and y_offset parameters.

  Changed in version 8.2: Added the tindex and alpha parameters.

  Changed in version 5.4: The Frame class moved from skoolkit.skoolhtml to skoolkit.graphics.

  Changed in version 5.1: The udgs parameter can be a function that returns the array of tiles; added the name parameter.

  Changed in version 4.0: The mask parameter specifies the type of mask to apply (see Masks).

  Added in version 3.6.

HtmlWriter and skoolkit.graphics provide the following image-related methods and functions.

HtmlWriter.handle_image(frames, fname='', cwd=None, alt=None, path_id='ImagePath')

  Register a named frame for an image, and write an image file if required. If fname is blank, no image file will be created. If fname does not end with ‘.png’, that suffix will be appended. If fname contains an image path ID replacement field, the corresponding parameter value from the [Paths] section will be substituted.

  Parameters:

    - frames – A frame (instance of `Frame`) or list of frames from which to build the image.

    - fname – The name of the image file.

    - cwd – The current working directory (from which the relative path of the image file will be computed).

    - alt – The alt text to use for the image.

    - path_id – The ID of the target directory (as defined in the [Paths] section of the ref file). This is not used if fname starts with a ‘/’ or contains an image path ID replacement field.

  Returns:

    The `<img .../>` element, or an empty string if no image is created.

  Changed in version 7.0: path_id defaults to `ImagePath` (previously `UDGImagePath`).

  Changed in version 6.4: frames may be a single frame.

  Changed in version 6.3: fname may contain an image path ID replacement field (e.g. `{UDGImagePath}`).

  Added in version 5.1.

HtmlWriter.screenshot(x=0, y=0, w=32, h=24, df_addr=16384, af_addr=22528)

  Return a two-dimensional array of tiles (instances of `Udg`) built from the display file and attribute file of the current memory snapshot.

  Parameters:

    - x – The x-coordinate of the top-left tile to include (0-31).

    - y – The y-coordinate of the top-left tile to include (0-23).

    - w – The width of the array (in tiles).

    - h – The height of the array (in tiles).

    - df_addr – The display file address to use.

    - af_addr – The attribute file address to use.

skoolkit.graphics.flip_udgs(udgs, flip=1)

  Flip a 2D array of UDGs (instances of `Udg`).

  Parameters:

    - udgs – The array of UDGs.

    - flip – 1 to flip horizontally, 2 to flip vertically, or 3 to flip horizontally and vertically.

skoolkit.graphics.overlay_udgs(bg, fg, x, y, mask=0, rattr=None, rbyte=None)

  Overlay a foreground array of UDGs (instances of `Udg`) on a background array of UDGs.

  Parameters:

    - bg – The background array of UDGs.

    - fg – The foreground array of UDGs.

    - x – Pixel x-coordinate on the background at which to overlay the foreground.

    - y – Pixel y-coordinate on the background at which to overlay the foreground.

    - mask – The type of mask to apply: 0 (no mask), 1 (OR-AND mask), or 2 (AND-OR mask). If 0, the contents of the foreground and background are combined by OR operations.

    - rattr – A function that returns the replacement attribute byte for a background UDG over which a foreground UDG is superimposed. It must accept two arguments: the existing background UDG attribute, and the foreground UDG attribute. If None, the existing background attributes are left in place.

    - rbyte – A function that returns the replacement value for each graphic byte of a background UDG over which a foreground UDG is superimposed. It must accept three arguments: the existing background UDG graphic byte, the foreground UDG graphic byte, and the foreground UDG mask byte. If None, the mask specified by mask is used.

  Added in version 8.5.

skoolkit.graphics.rotate_udgs(udgs, rotate=1)

  Rotate a 2D array of UDGs (instances of `Udg`) 90 degrees clockwise.

  Parameters:

    - udgs – The array of UDGs.

    - rotate – The number of rotations to perform.

## HTML page initialisation

If you need to perform page-specific actions or customise the `SkoolKit` and `Game` parameter dictionaries that are used by the HTML templates, the place to do that is the init_page() method.

HtmlWriter.init_page(skoolkit, game)

  Perform page initialisation operations. This method is called after the `SkoolKit` and `Game` parameter dictionaries have been initialised, and provides those dictionaries as arguments for inspection and customisation before a page is formatted. By default the method does nothing, but subclasses may override it.

  Parameters:

    - skoolkit – The `SkoolKit` parameter dictionary.

    - game – The `Game` parameter dictionary.

  Added in version 7.0.

## Writer initialisation

If your AsmWriter or HtmlWriter subclass needs to perform some initialisation tasks, such as creating instance variables, or parsing ref file sections, the place to do that is the init() method.

AsmWriter.init()

  Perform post-initialisation operations. This method is called after __init__() has completed. By default the method does nothing, but subclasses may override it.

  Added in version 6.1.

HtmlWriter.init()

  Perform post-initialisation operations. This method is called after __init__() has completed. By default the method does nothing, but subclasses may override it.

For example:

    from skoolkit.skoolhtml import HtmlWriter

    class GameHtmlWriter(HtmlWriter):
        def init(self):
            # Get character names from the ref file
            self.characters = self.get_dictionary('Characters')