Skip to content

Commit

Permalink
Merge pull request #1426 from heinezen/lgtm
Browse files Browse the repository at this point in the history
Converter code cleanup
TheJJ authored Oct 15, 2021
2 parents 103bc3a + e684e76 commit bf0094c
Showing 16 changed files with 153 additions and 156 deletions.
6 changes: 4 additions & 2 deletions doc/ide/vscode.md
Original file line number Diff line number Diff line change
@@ -67,13 +67,15 @@ If you use a C/C++ language support extension, you need to add the path to the *

If you use a Python language support extension with `autopep8` formatting, you should add these settings to get the openage Python code style. Add these entries to the list of passed arguments:

* `--ignore E221,E241,E251,E501`
* `--ignore`
* `E221,E241,E251,E501`

Ignoring the `E221,E241,E251` errors allows placing multiple spaces around commas and before comments for alignment, while ignoring `E501` disables auto-formatting of overlong lines.

If you don't want to ignore `E501`, you should add this argument which increases the maximum line length to 100:

* `--line-length 100`
* `--max-line-length`
* `100`


## Add openage configure and build tasks
Original file line number Diff line number Diff line change
@@ -380,7 +380,7 @@ def extend_raw_member(self, name, push_value, origin):
member_origin = raw_member[2]

if name == member_name and member_origin == origin:
member_value = member_value.extend(push_value)
member_value.extend(push_value)
break

else:
16 changes: 0 additions & 16 deletions openage/convert/entity_object/conversion/stringresource.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,6 @@
from collections import defaultdict

from ...entity_object.conversion.genie_structure import GenieStructure
from ...entity_object.export import data_definition


class StringResource(GenieStructure):
@@ -27,21 +26,6 @@ def get_tables(self):
"""
return self.strings

def dump(self, filename):
data = []

for lang, langstrings in self.strings.items():
for idx, text in langstrings.items():
entry = {
"id": idx,
"lang": lang,
"text": text,
}
data.append(entry)

data = sorted(data, key=lambda x: x["id"])
return [data_definition.DataDefinition(self, data, filename)]

@classmethod
def get_data_format_members(cls, game_version):
"""
Original file line number Diff line number Diff line change
@@ -4073,7 +4073,6 @@ def idle_ability(line):

if civ_animation_id != ability_animation_id:
# Find the corresponding graphics set
graphics_set_id = -1
for set_id, items in gset_lookup_dict.items():
if civ_id in items[0]:
graphics_set_id = set_id
@@ -6739,7 +6738,6 @@ def trade_ability(line):
# Trade route (use the trade route to the market)
trade_routes = []

trade_post_id = -1
unit_commands = current_unit["unit_commands"].get_value()
for command in unit_commands:
# Find the trade command and the trade post id
47 changes: 30 additions & 17 deletions openage/convert/processor/conversion/aoc/modifier_subprocessor.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Copyright 2020-2021 the openage authors. See copying.md for legal info.
#
# pylint: disable=too-many-locals,too-many-branches,too-many-nested-blocks
#
# TODO:
# pylint: disable=line-too-long
# pylint: disable=too-many-locals,too-many-branches,too-many-nested-blocks,too-many-statements

"""
Derives and adds abilities to lines or civ groups. Subroutine of the
@@ -34,8 +31,12 @@ def elevation_attack_modifiers(converter_obj_group):
"""
dataset = converter_obj_group.data
modifiers = [
dataset.pregen_nyan_objects["util.modifier.elevation_difference.AttackHigh"].get_nyan_object(),
dataset.pregen_nyan_objects["util.modifier.elevation_difference.AttackLow"].get_nyan_object()
dataset.pregen_nyan_objects[
"util.modifier.elevation_difference.AttackHigh"
].get_nyan_object(),
dataset.pregen_nyan_objects[
"util.modifier.elevation_difference.AttackLow"
].get_nyan_object()
]

