# HG changeset patch # User Laman # Date 2022-03-05 18:37:25 # Node ID d57d0d4ede15489391a9c4a22e2639b365aa9b9b # Parent cbabe0bae003c54392bf1cdcfa2826158785cc74 changed the naming convention to follow standards diff --git a/src/diana/config.py b/src/diana/config.py --- a/src/diana/config.py +++ b/src/diana/config.py @@ -2,10 +2,10 @@ import os from argparse import ArgumentParser -progName = "DianaXO" -version = (0, 1, 0) +PROG_NAME = "DianaXO" +VERSION = (0, 1, 0) -curDir = os.path.dirname(__file__) +cur_dir = os.path.dirname(__file__) parser = ArgumentParser() parser.add_argument("--encoding") @@ -17,34 +17,34 @@ parser.add_argument("--format", choices= parser.add_argument("-k", "--keep-broken") parser.add_argument("--moves-p-d", type=int) parser.add_argument("--min-p-d", type=int) -parser.add_argument("--version", action="version", version="{0} {1}.{2}.{3}".format(progName, *version)) +parser.add_argument("--version", action="version", version="{0} {1}.{2}.{3}".format(PROG_NAME, *VERSION)) -inputFiles = [] +input_files = [] encoding = "utf-8-sig" -sgfSuffix = True +sgf_suffix = True recursive = False -outputDir = curDir -outputFormat = "svg" -keepBroken = False +output_dir = cur_dir +output_format = "svg" +keep_broken = False -movesPerDiagram = 100 -minMovesPerDiagram = 10 +moves_per_diagram = 100 +min_moves_per_diagram = 10 -def parseArgs(): - global inputFiles, encoding, sgfSuffix, recursive, outputDir, outputFormat, keepBroken, movesPerDiagram - global minMovesPerDiagram +def parse_args(): + global input_files, encoding, sgf_suffix, recursive, output_dir, output_format, keep_broken, moves_per_diagram + global min_moves_per_diagram - args=parser.parse_args() + args = parser.parse_args() - inputFiles=args.input + input_files = args.input if args.encoding: encoding = args.encoding - if args.suffix: sgfSuffix = True + if args.suffix: sgf_suffix = True if args.recursive: recursive = True - if args.output: outputDir = args.output - if args.format: outputFormat = args.format - if args.keep_broken is not None: keepBroken = True + if args.output: output_dir = args.output + if args.format: output_format = args.format + if args.keep_broken is not None: keep_broken = True - if args.moves_p_d: movesPerDiagram = args.moves_p_d - if args.min_p_d: minMovesPerDiagram = args.min_p_d + if args.moves_p_d: moves_per_diagram = args.moves_p_d + if args.min_p_d: min_moves_per_diagram = args.min_p_d diff --git a/src/diana/diana.py b/src/diana/diana.py --- a/src/diana/diana.py +++ b/src/diana/diana.py @@ -3,18 +3,18 @@ import re from . import config as cfg from . import go -from .go import BLACK,WHITE,EMPTY +from .go import BLACK, WHITE, EMPTY from .sgfParser import ParserError from .sgfParser.collection import Collection from .drawer.svg import Svg from .drawer.tikz import Tikz -def collectMoves(root): +def collect_moves(root): node = root while len(node.children) > 0: - b = node.getProp("B") - w = node.getProp("W") + b = node.get_prop("B") + w = node.get_prop("W") if b is not None: yield ("b", b) elif w is not None: @@ -25,46 +25,46 @@ def collectMoves(root): class SourceFile: - def __init__(self, fileName): - self.fileName = fileName - self._shortName = "".join(re.split(r'[/\\]', fileName)[-1].split('.')[:-1]) + def __init__(self, file_name): + self.file_name = file_name + self._short_name = "".join(re.split(r'[/\\]', file_name)[-1].split('.')[:-1]) self._game = go.Go() - with open(self.fileName, 'r', encoding=cfg.encoding) as f: - games = Collection(f.read()).listGames() + with open(self.file_name, 'r', encoding=cfg.encoding) as f: + games = Collection(f.read()).list_games() self._record = list(games)[0] - self._moves = list(collectMoves(self._record.root)) + self._moves = list(collect_moves(self._record.root)) def process(self): - print("{0}... ".format(self.fileName), end="") + print("{0}... ".format(self.file_name), end="") i = 1 - for k in range(0,len(self._moves), cfg.movesPerDiagram): - filename = os.path.join(cfg.outputDir, "{0}-{1}".format(self._shortName, i)) - self.createDiagram(k, k+cfg.movesPerDiagram).save(filename, "templ-pleb.svg") + for k in range(0, len(self._moves), cfg.moves_per_diagram): + filename = os.path.join(cfg.output_dir, "{0}-{1}".format(self._short_name, i)) + self.create_diagram(k, k + cfg.moves_per_diagram).save(filename, "templ-pleb.svg") i += 1 - infoStr = """{GN} + info_str = """{GN} B: {PB} {BR} W: {PW} {WR} {DT} -{RE}""".format(**self.fetchGameInfo(["GN","PB","BR","PW","WR","DT","RE"], "")) - notes = open(os.path.join(cfg.outputDir, "{0}.txt".format(self._shortName)), 'w') - notes.write(infoStr) +{RE}""".format(**self.fetch_game_info(["GN", "PB", "BR", "PW", "WR", "DT", "RE"], "")) + notes = open(os.path.join(cfg.output_dir, "{0}.txt".format(self._short_name)), 'w') + notes.write(info_str) notes.close() print("done") - def createDiagram(self, start, end): + def create_diagram(self, start, end): # initialize the diagram template = Svg() - self._setMove(start) + self._set_move(start) # draw current state - for lineNumber, line in enumerate(self._game.board): - for itemNumber, item in enumerate(line): + for (line_number, line) in enumerate(self._game.board): + for (item_number, item) in enumerate(line): if item != EMPTY: - template.addStone(itemNumber, lineNumber, "b" if item==BLACK else "w") + template.add_stone(item_number, line_number, "b" if item == BLACK else "w") # draw the moves for k in range(start, end): @@ -73,35 +73,35 @@ W: {PW} {WR} color, move = self._moves[k] if move == tuple(): - template.overlays.append((k, "pass")) # !! + template.overlays.append((k, "pass")) # !! continue else: (c, r) = move if not self._move(color, c, r): - if cfg.keepBroken: + if cfg.keep_broken: continue else: return False # draw the move - template.addMove(c, r, color, k+1) + template.add_move(c, r, color, k + 1) return template - def fetchGameInfo(self, fieldNames, default=None): - return {k: self._record.get(k, default) for k in fieldNames} + def fetch_game_info(self, field_names, default=None): + return {k: self._record.get(k, default) for k in field_names} - def _setMove(self, k): + def _set_move(self, k): self._game = go.Go() - blackStones = self._record.root.getProp("AB") - whiteStones = self._record.root.getProp("AW") - if blackStones: - for p in blackStones: + black_stones = self._record.root.get_prop("AB") + white_stones = self._record.root.get_prop("AW") + if black_stones: + for p in black_stones: self._game.board[p.r][p.c] = BLACK - if whiteStones: - for p in whiteStones: + if white_stones: + for p in white_stones: self._game.board[p.r][p.c] = WHITE for i in range(k): @@ -113,8 +113,8 @@ W: {PW} {WR} def _move(self, color, c, r): if not self._game.move(BLACK if color=='b' else WHITE, c, r): # !! we do not honor http://red-bean.com/sgf/ff5/m_vs_ax.htm at the moment - msg = "illegal move: {0} at {1},{2}".format(self._game.moveCount+1, c, r) - if cfg.keepBroken: + msg = "illegal move: {0} at {1},{2}".format(self._game.move_count + 1, c, r) + if cfg.keep_broken: print(msg) else: msg += ". aborted" @@ -124,9 +124,9 @@ W: {PW} {WR} def main(): - cfg.parseArgs() + cfg.parse_args() print("processing:") - files = cfg.inputFiles[:] + files = cfg.input_files[:] for item in files: if os.path.isfile(item): diff --git a/src/diana/drawer/base.py b/src/diana/drawer/base.py --- a/src/diana/drawer/base.py +++ b/src/diana/drawer/base.py @@ -16,31 +16,31 @@ class DiagramPoint: class Base: - highNumbers = True + high_numbers = True def __init__(self, start=0): self.overlays = [] self._letter = "a" self._index = dict() - self._indexGen = count(start) + self._index_gen = count(start) - curDir = os.path.dirname(__file__) - templateDir = os.path.join(curDir, "..", "templ") - self._env = Environment(loader=FileSystemLoader(templateDir)) + cur_dir = os.path.dirname(__file__) + template_dir = os.path.join(cur_dir, "..", "templ") + self._env = Environment(loader=FileSystemLoader(template_dir)) self._env.trim_blocks = True self._env.lstrip_blocks = True - def addStone(self, x, y, color): + def add_stone(self, x, y, color): assert (x, y) not in self._index - self._index[(x, y)] = (next(self._indexGen), DiagramPoint(x, y, color)) + self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, color)) - def addMove(self, x, y, color, label): - if (not self.highNumbers) and isinstance(label, int) and label%100 != 0: + def add_move(self, x, y, color, label): + if (not self.high_numbers) and isinstance(label, int) and label%100 != 0: label %= 100 if (x, y) not in self._index: - self._index[(x, y)] = (next(self._indexGen), DiagramPoint(x, y, color, label)) + self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, color, label)) else: (_, point) = self._index[(x, y)] if not point.label: @@ -48,10 +48,10 @@ class Base: self._letter = chr(ord(self._letter)+1) self.overlays.append((label, point.label)) - def addLabel(self, x, y, label): - self._index[(x, y)] = (next(self._indexGen), DiagramPoint(x, y, "", label)) + def add_label(self, x, y, label): + self._index[(x, y)] = (next(self._index_gen), DiagramPoint(x, y, "", label)) def save(self, filename): - notes=open(filename+".txt", 'w') + notes = open(filename+".txt", 'w') notes.write("\n".join("{0} = {1}".format(a, b) for (a, b) in self.overlays)) notes.close() diff --git a/src/diana/drawer/svg.py b/src/diana/drawer/svg.py --- a/src/diana/drawer/svg.py +++ b/src/diana/drawer/svg.py @@ -1,7 +1,7 @@ from .base import Base -def adjustFont(base,text): +def adjust_font(base, text): text = str(text) if len(text) < 2: return round(0.7*base) @@ -15,14 +15,14 @@ class Svg(Base): extension = "svg" padding = 15 - highNumbers = True + high_numbers = True def __init__(self, start=0): super().__init__(start) self.boardSize = 480 self.padding = 30 - def render(self, templateName, bgcolor=""): + def render(self, template_name, bgcolor=""): points = [p for (i, p) in sorted(self._index.values(), key=lambda x: x[0])] stones = [p for p in points if p.color and p.label == ""] @@ -31,9 +31,9 @@ class Svg(Base): params = { "boardSize": self.boardSize, "padding": self.padding, "stones": stones, "moves": moves, - "labels": labels, "adjustFont": adjustFont, "bgcolor": bgcolor} + "labels": labels, "adjustFont": adjust_font, "bgcolor": bgcolor} - return self._env.get_template(templateName).render(params) + return self._env.get_template(template_name).render(params) def save(self, filename, template="templ.svg", bgcolor=""): file = open(filename+".svg", 'w') diff --git a/src/diana/drawer/tikz.py b/src/diana/drawer/tikz.py --- a/src/diana/drawer/tikz.py +++ b/src/diana/drawer/tikz.py @@ -3,7 +3,7 @@ class Tikz: footer = "" extension = "tex" - highNumbers = True + high_numbers = True def __init__(self): self.content = r'''\begin{tikzpicture} @@ -23,17 +23,17 @@ class Tikz: def __str__(self): return self.content+self.footer - def drawStone(self, x, y, color): + def draw_stone(self, x, y, color): fill = "black" if color == "b" else "white" self.content += r' \filldraw[draw=black, fill={0}] ({1}\boardSquare, {2}\boardSquare) circle[radius=0.5\boardSquare];'.format(fill, x, 18-y)+'\n' - def drawMove(self, x, y, label, color): + def draw_move(self, x, y, label, color): fill = "black" if color == "b" else "white" - labelColor = "white" if color == "b" else "black" - if (not self.highNumbers) and isinstance(label, int) and label%100 != 0: + label_color = "white" if color == "b" else "black" + if (not self.high_numbers) and isinstance(label, int) and label%100 != 0: label = label%100 - self.content += r' \filldraw[draw=black, fill={0}] ({1}\boardSquare, {2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill, x, 18-y, labelColor, label)+'\n' + self.content += r' \filldraw[draw=black, fill={0}] ({1}\boardSquare, {2}\boardSquare) circle[radius=0.5\boardSquare] node[color={3}]{{{4}}};'.format(fill, x, 18-y, label_color, label)+'\n' - def getContent(self): + def get_content(self): return self.content+self.footer diff --git a/src/diana/go.py b/src/diana/go.py --- a/src/diana/go.py +++ b/src/diana/go.py @@ -8,7 +8,8 @@ class Go: def __init__(self): self.board = [[EMPTY]*19 for i in range(19)] - self.moveCount = 0 + self.move_count = 0 + self.temp = [[]] def move(self, color, y, x): if self.board[x][y] != EMPTY: @@ -18,16 +19,16 @@ class Go: for i, j in ((-1, 0), (1, 0), (0, -1), (0, 1)): self.temp = [[False]*19 for i in range(19)] - if not self._floodFill(-color, x+i, y+j): + if not self._flood_fill(-color, x + i, y + j): self._remove() self.temp = [[False]*19 for i in range(19)] - if not self._floodFill(color, x, y): + if not self._flood_fill(color, x, y): self.board[x][y] = EMPTY return False - self.moveCount += 1 + self.move_count += 1 return True - def _floodFill(self, color, x, y): + def _flood_fill(self, color, x, y): if x < 0 or x > 18 or y < 0 or y > 18: return False if self.temp[x][y]: @@ -38,10 +39,10 @@ class Go: return False self.temp[x][y] = True - return self._floodFill(color, x-1, y) or \ - self._floodFill(color, x+1, y) or \ - self._floodFill(color, x, y-1) or \ - self._floodFill(color, x, y+1) + return self._flood_fill(color, x - 1, y) or \ + self._flood_fill(color, x + 1, y) or \ + self._flood_fill(color, x, y - 1) or \ + self._flood_fill(color, x, y + 1) def _remove(self): for i in range(19): diff --git a/src/diana/sgfParser/__init__.py b/src/diana/sgfParser/__init__.py --- a/src/diana/sgfParser/__init__.py +++ b/src/diana/sgfParser/__init__.py @@ -1,12 +1,12 @@ -def skipWhitespace(s, start): +def skip_whitespace(s, start): i = start while i < len(s) and s[i].isspace(): - i+=1 + i += 1 return i -def strRowCol(s, i): +def str_row_col(s, i): k = 0 (r, c) = (0, 0) for (r, line) in enumerate(s.splitlines(True)): @@ -21,7 +21,7 @@ def strRowCol(s, i): class ParserError(Exception): def __init__(self, msg, s, i): self.msg = msg - (self.row, self.col) = strRowCol(s, i) + (self.row, self.col) = str_row_col(s, i) self.context = s[i:i+16] def __str__(self): diff --git a/src/diana/sgfParser/collection.py b/src/diana/sgfParser/collection.py --- a/src/diana/sgfParser/collection.py +++ b/src/diana/sgfParser/collection.py @@ -1,25 +1,25 @@ from .node import Node -from . import skipWhitespace, ParserError +from . import skip_whitespace, ParserError from .gameRecord import GameRecord class Collection: def __init__(self, s): - self.gameTrees = [] - i = skipWhitespace(s, 0) + self.game_trees = [] + i = skip_whitespace(s, 0) if i >= len(s): return elif not GameTree.fits(s, i): raise ParserError("expected a GameTree starting with '('", s, i) while GameTree.fits(s, i): (i, x) = GameTree.create(s, i) - self.gameTrees.append(x) + self.game_trees.append(x) if i < len(s): raise ParserError("expected EOF", s, i) - def listGames(self): - for tree in self.gameTrees: - for game in tree.listGames(): + def list_games(self): + for tree in self.game_trees: + for game in tree.list_games(): yield game @@ -37,7 +37,7 @@ class GameTree: assert GameTree.fits(s, start) res = GameTree() - i = skipWhitespace(s, start+1) + i = skip_whitespace(s, start + 1) if not Node.fits(s, i): raise ParserError("expected a Node starting with ';'", s, i) @@ -46,48 +46,48 @@ class GameTree: (i, x) = Node.create(s, i) res.nodes.append(x) if y: - y.addChild(x) + y.add_child(x) x.parent = y y = x - i = skipWhitespace(s, i) + i = skip_whitespace(s, i) while GameTree.fits(s, i): (i, x) = GameTree.create(s, i) res.branches.append(x) - subroot = x.getNode(0) + subroot = x.get_node(0) subroot.parent = y if y: - y.addChild(subroot) - i = skipWhitespace(s, i) + y.add_child(subroot) + i = skip_whitespace(s, i) if i >= len(s) or s[i] != ")": raise ParserError("expected end of a GameTree marked by ')'", s, i) - i = skipWhitespace(s, i+1) + i = skip_whitespace(s, i + 1) return (i, res) ## Expand multiple games into distinct GameTrees and yield each. - def listGames(self): + def list_games(self): if len(self.nodes) == 0: return None - for node in self.nodes[0].listGINodes(): - yield GameRecord(self._buildSubtree(node)) + for node in self.nodes[0].list_gi_nodes(): + yield GameRecord(self._build_subtree(node)) - def getNode(self, i): + def get_node(self, i): if 0 <= i < len(self.nodes): return self.nodes[i] return None ## Create and return a new game tree containing the provided Node. # - # Ancestor nodes are copied, descendants are moved from the seedNode. - def _buildSubtree(self, seedNode): - node = seedNode.copy() - node.setChildren(seedNode.children) - seedNode.children = [] + # Ancestor nodes are copied, descendants are moved from the seed_node. + def _build_subtree(self, seed_node): + node = seed_node.copy() + node.set_children(seed_node.children) + seed_node.children = [] while node.parent: - newNode = node.parent.copy() - newNode.addChild(node) - node = newNode + new_node = node.parent.copy() + new_node.add_child(node) + node = new_node return node diff --git a/src/diana/sgfParser/gameRecord.py b/src/diana/sgfParser/gameRecord.py --- a/src/diana/sgfParser/gameRecord.py +++ b/src/diana/sgfParser/gameRecord.py @@ -5,13 +5,13 @@ from .node import Node class GameRecord: def __init__(self, root=None): self.root = root or Node() - self._gameInfoNode = next(root.listGINodes()) + self._game_info_node = next(root.list_gi_nodes()) def export(self): return self.root.export() def set(self, name, value): - self._gameInfoNode.setProp(name, value) + self._game_info_node.set_prop(name, value) def get(self, name, default=None): - return self._gameInfoNode.getProp(name, default) + return self._game_info_node.get_prop(name, default) diff --git a/src/diana/sgfParser/node.py b/src/diana/sgfParser/node.py --- a/src/diana/sgfParser/node.py +++ b/src/diana/sgfParser/node.py @@ -1,7 +1,7 @@ from collections import deque import logging as log -from . import skipWhitespace, ParserWarning +from . import skip_whitespace, ParserWarning from .property import Property, GAME_INFO @@ -20,65 +20,65 @@ class Node: assert Node.fits(s, start) res = Node() - i = skipWhitespace(s, start+1) + i = skip_whitespace(s, start + 1) while Property.fits(s, i): (i, x) = Property.create(s, i) if x.name in res.properties: log.warning(ParserWarning('duplicate "{0}" property in a node. second value ignored'.format(x.name), s, i)) else: res.properties[x.name] = x - i = skipWhitespace(s, i) + i = skip_whitespace(s, i) return (i, res) - def listGINodes(self): - if self.isGINode(): + def list_gi_nodes(self): + if self.is_gi_node(): yield self - empty = not self.isGINode() + empty = not self.is_gi_node() node = self while node.parent: node = node.parent - if node.isGINode(): + if node.is_gi_node(): empty = False yield node queue = deque(self.children) while len(queue) > 0: node = queue.popleft() - if node.isGINode(): + if node.is_gi_node(): empty = False yield node queue.extend(node.children) if empty: yield self # always yield at least self, can work as GINode as well as any other - def isGINode(self): + def is_gi_node(self): return any(prop.type == GAME_INFO for prop in self.properties.values()) - def setProp(self, name, value): + def set_prop(self, name, value): self.properties[name] = value # check value type - def setChildren(self, children): + def set_children(self, children): self.children = children for child in children: child.parent = self - def addChild(self, node): + def add_child(self, node): if node in self.children: return node node.parent = self self.children.append(node) return node - def removeChild(self, node): + def remove_child(self, node): if node not in self.children: return None del self.children[self.children.index(node)] node.parent = None return node - def removeChildAt(self, i): + def remove_child_at(self, i): if -len(self.children) < i < len(self.children): res = self.children[i] del self.children[i] @@ -93,7 +93,7 @@ class Node: res.parent = self.parent return res - def getProp(self, name, default=None): + def get_prop(self, name, default=None): if name in self.properties: return self.properties[name].value else: @@ -114,14 +114,14 @@ class Node: output.append("("*left) output.append(str(node)+"\n") - childCount = len(node.children) - if childCount == 0: # a leaf + child_count = len(node.children) + if child_count == 0: # a leaf output.append(")"*right+"\n") - elif childCount == 1: # a line + elif child_count == 1: # a line stack.append((node.children[0], 0, right)) else: # a branching node # first child pops first, last child closes parent's parentheses - children = zip(node.children, [1]*childCount, [1]*(childCount-1)+[1+right]) + children = zip(node.children, [1]*child_count, [1]*(child_count-1)+[1+right]) stack.extend(reversed(list(children))) return "".join(output) diff --git a/src/diana/sgfParser/propValues.py b/src/diana/sgfParser/propValues.py --- a/src/diana/sgfParser/propValues.py +++ b/src/diana/sgfParser/propValues.py @@ -1,6 +1,6 @@ import re -from . import ParserError, skipWhitespace +from . import ParserError, skip_whitespace class Regexp: @@ -8,14 +8,14 @@ class Regexp: real = re.compile(r"(\+|-|)\d+(\.\d+)?") point = re.compile(r"[a-zA-Z]{2}|") text = re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=])", re.DOTALL) - composedText = re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=]|:)", re.DOTALL) + composed_text = re.compile(r"(?:.*?[^\\])??(?:\\\\)*(?=]|:)", re.DOTALL) class Text: - softBreaks = re.compile(r"(^|[^\\])((\\\\)*)\\((\n\r)|(\r\n)|\r|\n)") + soft_breaks = re.compile(r"(^|[^\\])((\\\\)*)\\((\n\r)|(\r\n)|\r|\n)") whitespace = re.compile(r"[\t\f\v]") - simpleWhitespace = re.compile(r"[\t\f\v\n\r]") - removeSlashes = re.compile(r"(^|[^\\])((\\\\)*)\\($|[^\\])") - unescapeSlashes = re.compile(r"\\\\") + simple_whitespace = re.compile(r"[\t\f\v\n\r]") + remove_slashes = re.compile(r"(^|[^\\])((\\\\)*)\\($|[^\\])") + unescape_slashes = re.compile(r"\\\\") class Composed: @@ -44,9 +44,9 @@ class Point: ## Metatype matching one of the provided types. # # Returns the first match, so the order is important. -def choose(*vTypes): +def choose(*v_types): def f(s, start): - for vType in vTypes: + for vType in v_types: try: (i, x) = vType(s, start) return (i, x) @@ -56,50 +56,50 @@ def choose(*vTypes): return f -def singletonFits(s, i): +def singleton_fits(s, i): return i < len(s) and s[i] == "[" -def singletonEnds(s, i): +def singleton_ends(s, i): return i < len(s) and s[i] == "]" -def singleton(vType): +def singleton(v_type): def f(s, start): - if not singletonFits(s, start): + if not singleton_fits(s, start): raise ParserError("expected a property value starting with '['", s, start) - (i, x) = vType(s, start+1) - if not singletonEnds(s, i): + (i, x) = v_type(s, start + 1) + if not singleton_ends(s, i): raise ParserError("expected a property value ending with ']'", s, i) - i = skipWhitespace(s, i+1) + i = skip_whitespace(s, i + 1) return (i, x) return f -def listOf(vType, allowEmpty=False): +def list_of(v_type, allow_empty=False): def f(s, start): i = start - if not singletonFits(s, i): + if not singleton_fits(s, i): raise ParserError("expected a property value starting with '['", s, i) - if singletonEnds(s, i+1) and allowEmpty: - i = skipWhitespace(s, i+2) + if singleton_ends(s, i + 1) and allow_empty: + i = skip_whitespace(s, i + 2) return (i, []) - single = singleton(vType) + single = singleton(v_type) (i, x) = single(s, i) res = [x] - while singletonFits(s, i): + while singleton_fits(s, i): (i, x) = single(s, i) res.append(x) return (i, res) return f -def compose(vTypeA, vTypeB): +def compose(v_type_a, v_type_b): def f(s, start): - (i, a) = vTypeA(s, start) + (i, a) = v_type_a(s, start) if i >= len(s) or s[i] != ":": raise ParserError("expected a composed property value separated by ':'", s, i) - (i, b) = vTypeB(s, i+1) + (i, b) = v_type_b(s, i + 1) return (i, Composed(a, b)) return f @@ -137,15 +137,15 @@ def color(s,start): def text(simple=True, composed=False): def f(s, start): regexps = Regexp.Text - m = Regexp.composedText.match(s, start) if composed else Regexp.text.match(s, start) + m = Regexp.composed_text.match(s, start) if composed else Regexp.text.match(s, start) res = m.group(0) - res = regexps.softBreaks.sub(r"\1\2", res) # remove soft line breaks + res = regexps.soft_breaks.sub(r"\1\2", res) # remove soft line breaks if simple: - res = regexps.simpleWhitespace.sub(" ", res) # convert whitespace to spaces, no escapes + res = regexps.simple_whitespace.sub(" ", res) # convert whitespace to spaces, no escapes else: res = regexps.whitespace.sub(" ", res) # convert whitespace to spaces, no escapes - res = regexps.removeSlashes.sub(r"\1\2\4", res) - res = regexps.unescapeSlashes.sub(r"\\", res) # unescape slashes + res = regexps.remove_slashes.sub(r"\1\2\4", res) + res = regexps.unescape_slashes.sub(r"\\", res) # unescape slashes return (m.end(), res) return f diff --git a/src/diana/sgfParser/property.py b/src/diana/sgfParser/property.py --- a/src/diana/sgfParser/property.py +++ b/src/diana/sgfParser/property.py @@ -2,8 +2,8 @@ import re from datetime import date import logging as log -from .propValues import choose, singleton, listOf, compose, number, real, double, color, text, empty, anything, point, move, stone -from . import skipWhitespace, ParserError +from .propValues import choose, singleton, list_of, compose, number, real, double, color, text, empty, anything, point, move, stone +from . import skip_whitespace, ParserError GAME_INFO = 1 UNKNOWN = 99 @@ -14,7 +14,7 @@ class DateException(Exception): class Property: - identRegexp = re.compile(r"[A-Z]+") + ident_regexp = re.compile(r"[A-Z]+") def __init__(self): self.name = "" @@ -29,38 +29,38 @@ class Property: assert Property.fits(s, start) res = Property() (i, res.name) = Property.ident(s, start) - i = skipWhitespace(s, i) + i = skip_whitespace(s, i) try: - (i, x) = Property.createValue(s, i, res.name) + (i, x) = Property.create_value(s, i, res.name) except ParserError as e: # a malformed value log.warning(e) - (i, x) = choose(listOf(anything), singleton(anything))(s, i) + (i, x) = choose(list_of(anything), singleton(anything))(s, i) res.name = "_"+res.name res.value = x if res.name == "DT": res = DateProperty(x) - i = skipWhitespace(s, i) + i = skip_whitespace(s, i) return (i, res) @staticmethod def ident(s, start): - m = Property.identRegexp.match(s, start) + m = Property.ident_regexp.match(s, start) if m is None: raise ParserError("expected a property identifier matching '[A-Z]+'", s, start) return (m.end(), m.group()) @staticmethod - def createValue(s, start, name): + def create_value(s, start, name): if name in Property.patterns: return Property.patterns[name](s, start) else: log.info("unknown property %s at position %d", name, start) - return choose(listOf(anything), singleton(anything))(s, start) + return choose(list_of(anything), singleton(anything))(s, start) @property def type(self): - gameInfo = {"AN", "BR", "BT", "CP", "DT", "EV", "GN", "GC", "ON", "OT", "PB", "PC", "PW", "RE", "RO", "RU", "SO", "TM", "US", "WR", "WT"} - if self.name in gameInfo: + game_info = {"AN", "BR", "BT", "CP", "DT", "EV", "GN", "GC", "ON", "OT", "PB", "PC", "PW", "RE", "RO", "RU", "SO", "TM", "US", "WR", "WT"} + if self.name in game_info: return GAME_INFO else: return UNKNOWN @@ -83,9 +83,9 @@ class Property: "KO": singleton(empty), "MN": singleton(number), "W": singleton(move), - "AB": listOf(stone), # - "AE": listOf(point), # - "AW": listOf(stone), # + "AB": list_of(stone), # + "AE": list_of(point), # + "AW": list_of(stone), # "PL": singleton(color), "C": singleton(text(simple=False)), "DM": singleton(double), @@ -99,15 +99,15 @@ class Property: "DO": singleton(empty), "IT": singleton(empty), "TE": singleton(double), - "AR": listOf(compose(point, point)), # - "CR": listOf(point), # - "DD": listOf(point, allowEmpty=True), # - "LB": listOf(compose(point, text())), # - "LN": listOf(compose(point, point)), # - "MA": listOf(point), # - "SL": listOf(point), # - "SQ": listOf(point), # - "TR": listOf(point), # + "AR": list_of(compose(point, point)), # + "CR": list_of(point), # + "DD": list_of(point, allow_empty=True), # + "LB": list_of(compose(point, text())), # + "LN": list_of(compose(point, point)), # + "MA": list_of(point), # + "SL": list_of(point), # + "SQ": list_of(point), # + "TR": list_of(point), # "AP": singleton(compose(text(composed=True), text())), # "CA": singleton(text()), "FF": singleton(number), @@ -141,13 +141,13 @@ class Property: "WL": singleton(real), "FG": choose(singleton(empty), singleton(compose(number, text()))), # "PM": singleton(number), - "VW": listOf(point, allowEmpty=True), # + "VW": list_of(point, allow_empty=True), # # go specific "HA": singleton(number), "KM": singleton(real), - "TB": listOf(point, allowEmpty=True), - "TW": listOf(point, allowEmpty=True) + "TB": list_of(point, allow_empty=True), + "TW": list_of(point, allow_empty=True) } @@ -156,7 +156,7 @@ class DateProperty(Property): super().__init__() self.name = "DT" self.value = [] - self.rawValue = value + self.raw_value = value self.parse(value) def parse(self, s): @@ -165,21 +165,21 @@ class DateProperty(Property): if not match: raise DateException('Could not parse a DT value: "{0}"'.format(s)) substr = match.group(0) - dateStrs = substr.split(",") + date_strs = substr.split(",") dates = [] - prevFormat = None + prev_format = None - for s in dateStrs: + for s in date_strs: try: - (prevFormat, d) = DateProperty.parseSingle(s, prevFormat, dates[-1] if dates else None) + (prev_format, d) = DateProperty.parse_single(s, prev_format, dates[-1] if dates else None) except ValueError: raise DateException('Could not parse a DT value: "{0}"'.format(s)) dates.append(d) self.value = dates @staticmethod - def parseSingle(dateStr, prevFormat, prev=None): - tokens = dateStr.split("-") + def parse_single(date_str, prev_format, prev=None): + tokens = date_str.split("-") num_tokens = list(map(int, tokens)) if len(tokens) == 3: return ("YMD", date(*num_tokens)) @@ -191,7 +191,7 @@ class DateProperty(Property): else: if len(tokens[0]) == 4: return ("Y", date(*num_tokens, 1, 1)) - elif prevFormat in ("YM","M"): + elif prev_format in ("YM", "M"): return ("M", date(prev.year, *num_tokens, 1)) else: return ("D", date(prev.year, prev.month, *num_tokens)) diff --git a/src/diana/tests/testSgfParser.py b/src/diana/tests/testSgfParser.py --- a/src/diana/tests/testSgfParser.py +++ b/src/diana/tests/testSgfParser.py @@ -4,7 +4,7 @@ import unittest from unittest import TestCase import os -from ..sgfParser import strRowCol +from ..sgfParser import str_row_col from ..sgfParser.collection import Collection from ..sgfParser.property import Property, DateProperty, DateException from ..sgfParser.propValues import text, compose @@ -25,7 +25,7 @@ class TestUtils(TestCase): ] res = chain((r+1, c) for (r, row) in enumerate(rc) for c in row) for (i, (r, c)) in zip(range(len(s)+1), res): - self.assertEqual(strRowCol(s, i), (r, c)) + self.assertEqual(str_row_col(s, i), (r, c)) class TestProperty(TestCase): @@ -57,15 +57,15 @@ ghi]""" class TestDateProperty(TestCase): def testSingle(self): - self.assertEqual(DateProperty.parseSingle("2019", "Y")[1], date(2019, 1, 1)) - self.assertEqual(DateProperty.parseSingle("2019-06", "YM")[1], date(2019, 6, 1)) - self.assertEqual(DateProperty.parseSingle("2019-06-22", "YMD")[1], date(2019, 6, 22)) + self.assertEqual(DateProperty.parse_single("2019", "Y")[1], date(2019, 1, 1)) + self.assertEqual(DateProperty.parse_single("2019-06", "YM")[1], date(2019, 6, 1)) + self.assertEqual(DateProperty.parse_single("2019-06-22", "YMD")[1], date(2019, 6, 22)) d = date(2019, 6, 21) - self.assertEqual(DateProperty.parseSingle("22", "D", d)[1], date(2019, 6, 22)) - self.assertEqual(DateProperty.parseSingle("07-22", "MD", d)[1], date(2019, 7, 22)) - self.assertEqual(DateProperty.parseSingle("2020-07-22", "YMD", d)[1], date(2020, 7, 22)) + self.assertEqual(DateProperty.parse_single("22", "D", d)[1], date(2019, 6, 22)) + self.assertEqual(DateProperty.parse_single("07-22", "MD", d)[1], date(2019, 7, 22)) + self.assertEqual(DateProperty.parse_single("2020-07-22", "YMD", d)[1], date(2020, 7, 22)) with self.assertRaises(ValueError): - DateProperty.parseSingle("2019-31", "YMD") + DateProperty.parse_single("2019-31", "YMD") def testParse(self): self.assertEqual(DateProperty("1996-05,06").value, [date(1996, 5, 1), date(1996, 6, 1)]) @@ -85,7 +85,7 @@ class TestCollection(TestCase): (;W[ab]PB[Some Black]PW[Some White];B[ac]) (;W[bb]PB[Other Black]PW[Other White]) )""") - games = list(c.listGames()) + games = list(c.list_games()) self.assertEqual(len(games), 2) self.assertRegex(games[0].export(), r"^\(;B\[aa]\n;(PB\[Some Black]|PW\[Some White]|W\[ab]){3}\n;B\[ac]\n\)\n$")