diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 8d616bb..f37e2ae 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -12,8 +12,9 @@ PyTiled Parser is not tied to any particular graphics library or game engine. # pylint: disable=too-few-public-methods from .common_types import OrderedPair, Size +from .exception import UnknownFormat from .layer import ImageLayer, Layer, LayerGroup, ObjectLayer, TileLayer -from .parser import parse_map, parse_tmx +from .parser import parse_map from .properties import Properties from .tiled_map import TiledMap from .tileset import Tile, Tileset diff --git a/pytiled_parser/exception.py b/pytiled_parser/exception.py new file mode 100644 index 0000000..8d75354 --- /dev/null +++ b/pytiled_parser/exception.py @@ -0,0 +1,2 @@ +class UnknownFormat(Exception): + pass diff --git a/pytiled_parser/parser.py b/pytiled_parser/parser.py index 69343f8..9a0a389 100644 --- a/pytiled_parser/parser.py +++ b/pytiled_parser/parser.py @@ -1,22 +1,29 @@ from pathlib import Path +from pytiled_parser import UnknownFormat from pytiled_parser.parsers.json.tiled_map import parse as json_map_parse from pytiled_parser.parsers.tmx.tiled_map import parse as tmx_map_parse from pytiled_parser.tiled_map import TiledMap +from pytiled_parser.util import check_format def parse_map(file: Path) -> TiledMap: """Parse the raw Tiled map into a pytiled_parser type Args: - file: Path to the map's JSON file + file: Path to the map file Returns: - TileSet: a properly typed TileSet. + Tiledmap: a properly typed TiledMap """ - # I have no idea why, but mypy thinks this function returns "Any" - return json_map_parse(file) # type: ignore + parser = check_format(file) - -def parse_tmx(file: Path) -> TiledMap: - return tmx_map_parse(file) # type: ignore + # The type ignores are because mypy for some reaosn thinks those functions return Any + if parser == "tmx": + return tmx_map_parse(file) # type: ignore + elif parser == "json": + return json_map_parse(file) # type: ignore + else: + raise UnknownFormat( + "Unknown Map Format, please use either the TMX or JSON format." + ) diff --git a/pytiled_parser/parsers/json/tiled_map.py b/pytiled_parser/parsers/json/tiled_map.py index 304f577..82f6c04 100644 --- a/pytiled_parser/parsers/json/tiled_map.py +++ b/pytiled_parser/parsers/json/tiled_map.py @@ -1,18 +1,21 @@ import json +import xml.etree.ElementTree as etree from pathlib import Path from typing import List, Union, cast from typing_extensions import TypedDict from pytiled_parser.common_types import Size +from pytiled_parser.exception import UnknownFormat from pytiled_parser.parsers.json.layer import RawLayer from pytiled_parser.parsers.json.layer import parse as parse_layer from pytiled_parser.parsers.json.properties import RawProperty from pytiled_parser.parsers.json.properties import parse as parse_properties from pytiled_parser.parsers.json.tileset import RawTileSet -from pytiled_parser.parsers.json.tileset import parse as parse_tileset +from pytiled_parser.parsers.json.tileset import parse as parse_json_tileset +from pytiled_parser.parsers.tmx.tileset import parse as parse_tmx_tileset from pytiled_parser.tiled_map import TiledMap, TilesetDict -from pytiled_parser.util import parse_color +from pytiled_parser.util import check_format, parse_color class RawTilesetMapping(TypedDict): @@ -70,16 +73,30 @@ def parse(file: Path) -> TiledMap: if raw_tileset.get("source") is not None: # Is an external Tileset tileset_path = Path(parent_dir / raw_tileset["source"]) + parser = check_format(tileset_path) with open(tileset_path) as raw_tileset_file: - tilesets[raw_tileset["firstgid"]] = parse_tileset( - json.load(raw_tileset_file), - raw_tileset["firstgid"], - external_path=tileset_path.parent, - ) + if parser == "json": + tilesets[raw_tileset["firstgid"]] = parse_json_tileset( + json.load(raw_tileset_file), + raw_tileset["firstgid"], + external_path=tileset_path.parent, + ) + elif parser == "tmx": + raw_tileset_external = etree.parse(raw_tileset_file).getroot() + tilesets[raw_tileset["firstgid"]] = parse_tmx_tileset( + raw_tileset_external, + raw_tileset["firstgid"], + external_path=tileset_path.parent, + ) + else: + raise UnknownFormat( + "Unkown Tileset format, please use either the TSX or JSON format." + ) + else: # Is an embedded Tileset raw_tileset = cast(RawTileSet, raw_tileset) - tilesets[raw_tileset["firstgid"]] = parse_tileset( + tilesets[raw_tileset["firstgid"]] = parse_json_tileset( raw_tileset, raw_tileset["firstgid"] ) @@ -120,7 +137,7 @@ def parse(file: Path) -> TiledMap: highest_firstgid = max(map_.tilesets.keys()) last_tileset_count = map_.tilesets[highest_firstgid].tile_count new_firstgid = highest_firstgid + last_tileset_count - map_.tilesets[new_firstgid] = parse_tileset( + map_.tilesets[new_firstgid] = parse_json_tileset( tiled_object.new_tileset, new_firstgid, tiled_object.new_tileset_path, diff --git a/pytiled_parser/parsers/tmx/tiled_map.py b/pytiled_parser/parsers/tmx/tiled_map.py index c44e916..4ecb5ed 100644 --- a/pytiled_parser/parsers/tmx/tiled_map.py +++ b/pytiled_parser/parsers/tmx/tiled_map.py @@ -1,12 +1,15 @@ +import json import xml.etree.ElementTree as etree from pathlib import Path from pytiled_parser.common_types import OrderedPair, Size +from pytiled_parser.exception import UnknownFormat +from pytiled_parser.parsers.json.tileset import parse as parse_json_tileset from pytiled_parser.parsers.tmx.layer import parse as parse_layer from pytiled_parser.parsers.tmx.properties import parse as parse_properties -from pytiled_parser.parsers.tmx.tileset import parse as parse_tileset +from pytiled_parser.parsers.tmx.tileset import parse as parse_tmx_tileset from pytiled_parser.tiled_map import TiledMap, TilesetDict -from pytiled_parser.util import parse_color +from pytiled_parser.util import check_format, parse_color def parse(file: Path) -> TiledMap: @@ -18,7 +21,6 @@ def parse(file: Path) -> TiledMap: Returns: TiledMap: A parsed TiledMap. """ - print(file) with open(file) as map_file: raw_map = etree.parse(map_file).getroot() @@ -31,17 +33,29 @@ def parse(file: Path) -> TiledMap: if raw_tileset.attrib.get("source") is not None: # Is an external Tileset tileset_path = Path(parent_dir / raw_tileset.attrib["source"]) + parser = check_format(tileset_path) with open(tileset_path) as tileset_file: - raw_tileset_external = etree.parse(tileset_file).getroot() + if parser == "tmx": + raw_tileset_external = etree.parse(tileset_file).getroot() + tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tmx_tileset( + raw_tileset_external, + int(raw_tileset.attrib["firstgid"]), + external_path=tileset_path.parent, + ) + elif parser == "json": + tilesets[int(raw_tileset.attrib["firstgid"])] = parse_json_tileset( + json.load(tileset_file), + int(raw_tileset.attrib["firstgid"]), + external_path=tileset_path.parent, + ) + else: + raise UnknownFormat( + "Unkown Tileset format, please use either the TSX or JSON format." + ) - tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tileset( - raw_tileset_external, - int(raw_tileset.attrib["firstgid"]), - external_path=tileset_path.parent, - ) else: # Is an embedded Tileset - tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tileset( + tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tmx_tileset( raw_tileset, int(raw_tileset.attrib["firstgid"]) ) @@ -83,7 +97,7 @@ def parse(file: Path) -> TiledMap: highest_firstgid = max(map_.tilesets.keys()) last_tileset_count = map_.tilesets[highest_firstgid].tile_count new_firstgid = highest_firstgid + last_tileset_count - map_.tilesets[new_firstgid] = parse_tileset( + map_.tilesets[new_firstgid] = parse_tmx_tileset( tiled_object.new_tileset, new_firstgid, tiled_object.new_tileset_path, diff --git a/pytiled_parser/util.py b/pytiled_parser/util.py index 75c7d1d..07fd955 100644 --- a/pytiled_parser/util.py +++ b/pytiled_parser/util.py @@ -1,4 +1,5 @@ """Utility Functions for PyTiled""" +from pathlib import Path from pytiled_parser.common_types import Color @@ -27,3 +28,12 @@ def parse_color(color: str) -> Color: ) raise ValueError("Improperly formatted color passed to parse_color") + + +def check_format(file_path: Path) -> str: + with open(file_path) as file: + line = file.readline().rstrip().strip() + if line[0] == "<": + return "tmx" + else: + return "json"