return modifiers
@@ -51,7 +52,9 @@ def flyover_effect_modifier(converter_obj_group):
:rtype: ...dataformat.forward_ref.ForwardRef
"""
dataset = converter_obj_group.data
modifier = dataset.pregen_nyan_objects["util.modifier.flyover_cliff.AttackFlyover"].get_nyan_object()
modifier = dataset.pregen_nyan_objects[
"util.modifier.flyover_cliff.AttackFlyover"
].get_nyan_object()

return modifier

@@ -89,14 +92,16 @@ def gather_rate_modifier(converter_obj_group):
# Find a gather ability.
type_id = command["type"].get_value()

if type_id not in (5, 110):
gather_task_ids = internal_name_lookups.get_gather_lookups(
dataset.game_version).keys()
if type_id not in gather_task_ids:
continue

work_value = command["work_value1"].get_value()

# Check if the work value is 1 (with some rounding error margin)
# if not we have to create a modifier
if work_value < 1.0001 or work_value > 0.9999:
# if not, we have to create a modifier
if 0.9999 < work_value < 1.0001:
continue

# Search for the lines with the matching class/unit id
@@ -118,6 +123,9 @@ def gather_rate_modifier(converter_obj_group):
if line.get_class_id() == class_id:
lines.append(line)

else:
raise Exception("Gather task has no valid target ID.")

# Create a modifier for each matching resource spot
for resource_line in lines:
head_unit_id = resource_line.get_head_unit_id()
@@ -135,22 +143,27 @@ def gather_rate_modifier(converter_obj_group):
modifier_raw_api_object = RawAPIObject(modifier_ref,
"%sGatheringRate",
dataset.nyan_api_objects)
modifier_raw_api_object.add_raw_parent("engine.modifier.multiplier.type.GatheringRate")
modifier_raw_api_object.add_raw_parent(
"engine.modifier.multiplier.type.GatheringRate")
modifier_location = ForwardRef(converter_obj_group, target_obj_name)
modifier_raw_api_object.set_location(modifier_location)

# Multiplier
modifier_raw_api_object.add_raw_member("multiplier",
work_value,
"engine.modifier.multiplier.MultiplierModifier")
modifier_raw_api_object.add_raw_member(
"multiplier",
work_value,
"engine.modifier.multiplier.MultiplierModifier"
)

# Resource spot
spot_ref = "%s.Harvestable.%sResourceSpot" % (resource_line_name,
resource_line_name)
spot_forward_ref = ForwardRef(resource_line, spot_ref)
modifier_raw_api_object.add_raw_member("resource_spot",
spot_forward_ref,
"engine.modifier.multiplier.type.GatheringRate")
modifier_raw_api_object.add_raw_member(
"resource_spot",
spot_forward_ref,
"engine.modifier.multiplier.type.GatheringRate"
)

converter_obj_group.add_raw_api_object(modifier_raw_api_object)
modifier_forward_ref = ForwardRef(converter_obj_group,
2 changes: 0 additions & 2 deletions openage/convert/processor/conversion/aoc/processor.py
Original file line number Diff line number Diff line change
@@ -511,7 +511,6 @@ def create_unit_lines(full_data_set):

# Search other_connections for the previous unit in line
connected_types = connection["other_connections"].get_value()
connected_index = -1
for index, _ in enumerate(connected_types):
connected_type = connected_types[index]["other_connection"].get_value()
if connected_type == 2:
@@ -645,7 +644,6 @@ def create_building_lines(full_data_set):
continue

# Find the previous building
connected_index = -1
for c_index, _ in enumerate(connected_types):
connected_type = connected_types[c_index]["other_connection"].get_value()
if connected_type == 1:
Original file line number Diff line number Diff line change
@@ -1719,7 +1719,6 @@ def trade_ability(line):
# Trade route (use the trade route o the market)
trade_routes = []

trade_post_id = -1
unit_commands = current_unit["unit_commands"].get_value()
for command in unit_commands:
# Find the trade command and the trade post id
2 changes: 0 additions & 2 deletions openage/convert/processor/conversion/swgbcc/processor.py
Original file line number Diff line number Diff line change
@@ -235,7 +235,6 @@ def create_unit_lines(full_data_set):

# Search other_connections for the previous unit in line
connected_types = connection["other_connections"].get_value()
connected_index = -1
for index, _ in enumerate(connected_types):
connected_type = connected_types[index]["other_connection"].get_value()
if connected_type == 2:
@@ -438,7 +437,6 @@ def create_building_lines(full_data_set):

# Search other_connections for the previous unit in line
connected_types = connection["other_connections"].get_value()
connected_index = -1
for index, _ in enumerate(connected_types):
connected_type = connected_types[index]["other_connection"].get_value()
if connected_type == 1:
62 changes: 37 additions & 25 deletions openage/convert/processor/export/media_exporter.py
Original file line number Diff line number Diff line change
@@ -4,14 +4,15 @@
"""
Converts media requested by export requests to files.
"""
import logging
import os

from openage.convert.entity_object.export.texture import Texture
from openage.convert.service import debug_info
from openage.convert.service.export.load_media_cache import load_media_cache
from openage.convert.value_object.read.media.blendomatic import Blendomatic
from openage.convert.value_object.read.media_types import MediaType
from openage.log import dbg
from openage.log import dbg, get_loglevel


class MediaExporter:
@@ -124,10 +125,12 @@ def _export_blend(export_request, sourcedir, exportdir, blend_mode_count=None):
f"{export_request.target_filename}{idx}.png"
)

MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, f"{export_request.target_filename}{idx}.png"]
)
if get_loglevel() <= logging.DEBUG:
MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir,
f"{export_request.target_filename}{idx}.png"]
)

@staticmethod
def _export_graphics(export_request, sourcedir, exportdir, palettes,
@@ -207,10 +210,12 @@ def _export_graphics(export_request, sourcedir, exportdir, palettes,
export_request.set_changed()
export_request.notify_observers(metadata)
export_request.clear_changed()
MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)

if get_loglevel() <= logging.DEBUG:
MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)

@staticmethod
def _export_interface(export_request, sourcedir, **kwargs):
@@ -268,10 +273,11 @@ def _export_sound(export_request, sourcedir, exportdir):
with export_file.open_w() as outfile:
outfile.write(soundata)

MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)
if get_loglevel() <= logging.DEBUG:
MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)

@staticmethod
def _export_terrain(export_request, sourcedir, exportdir, palettes,
@@ -337,10 +343,11 @@ def _export_terrain(export_request, sourcedir, exportdir, palettes,
compression_level,
)

MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)
if get_loglevel() <= logging.DEBUG:
MediaExporter.log_fileinfo(
source_file,
exportdir[export_request.targetdir, export_request.target_filename]
)

@staticmethod
def _get_media_cache(export_request, sourcedir, palettes, compression_level):
@@ -466,18 +473,23 @@ def log_fileinfo(source_file, target_file):
source_format = source_file.suffix[1:].upper()
target_format = target_file.suffix[1:].upper()

with source_file.open('r') as src:
src.seek(0, os.SEEK_END)
source_size = src.tell()
source_path = source_file.resolve_native_path()
if source_path:
source_size = os.path.getsize(source_path)

else:
with source_file.open('r') as src:
src.seek(0, os.SEEK_END)
source_size = src.tell()

with target_file.open('r') as dest:
dest.seek(0, os.SEEK_END)
target_size = dest.tell()
target_path = target_file.resolve_native_path()
target_size = os.path.getsize(target_path)

log = ("Converted: "
f"{source_file.name} "
f" ({source_format}, {source_size}B) "
f"({source_format}, {source_size}B) "
f"-> {target_file.name} "
f"({target_format}, {target_size}B)")
f"({target_format}, {target_size}B | "
f"{(target_size / source_size * 100) - 100:+.1f}%)")

dbg(log)
24 changes: 0 additions & 24 deletions openage/convert/value_object/read/media/blendomatic.py
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@

from .....log import dbg
from ....entity_object.conversion.genie_structure import GenieStructure
from ....entity_object.export.data_definition import DataDefinition


class BlendingTile:
@@ -254,32 +253,9 @@ def get_textures(self):
one atlas per blending mode is generated,
each atlas contains all blending masks merged on one texture
"""

