Module refinery.lib.batch.model

Expand source code Browse git
from __future__ import annotations

import enum
import sys

from dataclasses import dataclass, field
from functools import cached_property
from typing import Generic, TypeVar, Union

from refinery.lib.batch.util import batchrange
from refinery.lib.structures import FlagAccessMixin

IntOrStr = TypeVar('IntOrStr', int, str)


class Ctrl(str, enum.Enum):
    At                  = '@'   # noqa;
    Semicolon           = ';'   # noqa;
    Comma               = ','   # noqa;
    Label               = ':'   # noqa;
    Comment             = '::'  # noqa;
    Equals              = '='   # noqa;
    NewGroup            = '('   # noqa;
#   The following can terminate a command:
    EndGroup            = ')'   # noqa;
    NewLine             = '\n'  # noqa;
    Ampersand           = '&'   # noqa;
    Pipe                = '|'   # noqa;
    EndOfFile           = ''    # noqa;

    def __str__(self):
        return self.value

    def upper(self):
        return self


class Word(str):
    def upper(self):
        return Word(super().upper())


class Expected(str):
    pass


class Redirect(str, enum.Enum):
    OutCreate = '>'
    OutAppend = '>>'
    In = '<'

    def __str__(self):
        return self.value

    def __repr__(self):
        return self.name


@dataclass(unsafe_hash=True)
class RedirectIO:
    type: Redirect
    source: int
    target: int | str = -1

    @property
    def target_is_file(self) -> bool:
        return isinstance(self.target, str)

    @property
    def is_out_create(self):
        return self.type == Redirect.OutCreate

    @property
    def is_out_append(self):
        return self.type == Redirect.OutAppend

    @property
    def is_input(self):
        return self.type == Redirect.In

    def __str__(self):
        target = self.target
        string = F'{self.source}{self.type!s}'
        if target is None:
            return string
        if isinstance(target, int):
            target = F'&{target}'
        elif any(p in target for p in ';,=\x20\t\v'):
            target = F'"{target}"'
        return F'{string}{target}'

    def isspace(self):
        return False

    def upper(self):
        return self


Token = Union[Word, Ctrl, RedirectIO]


class ArgVarFlags(FlagAccessMixin, enum.IntFlag):
    Empty = 0

    q = 0b0000_00001
    d = 0b0000_00010
    p = 0b0000_00100
    n = 0b0000_01000
    x = 0b0000_10000
    s = 0b0001_00000
    a = 0b0010_00000
    t = 0b0100_00000
    z = 0b1000_00000
    f = d | p | n | x

    StripQuotes   = q # noqa
    FullPath      = f # noqa
    DriveLetter   = d # noqa
    FilePath      = p # noqa
    FileName      = n # noqa
    FileExtension = x # noqa
    ShortName     = s # noqa
    Attributes    = a # noqa
    DateTime      = t # noqa
    FileSize      = z # noqa

    def __str__(self):
        options = self.__class__
        value = self.value
        string = ''
        for flag, char in (
            (options.q, '~'),
            (options.f, 'f'),
        ):
            if value & flag == flag:
                string += char
                value ^= flag
        for flag in options:
            if value & flag == flag:
                assert flag.name
                string += flag.name
        return string

    @classmethod
    def FromToken(cls, t: int):
        c = chr(t)
        if c == '~':
            return cls(1)
        if c == 'q':
            raise KeyError
        return cls[c]


@dataclass
class ArgVar:
    offset: int | ellipsis = -1
    path: str | None = None
    flags: ArgVarFlags = ArgVarFlags.Empty

    def __repr__(self):
        k = self.offset
        if k is (...):
            assert self.path is None
            assert self.flags is ArgVarFlags.Empty
            return '%*'
        elif k < 0:
            k = '?'
        p = F'${p}' if (p := self.path) is not None else ''
        return F'%{self.flags!s}{p}{k}'

    __str__ = __repr__


class AstCondition(str, enum.Enum):
    NoCheck = '&'
    Success = '&&'
    Failure = '||'

    def __str__(self):
        return self.value


