Add typing in HLDS code, change price to int

This commit is contained in:
Midgard 2020-01-26 15:09:22 +01:00
parent 798e08d74b
commit fe593fece6
Signed by: midgard
GPG key ID: 511C112F1331BBB4
4 changed files with 42 additions and 31 deletions

View file

@ -1,7 +1,9 @@
# Import this class to load the standard HLDS definitions
from os import path
from typing import List
from .parser import parse_all_directory
from .models import Location
__all__ = ["location_definitions"]
@ -10,4 +12,4 @@ __all__ = ["location_definitions"]
DATA_DIR = path.join(path.dirname(__file__), "..", "..", "data")
# pylint: disable=invalid-name
location_definitions = parse_all_directory(DATA_DIR)
location_definitions: List[Location] = parse_all_directory(DATA_DIR)

View file

@ -80,7 +80,7 @@ identifier = /[a-z0-9_-]+/ ;
string = /[^\n]+/ ;
choice_type = 'single_choice' | 'multi_choice' ;
number = /[0-9]+(\.[0-9]+)?/ ;
int = /[0-9]+/ ;
currency = '€' ;
price = currency:currency s value:number ;
price = currency:currency s value_unit:int [ '.' value_cents:/[0-9]{,2}/ ] ;

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
# pylint: disable=too-few-public-methods
from typing import List
from typing import List, Mapping, Any
def _format_tags(tags):
@ -19,11 +19,11 @@ def _format_type_and_choice(type_and_choice):
class Option:
def __init__(self, id_, *, name, description, price, tags):
self.id = id_
self.name = name
self.description = description
self.price = price
self.tags = tags
self.id: str = id_
self.name: str = name
self.description: str = description
self.price: int = price
self.tags: List[str] = tags
def __str__(self):
return "{0.id}: {0.name}{1}{2}{3}".format(
@ -36,9 +36,9 @@ class Option:
class Choice:
def __init__(self, id_, *, name, description, options):
self.id = id_
self.name = name
self.description = description
self.id: str = id_
self.name: str = name
self.description: str = description
self.options: List[Option] = options
@ -52,11 +52,11 @@ class Choice:
class Dish:
def __init__(self, id_, *, name, description, price, tags, choices):
self.id = id_
self.name = name
self.description = description
self.price = price
self.tags = tags
self.id: str = id_
self.name: str = name
self.description: str = description
self.price: int = price
self.tags: List[str] = tags
self.choices: List[(str, Choice)] = choices
@ -72,9 +72,9 @@ class Dish:
class Location:
def __init__(self, id_, *, name, attributes, dishes):
self.id = id_
self.name = name
self.attributes = attributes
self.id: str = id_
self.name: str = name
self.attributes: Mapping[str, Any] = attributes
self.dishes: List[Dish] = dishes

View file

@ -3,7 +3,9 @@
from glob import glob
from os import path
import itertools
from typing import Iterable, List, Union, Tuple
from tatsu import parse as tatsu_parse
from tatsu.ast import AST
from .models import Location, Choice, Option, Dish
@ -18,7 +20,7 @@ def filter_instance(cls, iterable):
# pylint: disable=no-self-use
class HldsSemanticActions:
def location(self, ast):
def location(self, ast) -> Location:
choices = {choice.id: choice for choice in filter_instance(Choice, ast["items_"])}
dishes = filter_instance(Dish, ast["items_"])
for dish in dishes:
@ -33,7 +35,7 @@ class HldsSemanticActions:
dishes=dishes,
)
def base_block(self, ast):
def base_block(self, ast) -> Dish:
return Dish(
ast["id"],
name=ast["name"],
@ -43,7 +45,7 @@ class HldsSemanticActions:
choices=ast["choices"],
)
def choice_block(self, ast):
def choice_block(self, ast) -> Choice:
return Choice(
ast["id"],
name=ast["name"],
@ -51,14 +53,14 @@ class HldsSemanticActions:
options=ast["entries"],
)
def indent_choice_block(self, ast):
def indent_choice_block(self, ast) -> Tuple[str, Union[Choice, AST]]:
return (
(ast["type"], self.choice_block(ast))
if ast["kind"] == "declaration" else
(ast["type"], ast["id"])
)
def indent_choice_entry(self, ast):
def indent_choice_entry(self, ast) -> Option:
return Option(
ast["id"],
name=ast["name"],
@ -69,8 +71,15 @@ class HldsSemanticActions:
noindent_choice_entry = indent_choice_entry
def price(self, ast):
return "{0[currency]} {0[value]}".format(ast)
def price(self, ast) -> int:
return (
100 * int(ast["value_unit"]) +
(
0 if not ast["value_cents"] else
10 * int(ast["value_cents"]) if len(ast["value_cents"]) == 1 else
int(ast["value_cents"])
)
)
def _default(self, ast):
return ast
@ -78,22 +87,22 @@ class HldsSemanticActions:
SEMANTICS = HldsSemanticActions()
def parse(menu):
def parse(menu: str) -> List[Location]:
parsed = tatsu_parse(GRAMMAR, menu, semantics=SEMANTICS)
return parsed
def parse_file(filename):
def parse_file(filename: str) -> List[Location]:
with open(filename, "r") as file_handle:
return parse(file_handle.read())
def parse_files(files):
def parse_files(files: Iterable[str]) -> List[Location]:
menus = map(parse_file, files)
return list(itertools.chain.from_iterable(menus))
def parse_all_directory(directory):
def parse_all_directory(directory: str) -> List[Location]:
# TODO Use proper way to get resources, see https://stackoverflow.com/a/10935674
files = glob(path.join(directory, "**.hlds"), recursive=True)
return parse_files(files)