from ....entity_object.export.texture import Texture
return [Texture(b_mode) for b_mode in self.blending_modes]

def dump(self, filename):
"""
Return a printable file.
"""
data = [
{"blend_mode": idx}
for idx, _ in enumerate(self.blending_modes)
]
return [DataDefinition(self, data, filename)]

def save(self, fslikeobj, path, compression_level):
"""
Save the blending mask textures to disk.
"""

for idx, texture in enumerate(self.get_textures()):
name = "mode%02d.png" % idx
dbg("saving blending mode %02d texture -> %s", idx, name)
texture.save(fslikeobj, path + '/' + name, compression_level)

dbg("blending masks successfully exported")

@classmethod
def get_data_format_members(cls, game_version):
"""
39 changes: 19 additions & 20 deletions openage/convert/value_object/read/media/colortable.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@

from .....log import dbg
from ....entity_object.conversion.genie_structure import GenieStructure
from ....entity_object.export.data_definition import DataDefinition


class ColorTable(GenieStructure):
@@ -151,22 +150,6 @@ def get_ndarray(self):
def save_visualization(self, fileobj):
self.gen_image().save(fileobj, 'png')

def dump(self, filename):
data = list()

# dump all color entries
for idx, entry in enumerate(self.palette):
color_entry = {
"idx": idx,
"r": entry[0],
"g": entry[1],
"b": entry[2],
"a": 255,
}
data.append(color_entry)

return [DataDefinition(self, data, filename)]

@classmethod
def get_data_format_members(cls, game_version):
"""
@@ -183,7 +166,7 @@ def get_data_format_members(cls, game_version):
return data_format