@dataclass(repr=False)
class AstNode:
    offset: int
    parent: AstNode | None

    def is_descendant_of(self, ast: AstNode | None):
        parent = self.parent
        if parent is ast:
            return True
        if parent is None:
            return False
        return parent.is_descendant_of(ast)

    @cached_property
    def depth(self):
        if (p := self.parent) is None:
            return 0
        return 1 + p.depth

    def __repr__(self):
        try:
            synth = sys.modules['refinery.lib.batch.synth']
        except KeyError:
            return super().__repr__()
        else:
            return str(synth.synthesize(self))


@dataclass(repr=False)
class AstError(AstNode):
    token: str
    error: str | None


@dataclass(repr=False)
class AstStatement(AstNode):
    silenced: bool


@dataclass(repr=False)
class AstLabel(AstStatement):
    line: str = ''
    label: str = ''
    comment: bool = False


@dataclass(repr=False)
class AstCommand(AstStatement):
    redirects: dict[int, RedirectIO] = field(default_factory=dict)
    fragments: list[str] = field(default_factory=list)


@dataclass(repr=False)
class AstGroup(AstStatement):
    redirects: dict[int, RedirectIO] = field(default_factory=dict)
    fragments: list[AstSequence] = field(default_factory=list)


@dataclass(repr=False)
class AstPipeline(AstStatement):
    parts: list[AstCommand | AstGroup] = field(default_factory=list)


@dataclass(repr=False)
class AstConditionalStatement(AstNode):
    condition: AstCondition
    statement: AstStatement

    def __repr__(self):
        return F'{self.condition.value} {self.statement!r}'


@dataclass(repr=False)
class AstSequence(AstNode):
    head: AstStatement
    tail: list[AstConditionalStatement] = field(default_factory=list)


class AstForVariant(str, enum.Enum):
    D = 'D'
    R = 'R'
    L = 'L'
    F = 'F'
    Default = ''
    MatchFolders = D
    DescendRecursively = R
    NumericLoop = L
    FileParsing = F


class AstForParserMode(enum.IntEnum):
    FileSet = 0
    Literal = 1
    Command = 2


@dataclass
class AstForOptions:
    comment: str | None = None
    skip: int = 0
    tokens: tuple[int, ...] = (0,)
    asterisk: bool = False
    delims: str = '\x20\t'
    usebackq: bool = False


@dataclass(repr=False)
class AstFor(AstStatement):
    variant: AstForVariant
    variable: str
    options: AstForOptions
    body: AstSequence
    spec: list[str] | batchrange
    spec_string: str
    path: str | None
    mode: AstForParserMode

    @property
    def specline(self):
        spec = self.spec
        if isinstance(spec, batchrange):
            raise AttributeError
        try:
            return spec[0]
        except IndexError:
            raise AttributeError


class AstIfVariant(str, enum.Enum):
    Defined = 'DEFINED'             # IF DEFINED VARIABLE
    CmdExtVersion = 'CMDEXTVERSION' # IF CMDEXTVERSION NUMBER
    Exist = 'EXIST'                 # IF EXIST PATH
    ErrorLevel = 'ERRORLEVEL'       # IF ERRORLEVEL NUMBER


class AstIfCmp(str, enum.Enum):
    STR = '=='
    EQU = 'EQU'
    NEQ = 'NEQ'
    LSS = 'LSS'
    LEQ = 'LEQ'
    GTR = 'GTR'
    GEQ = 'GEQ'


@dataclass(repr=False)
class AstIf(AstStatement, Generic[IntOrStr]):
    then_do: AstSequence
    else_do: AstSequence | None = None
    variant: AstIfVariant | None = None
    casefold: bool = True
    negated: bool = False
    cmp: AstIfCmp | None = None
    lhs: IntOrStr | None = None
    rhs: IntOrStr | None = None

    @property
    def var_int(self):
        var = self.lhs
        if isinstance(var, int):
            return var
        raise AttributeError

    @property
    def var_str(self):
        var = self.lhs
        if isinstance(var, str):
            return var
        raise AttributeError


