Changeset - e3e6dfbb44f6
[Not reviewed]
default
0 3 0
Laman - 6 years ago 2019-10-14 22:36:58

date property, minor tweaks
3 files changed with 79 insertions and 10 deletions:
0 comments (0 inline, 0 general)
src/diana/sgfParser/node.py
Show inline comments
 
@@ -98,18 +98,18 @@ class Node:
 
		return ";" + "".join(str(p) for p in self.properties.values())
 

	
 
	def export(self):
 
		# there is a beatiful recursive solution, which this stack is too narrow to contain
 
		# there is a beautiful recursive solution, which this stack is too narrow to contain
 
		stack=[(self,1,1)]
 
		output=[]
 

	
 
		while len(stack)>0:
 
			node,left,right=stack.pop()
 
			if left>0: output.append("("*left)
 
			output.append(str(node))
 
			output.append(str(node)+"\n")
 

	
 
			childCount=len(node.children)
 
			if childCount==0: # a leaf
 
				output.append(")"*right)
 
				output.append(")"*right+"\n")
 
			elif childCount==1: # a line
 
				stack.append((node.children[0],0,right))
 
			else: # a branching node
src/diana/sgfParser/property.py
Show inline comments
 
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
 
@@ -8,6 +9,10 @@ GAME_INFO=1
 
UNKNOWN=99
 

	
 

	
 
class DateException(Exception):
 
	pass
 

	
 

	
 
class Property:
 
	identRegexp=re.compile(r"[A-Z]+")
 

	
 
@@ -32,6 +37,8 @@ class Property:
 
			i,x=choose(listOf(anything), singleton(anything))(s,i)
 
			res.name="_"+res.name
 
		res.value=x
 
		if res.name=="DT":
 
			res=DateProperty(x)
 
		i=skipWhitespace(s,i)
 
		return (i,res)
 

	
 
@@ -46,8 +53,7 @@ class Property:
 
		if name in Property.patterns:
 
			return Property.patterns[name](s,start)
 
		else:
 
			# !! raise or log or ignore
 
			# print('warning, unknown property "{0}" at position {1}'.format(name,start))
 
			log.info("unknown property %s at position %d",name,start)
 
			return choose(listOf(anything), singleton(anything))(s,start)
 

	
 
	@property
 
@@ -63,8 +69,9 @@ class Property:
 
		return res
 

	
 
	def __str__(self):
 
		name=self.name.lstrip("_")
 
		val="[{0}]".format(self.value) if not isinstance(self.value,list) else "".join("[{0}]".format(x) for x in self.value)
 
		return "{0}{1}".format(self.name,val)
 
		return "{0}{1}".format(name,val)
 

	
 
	patterns={
 
		"B":singleton(move),
 
@@ -139,4 +146,42 @@ class Property:
 
	}
 

	
 

	
 
# !! TODO: date
 
class DateProperty(Property):
 
	def __init__(self,value):
 
		super().__init__()
 
		self.name="DT"
 
		self.value=[]
 
		self.rawValue=value
 
		self.parse(value)
 

	
 
	def parse(self,s):
 
		regexp=re.compile(r"\d{4}(-\d\d){0,2}(,(\d{4}(-\d\d){0,2}|\d\d(-\d\d)?))*")
 
		match=re.search(regexp,s)
 
		if not match:
 
			raise DateException('Could not parse a DT value: "{0}"'.format(s))
 
		substr=match.group(0)
 
		dateStrs=substr.split(",")
 
		dates=[]
 
		prevFormat=None
 

	
 
		for s in dateStrs:
 
			try:
 
				(prevFormat,d)=DateProperty.parseSingle(s,prevFormat,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("-")
 
		num_tokens=list(map(int,tokens))
 
		if len(tokens)==3:
 
			return ("YMD",date(*num_tokens))
 
		elif len(tokens)==2:
 
			if len(tokens[0])==4: return ("YM",date(*num_tokens,1))
 
			else: return ("MD",date(prev.year,*num_tokens))
 
		else:
 
			if len(tokens[0])==4: return ("Y",date(*num_tokens,1,1))
 
			elif prevFormat in ("YM","M"): return ("M",date(prev.year,*num_tokens,1))
 
			else: return ("D",date(prev.year,prev.month,*num_tokens))
src/diana/tests/testSgfParser.py
Show inline comments
 
from itertools import chain
 
from datetime import date
 
import unittest
 
from unittest import TestCase
 
import os
 

	
 
from sgfParser import strRowCol
 
from sgfParser.collection import Collection
 
from sgfParser.property import Property
 
from sgfParser.property import Property,DateProperty,DateException
 
from sgfParser.propValues import text,compose
 

	
 

	
 
@@ -54,6 +55,29 @@ ghi]"""
 
		self.assertEqual(str(parsed[1]), "abc:def")
 

	
 

	
 
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))
 
		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))
 
		with self.assertRaises(ValueError):
 
			DateProperty.parseSingle("2019-31","YMD")
 

	
 
	def testParse(self):
 
		self.assertEqual(DateProperty("1996-05,06").value, [date(1996,5,1),date(1996,6,1)])
 
		self.assertEqual(DateProperty("1996-05-06,07,08").value, [date(1996,5,6),date(1996,5,7),date(1996,5,8)])
 
		self.assertEqual(DateProperty("1996,1997").value, [date(1996,1,1),date(1997,1,1)])
 
		self.assertEqual(DateProperty("1996-12-27,28,1997-01-03,04").value, [date(1996,12,27),date(1996,12,28),date(1997,1,3),date(1997,1,4)])
 
		self.assertEqual(DateProperty("1997-05-05,1997-05-06").value, [date(1997,5,5),date(1997,5,6)])
 
		self.assertEqual(DateProperty("Published on 1997-05-06").value, [date(1997,5,6)])
 
		with self.assertRaises(DateException):
 
			DateProperty("unknown")
 

	
 

	
 
class TestCollection(TestCase):
 
	def testSubtrees(self):
 
		c=Collection("""
 
@@ -64,8 +88,8 @@ class TestCollection(TestCase):
 
		games=list(c.listGames())
 

	
 
		self.assertEqual(len(games),2)
 
		self.assertRegex(games[0].export(), r"^\(;B\[aa];(PB\[Some Black]|PW\[Some White]|W\[ab]){3};B\[ac]\)$")
 
		self.assertRegex(games[1].export(), r"^\(;B\[aa];(PB\[Other Black]|PW\[Other White]|W\[bb]){3}\)$")
 
		self.assertRegex(games[0].export(), r"^\(;B\[aa]\n;(PB\[Some Black]|PW\[Some White]|W\[ab]){3}\n;B\[ac]\n\)\n$")
 
		self.assertRegex(games[1].export(), r"^\(;B\[aa]\n;(PB\[Other Black]|PW\[Other White]|W\[bb]){3}\n\)\n$")
 

	
 
	def testEmptySgf(self):
 
		Collection("(;)")
0 comments (0 inline, 0 general)