class PlayerColorTable(ColorTable):
class PlayerColorTable(GenieStructure):
"""
this class represents stock player color values.
@@ -193,7 +176,8 @@ class PlayerColorTable(ColorTable):
__slots__ = ('header', 'version', 'palette')

def __init__(self, base_table):
# TODO pylint: disable=super-init-not-called
super().__init__()

if not isinstance(base_table, ColorTable):
raise Exception(f"no ColorTable supplied, instead: {type(base_table)}")

@@ -211,5 +195,20 @@ def __init__(self, base_table):
r, g, b = base_table[16 * i + subcol]
self.palette.append((r, g, b))

@classmethod
def get_data_format_members(cls, game_version):
"""
Return the members in this struct.
"""
data_format = (
(True, "idx", None, "int32_t"),
(True, "r", None, "uint8_t"),
(True, "g", None, "uint8_t"),
(True, "b", None, "uint8_t"),
(True, "a", None, "uint8_t"),
)

return data_format

def __repr__(self):
return "ColorTable<%d entries>" % len(self.palette)
return "PlayerColorTable<%d entries>" % len(self.palette)
6 changes: 3 additions & 3 deletions openage/log/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2014-2018 the openage authors. See copying.md for legal info.
# Copyright 2014-2021 the openage authors. See copying.md for legal info.

"""
Python logging.
@@ -8,18 +8,18 @@
"""

import logging
from logging import Handler
from os import environ

from ..util.math import clamp

PYTHON_TO_CPP_LOG_LEVEL = {}


class CppHandler(Handler):
class CppHandler(logging.Handler):
"""
CppHandler calls into the CPP logging system if the library has been loaded.
"""

def __init__(self):
super().__init__()

81 changes: 45 additions & 36 deletions openage/nyan/nyan_structs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Copyright 2019-2021 the openage authors. See copying.md for legal info.
#
# pylint: disable=too-many-lines,too-many-arguments,too-many-return-statements,too-many-locals

"""
Nyan structs.
@@ -19,7 +21,7 @@


INDENT = " "
LINE_WIDTH = 130
MAX_LINE_WIDTH = 130


class NyanObject:
@@ -177,17 +179,19 @@ def get_member_by_name(self, member_name, origin=None):
Returns the NyanMember with the specified name.
"""
if origin and origin is not self:
# Inherited member: Search in the inheritance tree
for inherited_member in self._inherited_members:
if origin == inherited_member.get_origin():
if inherited_member.get_name() == member_name:
return inherited_member

raise Exception("%s has no member '%s' with origin '%s'"
% (self, member_name, origin))
else:
for member in self._members:
if member.get_name() == member_name:
return member

# Else: Member should be a direct member of this nyan object
for member in self._members:
if member.get_name() == member_name:
return member

raise Exception(f"{self} has no member '{member_name}'")

@@ -241,7 +245,8 @@ def is_abstract(self):
"""
return len(self.get_uninitialized_members()) > 0

def is_patch(self):
@staticmethod
def is_patch():
"""
Returns True if the object is a NyanPatch.
"""
@@ -719,38 +724,38 @@ def accepts_op(self, operator):
MemberOperator.DIVIDE):
return False

elif self._member_type is MemberType.TEXT\
if self._member_type is MemberType.TEXT\
and operator not in (MemberOperator.ASSIGN,
MemberOperator.ADD):
return False

elif self._member_type is MemberType.FILE\
if self._member_type is MemberType.FILE\
and operator is not MemberOperator.ASSIGN:
return False