class If(enum.IntFlag):
    Inactive = 0b0000
    Active = 0b0001
    Block = 0b0010
    Then = 0b0100
    Else = 0b1000

    def skip_block(self):
        skip = If.Then not in self
        if If.Else in self:
            skip = not skip
        return skip


class MissingVariable(LookupError):
    pass


class EmulatorException(Exception):
    pass


class InputLocked(EmulatorException):
    def __str__(self):
        return 'The emulation could not continue because a command is waiting for input.'


class AbortExecution(EmulatorException):
    pass


class EmulatorLongJump(EmulatorException):
    pass


class Goto(EmulatorLongJump):
    def __init__(self, label: str):
        self.label = label


class Call(EmulatorLongJump):
    def __init__(self, label: str, offset: int):
        self.label = label
        self.offset = offset


class Exit(EmulatorLongJump):
    def __init__(self, code: int, exit: bool):
        self.code = code
        self.exit = exit


class UnexpectedEOF(EmulatorException, EOFError):
    pass


class UnexpectedToken(EmulatorException):
    def __init__(self, offset: int, token, error: str | None = None) -> None:
        if isinstance(token, int):
            token = chr(token)
        else:
            token = str(token)
        self.token = token
        self.error = error
        self.offset = offset

    def __str__(self):
        end = self.error and F': {self.error}' or '.'
        return F'The token "{self.token}" was unexpected{end}'


class UnexpectedFirstToken(UnexpectedToken):
    def __init__(self, offset: int, token: str | int) -> None:
        super().__init__(offset, token, 'This token may not occur as the first token in a line.')


class InvalidLabel(EmulatorException):
    def __init__(self, label: str):
        self.label = label

    def __str__(self):
        return F'The following label was not found: {self.label}'

Classes

