Skip to content

Commit

Permalink
moar changes
Browse files Browse the repository at this point in the history
  • Loading branch information
redruin1 committed Aug 1, 2023
1 parent c669f1c commit 769291e
Show file tree
Hide file tree
Showing 29 changed files with 1,475 additions and 816 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,9 @@ Allows `draftsman-update` to run on Lua 5.2 instead of Lua 5.4 (which fixes some
* Python3-ify everything
* More doctests
* Make draftsman's prototypes match Factorio's prototypes exactly (for consistency's sake)
* Add documentation on report and contributing
* Write test cases for `dump_format`
* Change type annotations on all functions to follow py3
* Add plaintext representations of Entity JSON objects for all entities in addition to blueprintables
* Write `__repr__` function for everything
* Write `dump_format` (and test_cases)
* Add plaintext representations of Entity JSON objects for all entities in addition to blueprintables
* Update modding documentation guide to reflect 2.0 changes
* Add warnings for placement constraints on rails, rail signals and train stops
* Reevaluate the diamond diagrams for inherited `Entity` subclass
Expand Down
22 changes: 19 additions & 3 deletions draftsman/classes/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,22 @@ def label_color(self, value):
# type: (dict) -> None
if value is None:
self._root.pop("label_color", None)
return
else:
self._root["label_color"] = value

def set_label_color(self, r, g, b, a=None):
"""
TODO
"""
try:
self._root["label_color"] = signatures.COLOR.validate(value)
if a is None:
self._root["label_color"] = signatures.COLOR.validate([r, g, b]) # TODO
else:
self._root["label_color"] = signatures.COLOR.validate(
[r, g, b, a]
) # FIXME
except SchemaError as e:
six.raise_from(DataFormatError(e), None)
raise DataFormatError from e

# =========================================================================

Expand Down Expand Up @@ -779,6 +789,12 @@ def recalculate_area(self):
" (10,000 x 10,000)".format(self.tile_width, self.tile_height)
)

def validate(self):
"""
TODO
"""
pass

def to_dict(self):
# type: () -> dict
"""
Expand Down
31 changes: 24 additions & 7 deletions draftsman/classes/blueprint_book.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,28 @@ def __init__(self, initlist=None, unknown="error"):
if "blueprint" in elem:
self.append(
Blueprint(
elem["blueprint"],
elem,
unknown=unknown
)
)
elif "deconstruction_planner" in elem:
self.append(
DeconstructionPlanner(
elem["deconstruction_planner"],
elem,
unknown=unknown
)
)
elif "upgrade_planner" in elem:
self.append(
UpgradePlanner(
elem["upgrade_planner"],
elem,
unknown=unknown
)
)
elif "blueprint_book" in elem:
self.append(
BlueprintBook(
elem["blueprint_book"],
elem,
unknown=unknown
)
)
Expand Down Expand Up @@ -255,11 +255,22 @@ def label_color(self, value):
# type: (dict) -> None
if value is None:
self._root.pop("label_color", None)
return
else:
self._root["label_color"] = value

def set_label_color(self, r, g, b, a=None):
"""
TODO
"""
try:
self._root["label_color"] = signatures.COLOR.validate(value)
if a is None:
self._root["label_color"] = signatures.COLOR.validate([r, g, b]) # TODO
else:
self._root["label_color"] = signatures.COLOR.validate(
[r, g, b, a]
) # FIXME
except SchemaError as e:
six.raise_from(DataFormatError(e), None)
raise DataFormatError from e

# =========================================================================

Expand Down Expand Up @@ -335,6 +346,12 @@ def blueprints(self, value):
# Utility functions
# =========================================================================

def validate(self):
"""
TODO
"""
pass

def to_dict(self):
# type: () -> dict
"""
Expand Down
109 changes: 42 additions & 67 deletions draftsman/classes/blueprintable.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from __future__ import unicode_literals
import re

from draftsman.classes.exportable import Exportable
from draftsman.data.signals import signal_dict
from draftsman.error import (
IncorrectBlueprintTypeError,
DataFormatError,
Expand All @@ -13,14 +15,14 @@

from abc import ABCMeta, abstractmethod

from functools import cache
import json
from schema import SchemaError
import six
from typing import Any, Sequence, Union


@six.add_metaclass(ABCMeta)
class Blueprintable(object):
class Blueprintable(Exportable, metaclass=ABCMeta):
"""
An abstract base class representing "blueprint-like" objects, such as
:py:class:`.Blueprint`, :py:class:`.DeconstructionPlanner`,
Expand All @@ -37,10 +39,12 @@ def __init__(self, root_item, item, init_data, unknown):
Initializes the private ``_root`` data dictionary, as well as setting
the ``item`` name.
"""
# Init exportable
super().__init__()

# The "root" dict, contains everything inside of this blueprintable
# Output format is equivalent to:
# { self._root_item: self._root }
self._root = {}

self._root_item = six.text_type(root_item)
self._root["item"] = six.text_type(item)
Expand Down Expand Up @@ -91,7 +95,7 @@ def load_from_string(self, string, unknown="error"):
self.setup(**root[self._root_item], unknown=unknown)

@abstractmethod
def setup(unknown="error", **kwargs): # pragma: no coverage
def setup(self, unknown="error", **kwargs): # pragma: no coverage
# type: (str, **dict) -> None
"""
Setup the Blueprintable's parameters with the input keywords as values.
Expand Down Expand Up @@ -179,10 +183,8 @@ def label(self, value):
# type: (str) -> None
if value is None:
self._root.pop("label", None)
elif isinstance(value, six.string_types):
self._root["label"] = six.text_type(value)
else:
raise TypeError("`label` must be a string or None")
self._root["label"] = value

# =========================================================================

Expand All @@ -208,10 +210,8 @@ def description(self, value):
# type: (str) -> None
if value is None:
self._root.pop("description", None)
elif isinstance(value, six.string_types):
self._root["description"] = six.text_type(value)
else:
raise TypeError("'description' must be a string or None")
self._root["description"] = value

# =========================================================================

Expand Down Expand Up @@ -255,11 +255,16 @@ def icons(self, value):
# type: (list[Union[dict, str]]) -> None
if value is None:
self._root.pop("icons", None)
return
try:
self._root["icons"] = signatures.ICONS.validate(value)
except SchemaError as e:
six.raise_from(DataFormatError(e), None)
else:
self._root["icons"] = value

def set_icons(self, *icon_names):
"""
TODO
"""
self.icons = [None] * len(icon_names)
for i, icon in enumerate(icon_names):
self.icons[i] = {"index": i + 1, "signal": signal_dict(icon)}

# =========================================================================

Expand Down Expand Up @@ -312,12 +317,22 @@ def version(self, value):
# type: (Union[int, Sequence[int]]) -> None
if value is None:
self._root.pop("version", None)
elif isinstance(value, six.integer_types):
self._root["version"] = value
elif isinstance(value, Sequence):
self._root["version"] = utils.encode_version(*value)
else:
raise TypeError("'version' must be an int, sequence of ints or None")
self._root["version"] = value

def set_version(self, major, minor, patch=0, dev_ver=0):
"""
Convenience function for setting a Blueprintable's version by it's
component semantic version numbers. Loose wrapper around
:py:func:`.encode_version`.
:param major: The major Factorio version.
:param minor: The minor Factorio version.
:param patch: The current patch number.
:param dev_ver: The (internal) development version.
"""
# TODO: use this method in constructor
self._root["version"] = utils.encode_version(major, minor, patch, dev_ver)

# =========================================================================
# Utility functions
Expand Down Expand Up @@ -385,54 +400,14 @@ def version_string(self):
version_tuple = utils.decode_version(self._root["version"])
return utils.version_tuple_to_string(version_tuple)

@abstractmethod
def to_dict(self): # pragma: no coverage
# type: () -> dict
"""
Returns the blueprintable as a dictionary. Intended for getting the
precursor to a Factorio blueprint string before encoding and compression
takes place.
:returns: The ``dict`` representation of the :py:class:`.Blueprintable`.
"""
pass

def to_string(self): # pragma: no coverage
# type: () -> str
"""
Returns this object as an encoded Factorio blueprint string.
:returns: The zlib-compressed, base-64 encoded string.
:example:
.. doctest::
>>> from draftsman.blueprintable import (
... Blueprint, DeconstructionPlanner, UpgradePlanner, BlueprintBook
... )
>>> Blueprint({"version": (1, 0)}).to_string()
'0eNqrVkrKKU0tKMrMK1GyqlbKLEnNVbJCEtNRKkstKs7Mz1OyMrIwNDE3sTQ3Mzc0MDM1q60FAHmVE1M='
>>> DeconstructionPlanner({"version": (1, 0)}).to_string()
'0eNpdy0EKgCAQAMC/7Nkgw7T8TIQtIdga7tol/HtdunQdmBs2DJlYSg0SMy1nWomwgL+BUSTSzuCppqQgCh7gf6H7goILC78Cfpi0cWZ21unejra1B7C2I9M='
>>> UpgradePlanner({"version": (1, 0)}).to_string()
'0eNo1yksKgCAUBdC93LFBhmm5mRB6iGAv8dNE3Hsjz/h0tOSzu+lK0TFThu0oVGtgX2C5xSgQKj2wcy5zCnyUS3gZdjukMuo02shV73qMH4ZxHbs='
>>> BlueprintBook({"version": (1, 0)}).to_string()
'0eNqrVkrKKU0tKMrMK4lPys/PVrKqVsosSc1VskJI6IIldJQSk0syy1LjM/NSUiuUrAx0lMpSi4oz8/OUrIwsDE3MTSzNzcwNDcxMzWprAVWGHQI='
"""
return utils.JSON_to_string(self.to_dict())

def __setitem__(self, key, value):
# type: (str, Any) -> None
self._root[key] = value

def __getitem__(self, key):
# type: (str) -> Any
return self._root[key]
# def validate(self):
# # type: () -> bool
# self.label = signatures.Label.validate(self.label)
# self.description = signatures.Description.validate(self.description)
# self.icons = signatures.Icons.validate(self.icons)
# self.version = signatures.Version.validate(self.version)

def __contains__(self, item):
# type: (str) -> bool
return item in self._root
# super().validate()

def __str__(self): # pragma: no coverage
# type: () -> str
Expand Down
8 changes: 8 additions & 0 deletions draftsman/classes/deconstruction_planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,14 @@ def set_tile_filter(self, index, name):
# Otherwise its unique; add to list
self.tile_filters.append({"index": index + 1, "name": name})

# =========================================================================

def validate(self):
"""
TODO
"""
pass

def to_dict(self):
out_dict = copy.deepcopy(self._root)

Expand Down
2 changes: 1 addition & 1 deletion draftsman/classes/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def __init__(self, name, similar_entities, tile_position=[0, 0], **kwargs):
self.tile_position = tile_position

# Entity tags
self.tags = None
self.tags = {}
if "tags" in kwargs:
self.tags = kwargs["tags"]
self.unused_args.pop("tags")
Expand Down
Loading

0 comments on commit 769291e

Please sign in to comment.