elif self._member_type is MemberType.BOOLEAN\
if self._member_type is MemberType.BOOLEAN\
and operator not in (MemberOperator.ASSIGN,
MemberOperator.AND,
MemberOperator.OR):
return False

elif self._member_type is MemberType.SET\
if self._member_type is MemberType.SET\
and operator not in (MemberOperator.ASSIGN,
MemberOperator.ADD,
MemberOperator.SUBTRACT,
MemberOperator.AND,
MemberOperator.OR):
return False

elif self._member_type is MemberType.ORDEREDSET\
if self._member_type is MemberType.ORDEREDSET\
and operator not in (MemberOperator.ASSIGN,
MemberOperator.ADD,
MemberOperator.SUBTRACT,
MemberOperator.AND,
MemberOperator.OR):
return False

elif self._member_type is MemberType.DICT\
if self._member_type is MemberType.DICT\
and operator not in (MemberOperator.ASSIGN,
MemberOperator.ADD,
MemberOperator.SUBTRACT,
@@ -768,7 +773,7 @@ def accepts_value(self, value):
if value is MemberSpecialValue.NYAN_NONE:
return self._member_type is MemberType.OPTIONAL

elif self.is_modifier():
if self.is_modifier():
return self._element_types[0].accepts_value(value)

# inf is only used for ints and floats
@@ -799,12 +804,16 @@ def _sanity_check(self):
# element types of complex types cannot be complex
for elem_type in self._element_types:
if elem_type.is_real_complex():
raise Exception(f"{repr(self)}: element types cannot be complex but contains {elem_type}")
raise Exception(
f"{repr(self)}: element types cannot be complex "
f"but contains {elem_type}")

else:
# if the member is not a composite, the element types should be None
if self._element_types:
raise Exception(f"{repr(self)}: member type has element types but is not a composite")
raise Exception(
f"{repr(self)}: member type has element types "
"but is not a composite")

def dump(self, import_tree=None, namespace=None):
"""
@@ -813,7 +822,7 @@ def dump(self, import_tree=None, namespace=None):
if self.is_primitive():
return self._member_type.value

elif self.is_object():
if self.is_object():
if import_tree:
sfqon = ".".join(import_tree.get_alias_fqon(
self._member_type.get_fqon(),
@@ -924,12 +933,19 @@ def is_initialized(self):
"""
return self.value is not None

def is_inherited(self):
@staticmethod
def is_inherited():
"""
Returns True if the member is inherited from another object.
"""
return False

def has_value(self):
"""
Returns True if the member has a value.
"""
return self.value is not None

def set_value(self, value, operator=None):
"""
Set the value of the nyan member to the specified value and
@@ -1044,16 +1060,17 @@ def _type_conversion(self):
elif self._member_type.get_real_type() is MemberType.DICT:
self.value = dict(self.value)

def _get_primitive_value_str(self, member_type, value, import_tree=None, namespace=None):
@staticmethod
def _get_primitive_value_str(member_type, value, import_tree=None, namespace=None):
"""
Returns the nyan string representation of primitive values.
Subroutine of _get_value_str()
Subroutine of _get_value_str(..)
"""
if member_type.get_real_type() in (MemberType.TEXT, MemberType.FILE):
return f"\"{value}\""

elif member_type.is_real_object():
if member_type.is_real_object():
if import_tree:
sfqon = ".".join(import_tree.get_alias_fqon(
value.get_fqon(),
@@ -1067,7 +1084,8 @@ def _get_primitive_value_str(self, member_type, value, import_tree=None, namespa

return f"{value}"

def _get_complex_value_str(self, indent_depth, member_type, value, import_tree=None, namespace=None):
def _get_complex_value_str(self, indent_depth, member_type, value,
import_tree=None, namespace=None):
"""
Returns the nyan string representation of complex values.
@@ -1124,23 +1142,21 @@ def _get_complex_value_str(self, indent_depth, member_type, value, import_tree=N
f"{concat_values}"
))

if line_length < LINE_WIDTH:
if line_length < MAX_LINE_WIDTH:
output_str += concat_values

elif stored_values:
output_str += "\n"

# How much space is left per formatted line
space_left = LINE_WIDTH - len((indent_depth + 2) * INDENT)
space_left = MAX_LINE_WIDTH - len((indent_depth + 2) * INDENT)