class Ctrl (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class Ctrl(str, enum.Enum):
    At                  = '@'   # noqa;
    Semicolon           = ';'   # noqa;
    Comma               = ','   # noqa;
    Label               = ':'   # noqa;
    Comment             = '::'  # noqa;
    Equals              = '='   # noqa;
    NewGroup            = '('   # noqa;
#   The following can terminate a command:
    EndGroup            = ')'   # noqa;
    NewLine             = '\n'  # noqa;
    Ampersand           = '&'   # noqa;
    Pipe                = '|'   # noqa;
    EndOfFile           = ''    # noqa;

    def __str__(self):
        return self.value

    def upper(self):
        return self

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var At

The type of the None singleton.

var Semicolon

The type of the None singleton.

var Comma

The type of the None singleton.

var Label

The type of the None singleton.

var Comment

The type of the None singleton.

var Equals

The type of the None singleton.

var NewGroup

The type of the None singleton.

var EndGroup

The type of the None singleton.

var NewLine

The type of the None singleton.

var Ampersand

The type of the None singleton.

var Pipe

The type of the None singleton.

var EndOfFile

The type of the None singleton.

Methods

def upper(self)

Return a copy of the string converted to uppercase.

Expand source code Browse git
def upper(self):
    return self
class Word (...)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class Word(str):
    def upper(self):
        return Word(super().upper())

Ancestors

  • builtins.str

Methods

def upper(self)

Return a copy of the string converted to uppercase.

Expand source code Browse git
def upper(self):
    return Word(super().upper())
class Expected (...)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class Expected(str):
    pass

Ancestors

  • builtins.str
class Redirect (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class Redirect(str, enum.Enum):
    OutCreate = '>'
    OutAppend = '>>'
    In = '<'

    def __str__(self):
        return self.value

    def __repr__(self):
        return self.name

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var OutCreate

The type of the None singleton.

var OutAppend

The type of the None singleton.

var In

The type of the None singleton.

class RedirectIO (type, source, target=-1)

RedirectIO(type: 'Redirect', source: 'int', target: 'int | str' = -1)

Expand source code Browse git
@dataclass(unsafe_hash=True)
class RedirectIO:
    type: Redirect
    source: int
    target: int | str = -1

    @property
    def target_is_file(self) -> bool:
        return isinstance(self.target, str)

    @property
    def is_out_create(self):
        return self.type == Redirect.OutCreate

    @property
    def is_out_append(self):
        return self.type == Redirect.OutAppend

    @property
    def is_input(self):
        return self.type == Redirect.In

    def __str__(self):
        target = self.target
        string = F'{self.source}{self.type!s}'
        if target is None:
            return string
        if isinstance(target, int):
            target = F'&{target}'
        elif any(p in target for p in ';,=\x20\t\v'):
            target = F'"{target}"'
        return F'{string}{target}'

    def isspace(self):
        return False

    def upper(self):
        return self

Instance variables

var type

The type of the None singleton.

var source

The type of the None singleton.

var target

The type of the None singleton.

var target_is_file
Expand source code Browse git
@property
def target_is_file(self) -> bool:
    return isinstance(self.target, str)
var is_out_create
Expand source code Browse git
@property
def is_out_create(self):
    return self.type == Redirect.OutCreate
var is_out_append
Expand source code Browse git
@property
def is_out_append(self):
    return self.type == Redirect.OutAppend
var is_input
Expand source code Browse git
@property
def is_input(self):
    return self.type == Redirect.In

Methods

def isspace(self)
Expand source code Browse git
def isspace(self):
    return False
def upper(self)
Expand source code Browse git
def upper(self):
    return self
class ArgVarFlags (*args, **kwds)

This class can be mixed into an enum.IntFlag for some quality of life improvements. Firstly, you can now access flags as follows:

class Flags(FlagAccessMixin, enum.IntFlag):
    IsBinary = 1
    IsCompressed = 2

flag = Flags(3)

if flag.IsCompressed:
    decompress()

Furthermore, flag values can be enumerated:

>>> list(flag)
[IsBinary, IsCompressed]
>>> flag
IsBinary|IsCompressed

And finally, as visible from the above output, flag values are represented by their name by default.

Expand source code Browse git
class ArgVarFlags(FlagAccessMixin, enum.IntFlag):
    Empty = 0

    q = 0b0000_00001
    d = 0b0000_00010
    p = 0b0000_00100
    n = 0b0000_01000
    x = 0b0000_10000
    s = 0b0001_00000
    a = 0b0010_00000
    t = 0b0100_00000
    z = 0b1000_00000
    f = d | p | n | x

    StripQuotes   = q # noqa
    FullPath      = f # noqa
    DriveLetter   = d # noqa
    FilePath      = p # noqa
    FileName      = n # noqa
    FileExtension = x # noqa
    ShortName     = s # noqa
    Attributes    = a # noqa
    DateTime      = t # noqa
    FileSize      = z # noqa

    def __str__(self):
        options = self.__class__
        value = self.value
        string = ''
        for flag, char in (
            (options.q, '~'),
            (options.f, 'f'),
        ):
            if value & flag == flag:
                string += char
                value ^= flag
        for flag in options:
            if value & flag == flag:
                assert flag.name
                string += flag.name
        return string

    @classmethod
    def FromToken(cls, t: int):
        c = chr(t)
        if c == '~':
            return cls(1)
        if c == 'q':
            raise KeyError
        return cls[c]

Ancestors

  • FlagAccessMixin
  • enum.IntFlag
  • builtins.int
  • enum.ReprEnum
  • enum.Flag
  • enum.Enum

Class variables

var Empty

The type of the None singleton.

var q

The type of the None singleton.

var d

The type of the None singleton.

var p

The type of the None singleton.

var n

The type of the None singleton.

var x

The type of the None singleton.

var s

The type of the None singleton.

var a

The type of the None singleton.

var t

The type of the None singleton.

var z

The type of the None singleton.

var f

The type of the None singleton.

var StripQuotes

The type of the None singleton.

var FullPath

The type of the None singleton.

var DriveLetter

The type of the None singleton.

var FilePath

The type of the None singleton.

var FileName

The type of the None singleton.

var FileExtension

The type of the None singleton.

var ShortName

The type of the None singleton.

var Attributes

The type of the None singleton.

var DateTime

The type of the None singleton.

var FileSize

The type of the None singleton.

Static methods

def FromToken(t)
class ArgVar (offset=-1, path=None, flags=Empty)

ArgVar(offset: 'int | ellipsis' = -1, path: 'str | None' = None, flags: 'ArgVarFlags' = Empty)

Expand source code Browse git
@dataclass
class ArgVar:
    offset: int | ellipsis = -1
    path: str | None = None
    flags: ArgVarFlags = ArgVarFlags.Empty

    def __repr__(self):
        k = self.offset
        if k is (...):
            assert self.path is None
            assert self.flags is ArgVarFlags.Empty
            return '%*'
        elif k < 0:
            k = '?'
        p = F'${p}' if (p := self.path) is not None else ''
        return F'%{self.flags!s}{p}{k}'

    __str__ = __repr__

Instance variables

var offset

The type of the None singleton.

var path

The type of the None singleton.

var flags

The type of the None singleton.

class AstCondition (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class AstCondition(str, enum.Enum):
    NoCheck = '&'
    Success = '&&'
    Failure = '||'

    def __str__(self):
        return self.value

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var NoCheck

The type of the None singleton.

var Success

The type of the None singleton.

var Failure

The type of the None singleton.

class AstNode (offset, parent)

AstNode(offset: 'int', parent: 'AstNode | None')

Expand source code Browse git
@dataclass(repr=False)
class AstNode:
    offset: int
    parent: AstNode | None

    def is_descendant_of(self, ast: AstNode | None):
        parent = self.parent
        if parent is ast:
            return True
        if parent is None:
            return False
        return parent.is_descendant_of(ast)

    @cached_property
    def depth(self):
        if (p := self.parent) is None:
            return 0
        return 1 + p.depth

    def __repr__(self):
        try:
            synth = sys.modules['refinery.lib.batch.synth']
        except KeyError:
            return super().__repr__()
        else:
            return str(synth.synthesize(self))

Subclasses

Instance variables

var offset

The type of the None singleton.

var parent

The type of the None singleton.

var depth
Expand source code Browse git
@cached_property
def depth(self):
    if (p := self.parent) is None:
        return 0
    return 1 + p.depth

Methods

def is_descendant_of(self, ast)
Expand source code Browse git
def is_descendant_of(self, ast: AstNode | None):
    parent = self.parent
    if parent is ast:
        return True
    if parent is None:
        return False
    return parent.is_descendant_of(ast)
class AstError (offset, parent, token, error)

AstError(offset: 'int', parent: 'AstNode | None', token: 'str', error: 'str | None')

Expand source code Browse git
@dataclass(repr=False)
class AstError(AstNode):
    token: str
    error: str | None

Ancestors

Instance variables

var token

The type of the None singleton.

var error

The type of the None singleton.

Inherited members

class AstStatement (offset, parent, silenced)

AstStatement(offset: 'int', parent: 'AstNode | None', silenced: 'bool')

Expand source code Browse git
@dataclass(repr=False)
class AstStatement(AstNode):
    silenced: bool

Ancestors

Subclasses

Instance variables

var silenced

The type of the None singleton.

Inherited members

class AstLabel (offset, parent, silenced, line='', label='', comment=False)

AstLabel(offset: 'int', parent: 'AstNode | None', silenced: 'bool', line: 'str' = '', label: 'str' = '', comment: 'bool' = False)

Expand source code Browse git
@dataclass(repr=False)
class AstLabel(AstStatement):
    line: str = ''
    label: str = ''
    comment: bool = False

Ancestors

Instance variables

var line

The type of the None singleton.

var label

The type of the None singleton.

var comment

The type of the None singleton.

Inherited members

class AstCommand (offset, parent, silenced, redirects=<factory>, fragments=<factory>)

AstCommand(offset: 'int', parent: 'AstNode | None', silenced: 'bool', redirects: 'dict[int, RedirectIO]' = , fragments: 'list[str]' = )

Expand source code Browse git
@dataclass(repr=False)
class AstCommand(AstStatement):
    redirects: dict[int, RedirectIO] = field(default_factory=dict)
    fragments: list[str] = field(default_factory=list)

Ancestors

Instance variables

var redirects

The type of the None singleton.

var fragments

The type of the None singleton.

Inherited members

class AstGroup (offset, parent, silenced, redirects=<factory>, fragments=<factory>)

AstGroup(offset: 'int', parent: 'AstNode | None', silenced: 'bool', redirects: 'dict[int, RedirectIO]' = , fragments: 'list[AstSequence]' = )

Expand source code Browse git
@dataclass(repr=False)
class AstGroup(AstStatement):
    redirects: dict[int, RedirectIO] = field(default_factory=dict)
    fragments: list[AstSequence] = field(default_factory=list)

Ancestors

Instance variables

var redirects

The type of the None singleton.

var fragments

The type of the None singleton.

Inherited members

class AstPipeline (offset, parent, silenced, parts=<factory>)

AstPipeline(offset: 'int', parent: 'AstNode | None', silenced: 'bool', parts: 'list[AstCommand | AstGroup]' = )

Expand source code Browse git
@dataclass(repr=False)
class AstPipeline(AstStatement):
    parts: list[AstCommand | AstGroup] = field(default_factory=list)

Ancestors

Instance variables

var parts

The type of the None singleton.

Inherited members

class AstConditionalStatement (offset, parent, condition, statement)

AstConditionalStatement(offset: 'int', parent: 'AstNode | None', condition: 'AstCondition', statement: 'AstStatement')

Expand source code Browse git
@dataclass(repr=False)
class AstConditionalStatement(AstNode):
    condition: AstCondition
    statement: AstStatement

    def __repr__(self):
        return F'{self.condition.value} {self.statement!r}'

Ancestors

Instance variables

var condition

The type of the None singleton.

var statement

The type of the None singleton.

Inherited members

class AstSequence (offset, parent, head, tail=<factory>)

AstSequence(offset: 'int', parent: 'AstNode | None', head: 'AstStatement', tail: 'list[AstConditionalStatement]' = )

Expand source code Browse git
@dataclass(repr=False)
class AstSequence(AstNode):
    head: AstStatement
    tail: list[AstConditionalStatement] = field(default_factory=list)

Ancestors

Instance variables

var head

The type of the None singleton.

var tail

The type of the None singleton.

Inherited members

class AstForVariant (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class AstForVariant(str, enum.Enum):
    D = 'D'
    R = 'R'
    L = 'L'
    F = 'F'
    Default = ''
    MatchFolders = D
    DescendRecursively = R
    NumericLoop = L
    FileParsing = F

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var D

The type of the None singleton.

var R

The type of the None singleton.

var L

The type of the None singleton.

var F

The type of the None singleton.

var Default

The type of the None singleton.

var MatchFolders

The type of the None singleton.

var DescendRecursively

The type of the None singleton.

var NumericLoop

The type of the None singleton.

var FileParsing

The type of the None singleton.

class AstForParserMode (*args, **kwds)

Enum where members are also (and must be) ints

Expand source code Browse git
class AstForParserMode(enum.IntEnum):
    FileSet = 0
    Literal = 1
    Command = 2

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.ReprEnum
  • enum.Enum

Class variables

var FileSet

The type of the None singleton.

var Literal

The type of the None singleton.

var Command

The type of the None singleton.

class AstForOptions (comment=None, skip=0, tokens=(0,), asterisk=False, delims=' \t', usebackq=False)

AstForOptions(comment: 'str | None' = None, skip: 'int' = 0, tokens: 'tuple[int, …]' = (0,), asterisk: 'bool' = False, delims: 'str' = ' \t', usebackq: 'bool' = False)

Expand source code Browse git
@dataclass
class AstForOptions:
    comment: str | None = None
    skip: int = 0
    tokens: tuple[int, ...] = (0,)
    asterisk: bool = False
    delims: str = '\x20\t'
    usebackq: bool = False

Instance variables

var comment

The type of the None singleton.

var skip

The type of the None singleton.

var tokens

The type of the None singleton.

var asterisk

The type of the None singleton.

var delims

The type of the None singleton.

var usebackq

The type of the None singleton.

class AstFor (offset, parent, silenced, variant, variable, options, body, spec, spec_string, path, mode)

AstFor(offset: 'int', parent: 'AstNode | None', silenced: 'bool', variant: 'AstForVariant', variable: 'str', options: 'AstForOptions', body: 'AstSequence', spec: 'list[str] | batchrange', spec_string: 'str', path: 'str | None', mode: 'AstForParserMode')

Expand source code Browse git
@dataclass(repr=False)
class AstFor(AstStatement):
    variant: AstForVariant
    variable: str
    options: AstForOptions
    body: AstSequence
    spec: list[str] | batchrange
    spec_string: str
    path: str | None
    mode: AstForParserMode

    @property
    def specline(self):
        spec = self.spec
        if isinstance(spec, batchrange):
            raise AttributeError
        try:
            return spec[0]
        except IndexError:
            raise AttributeError

Ancestors

Instance variables

var variant

The type of the None singleton.

var variable

The type of the None singleton.

var options

The type of the None singleton.

var body

The type of the None singleton.

var spec

The type of the None singleton.

var spec_string

The type of the None singleton.

var path

The type of the None singleton.

var mode

The type of the None singleton.

var specline
Expand source code Browse git
@property
def specline(self):
    spec = self.spec
    if isinstance(spec, batchrange):
        raise AttributeError
    try:
        return spec[0]
    except IndexError:
        raise AttributeError

Inherited members

class AstIfVariant (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class AstIfVariant(str, enum.Enum):
    Defined = 'DEFINED'             # IF DEFINED VARIABLE
    CmdExtVersion = 'CMDEXTVERSION' # IF CMDEXTVERSION NUMBER
    Exist = 'EXIST'                 # IF EXIST PATH
    ErrorLevel = 'ERRORLEVEL'       # IF ERRORLEVEL NUMBER

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var Defined

The type of the None singleton.

var CmdExtVersion

The type of the None singleton.

var Exist

The type of the None singleton.

var ErrorLevel

The type of the None singleton.

class AstIfCmp (*args, **kwds)

str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.

Expand source code Browse git
class AstIfCmp(str, enum.Enum):
    STR = '=='
    EQU = 'EQU'
    NEQ = 'NEQ'
    LSS = 'LSS'
    LEQ = 'LEQ'
    GTR = 'GTR'
    GEQ = 'GEQ'

Ancestors

  • builtins.str
  • enum.Enum

Class variables

var STR

The type of the None singleton.

var EQU

The type of the None singleton.

var NEQ

The type of the None singleton.

var LSS

The type of the None singleton.

var LEQ

The type of the None singleton.

var GTR

The type of the None singleton.

var GEQ

The type of the None singleton.

class AstIf (offset, parent, silenced, then_do, else_do=None, variant=None, casefold=True, negated=False, cmp=None, lhs=None, rhs=None)

AstIf(offset: 'int', parent: 'AstNode | None', silenced: 'bool', then_do: 'AstSequence', else_do: 'AstSequence | None' = None, variant: 'AstIfVariant | None' = None, casefold: 'bool' = True, negated: 'bool' = False, cmp: 'AstIfCmp | None' = None, lhs: 'IntOrStr | None' = None, rhs: 'IntOrStr | None' = None)

Expand source code Browse git
@dataclass(repr=False)
class AstIf(AstStatement, Generic[IntOrStr]):
    then_do: AstSequence
    else_do: AstSequence | None = None
    variant: AstIfVariant | None = None
    casefold: bool = True
    negated: bool = False
    cmp: AstIfCmp | None = None
    lhs: IntOrStr | None = None
    rhs: IntOrStr | None = None

    @property
    def var_int(self):
        var = self.lhs
        if isinstance(var, int):
            return var
        raise AttributeError

    @property
    def var_str(self):
        var = self.lhs
        if isinstance(var, str):
            return var
        raise AttributeError

Ancestors

Instance variables

var then_do

The type of the None singleton.

var else_do

The type of the None singleton.

var variant

The type of the None singleton.

var casefold

The type of the None singleton.

var negated

The type of the None singleton.

var cmp

The type of the None singleton.

var lhs

The type of the None singleton.

var rhs

The type of the None singleton.

var var_int
Expand source code Browse git
@property
def var_int(self):
    var = self.lhs
    if isinstance(var, int):
        return var
    raise AttributeError
var var_str
Expand source code Browse git
@property
def var_str(self):
    var = self.lhs
    if isinstance(var, str):
        return var
    raise AttributeError

Inherited members

class If (*args, **kwds)

Support for integer-based Flags

Expand source code Browse git
class If(enum.IntFlag):
    Inactive = 0b0000
    Active = 0b0001
    Block = 0b0010
    Then = 0b0100
    Else = 0b1000

    def skip_block(self):
        skip = If.Then not in self
        if If.Else in self:
            skip = not skip
        return skip

Ancestors

  • enum.IntFlag
  • builtins.int
  • enum.ReprEnum
  • enum.Flag
  • enum.Enum

Class variables

var Inactive

The type of the None singleton.

var Active

The type of the None singleton.

var Block

The type of the None singleton.

var Then

The type of the None singleton.

var Else

The type of the None singleton.

Methods

def skip_block(self)
Expand source code Browse git
def skip_block(self):
    skip = If.Then not in self
    if If.Else in self:
        skip = not skip
    return skip
class MissingVariable (*args, **kwargs)

Base class for lookup errors.

Expand source code Browse git
class MissingVariable(LookupError):
    pass

Ancestors

  • builtins.LookupError
  • builtins.Exception
  • builtins.BaseException
class EmulatorException (*args, **kwargs)

Common base class for all non-exit exceptions.

Expand source code Browse git
class EmulatorException(Exception):
    pass

Ancestors

  • builtins.Exception
  • builtins.BaseException

Subclasses

class InputLocked (*args, **kwargs)

Common base class for all non-exit exceptions.

Expand source code Browse git
class InputLocked(EmulatorException):
    def __str__(self):
        return 'The emulation could not continue because a command is waiting for input.'

Ancestors

class AbortExecution (*args, **kwargs)

Common base class for all non-exit exceptions.

Expand source code Browse git
class AbortExecution(EmulatorException):
    pass

Ancestors

class EmulatorLongJump (*args, **kwargs)

Common base class for all non-exit exceptions.

Expand source code Browse git
class EmulatorLongJump(EmulatorException):
    pass

Ancestors

Subclasses

class Goto (label)

Common base class for all non-exit exceptions.

Expand source code Browse git
class Goto(EmulatorLongJump):
    def __init__(self, label: str):
        self.label = label

Ancestors

class Call (label, offset)

Common base class for all non-exit exceptions.

Expand source code Browse git
class Call(EmulatorLongJump):
    def __init__(self, label: str, offset: int):
        self.label = label
        self.offset = offset

Ancestors

class Exit (code, exit)

Common base class for all non-exit exceptions.

Expand source code Browse git
class Exit(EmulatorLongJump):
    def __init__(self, code: int, exit: bool):
        self.code = code
        self.exit = exit

Ancestors

class UnexpectedEOF (*args, **kwargs)

Read beyond end of file.

Expand source code Browse git
class UnexpectedEOF(EmulatorException, EOFError):
    pass

Ancestors

class UnexpectedToken (offset, token, error=None)

Common base class for all non-exit exceptions.

Expand source code Browse git
class UnexpectedToken(EmulatorException):
    def __init__(self, offset: int, token, error: str | None = None) -> None:
        if isinstance(token, int):
            token = chr(token)
        else:
            token = str(token)
        self.token = token
        self.error = error
        self.offset = offset

    def __str__(self):
        end = self.error and F': {self.error}' or '.'
        return F'The token "{self.token}" was unexpected{end}'

Ancestors

Subclasses

class UnexpectedFirstToken (offset, token)

Common base class for all non-exit exceptions.

Expand source code Browse git
class UnexpectedFirstToken(UnexpectedToken):
    def __init__(self, offset: int, token: str | int) -> None:
        super().__init__(offset, token, 'This token may not occur as the first token in a line.')

Ancestors

class InvalidLabel (label)

Common base class for all non-exit exceptions.

Expand source code Browse git
class InvalidLabel(EmulatorException):
    def __init__(self, label: str):
        self.label = label

    def __str__(self):
        return F'The following label was not found: {self.label}'

Ancestors