# Find the longest value's length
longest_len = len(max(stored_values, key=len))

# How man values of that length fit in one line
values_per_line = space_left // longest_len

if values_per_line < 1:
values_per_line = 1
values_per_line = max(values_per_line, 1)

output_str += (indent_depth + 2) * INDENT

@@ -1187,7 +1203,7 @@ def _get_value_str(self, indent_depth, import_tree=None, namespace=None):
namespace=namespace
)

elif self.is_complex():
if self.is_complex():
return self._get_complex_value_str(
indent_depth,
self._member_type,
@@ -1196,11 +1212,10 @@ def _get_value_str(self, indent_depth, import_tree=None, namespace=None):
namespace=namespace
)

else:
raise Exception(f"{repr(self)} has no valid type")
raise Exception(f"{repr(self)} has no valid type")

def __str__(self):
return self._get_value_str()
return self._get_value_str(indent_depth=0)

def __repr__(self):
return f"NyanMember<{self.name}: {self._member_type}>"
@@ -1334,12 +1349,6 @@ def is_initialized(self):
return super().is_initialized() or\
self._parent.get_member_by_name(self.name, self._origin).is_initialized()

def has_value(self):
"""
Returns True if the inherited member has a value
"""
return self.value is not None

def dump(self, indent_depth, import_tree=None, namespace=None):
"""
Returns the string representation of the member.
4 changes: 2 additions & 2 deletions openage/util/context.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2016 the openage authors. See copying.md for legal info.
# Copyright 2015-2021 the openage authors. See copying.md for legal info.

"""
Provides some utility context guards.
@@ -15,4 +15,4 @@ def __enter__():

@staticmethod
def __exit__(exc_type, exc_value, traceback):
del exc_type, exc_value, traceback # unused
pass
6 changes: 4 additions & 2 deletions openage/util/fslike/filecollection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2017 the openage authors. See copying.md for legal info.
# Copyright 2015-2021 the openage authors. See copying.md for legal info.

"""
Provides Filecollection, a utility class for combining multiple file-like
@@ -18,6 +18,7 @@ class FileCollection(FSLikeObject):
Uses lambdas to access files somewhere else on the fly.
"""

def __init__(self):
super().__init__()

@@ -212,13 +213,14 @@ def watch(self, parts, callback):
return False

def poll_watches(self):
del self # unused
pass


class FileCollectionPath(Path):
"""
Provides an additional method for adding a file at this path.
"""

def add_file(self, open_r=None, open_w=None, filesize=None, mtime=None):
"""
All parent directories are 'created', if needed.
9 changes: 8 additions & 1 deletion openage/util/fslike/wrapper.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2020 the openage authors. See copying.md for legal info.
# Copyright 2015-2021 the openage authors. See copying.md for legal info.

"""
Provides
@@ -28,6 +28,7 @@ class Wrapper(FSLikeObject):
Inherit to override individual methods.
Pass a context guard to protect calls.
"""

def __init__(self, obj, contextguard=None):
if not isinstance(obj, Path):
raise TypeError(f"Path expected as obj, got '{type(obj)}'")
@@ -68,6 +69,9 @@ def resolve_r(self, parts):
def resolve_w(self, parts):
return self.obj.joinpath(parts) if self.writable(parts) else None

def get_native_path(self, parts):
return self.obj.joinpath(parts).resolve_native_path() if self.exists(parts) else None

def list(self, parts):
with self.contextguard:
return list(self.obj.joinpath(parts).list())
@@ -128,6 +132,7 @@ class WriteBlocker(ReadOnlyFSLikeObject, Wrapper):
All writing calls raise IOError, and writable returns False.
"""

def __repr__(self):
return f"WriteBlocker({repr(self.obj)})"

@@ -136,6 +141,7 @@ class Synchronizer(Wrapper):
"""
Wraps a FSLikeObject, securing all wrapped calls with a mutex.
"""

def __init__(self, obj):
self.lock = Lock()
super().__init__(obj, self.lock)
@@ -151,6 +157,7 @@ class GuardedFile(FileLikeObject):
Wraps file-like objects, protecting calls to their members with the given
context guard.
"""

def __init__(self, obj, guard):
super().__init__()
self.obj = obj

0 comments on commit bf0094c

Please sign in to comment.