Skip to content

Commit f8cdef5

Browse files
author
Maxim Zhiltsov
authored
Fixes (#76)
* Prevent inplace file copying when saving images * Add more dataset tests * Move config tests to separate file * Fix labelmap parameter in voc converter * Update config class: - Fix eq comparison with other classes - Add parsing and dumping into a file - Rename DefaultConfig to DictConfig * Rename from_cmdline to parse_cmdline
1 parent c473ba9 commit f8cdef5

File tree

13 files changed

+138
-89
lines changed

13 files changed

+138
-89
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
- Allow plugins inherited from `Extractor` (instead of only `SourceExtractor`) (<https://github.com/openvinotoolkit/datumaro/pull/70>)
2929
- Windows installation with `pip` for `pycocotools` (<https://github.com/openvinotoolkit/datumaro/pull/73>)
3030
- `YOLO` extractor path matching on Windows (<https://github.com/openvinotoolkit/datumaro/pull/73>)
31+
- Fixed inplace file copying when saving images (<https://github.com/openvinotoolkit/datumaro/pull/76>)
32+
- Fixed `labelmap` parameter type checking in `VOC` converter (<https://github.com/openvinotoolkit/datumaro/pull/76>)
3133

3234
### Security
3335
-

datumaro/cli/commands/convert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def convert_command(args):
6868
except KeyError:
6969
raise CliException("Converter for format '%s' is not found" % \
7070
args.output_format)
71-
extra_args = converter.from_cmdline(args.extra_args)
71+
extra_args = converter.parse_cmdline(args.extra_args)
7272

7373
filter_args = FilterModes.make_filter_args(args.filter_mode)
7474

datumaro/cli/contexts/model/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ def add_command(args):
5959
assert args.name not in project.config.models, args.name
6060

6161
try:
62-
launcher = project.env.launchers.get(args.launcher)
62+
launcher = project.env.launchers[args.launcher]
6363
except KeyError:
6464
raise CliException("Launcher '%s' is not found" % args.launcher)
6565

6666
cli_plugin = getattr(launcher, 'cli_plugin', launcher)
67-
model_args = cli_plugin.from_cmdline(args.extra_args)
67+
model_args = cli_plugin.parse_cmdline(args.extra_args)
6868

6969
if args.copy:
7070
log.info("Copying model data")

datumaro/cli/contexts/project/__init__.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ def import_command(args):
200200
raise CliException("Unknown format '%s'. A format can be added"
201201
"by providing an Extractor and Importer plugins" % fmt)
202202

203-
if hasattr(arg_parser, 'from_cmdline'):
204-
extra_args = arg_parser.from_cmdline(args.extra_args)
203+
if hasattr(arg_parser, 'parse_cmdline'):
204+
extra_args = arg_parser.parse_cmdline(args.extra_args)
205205
else:
206206
raise CliException("Format '%s' does not accept "
207207
"extra parameters" % fmt)
@@ -330,26 +330,24 @@ def export_command(args):
330330
dst_dir = osp.abspath(dst_dir)
331331

332332
try:
333-
converter = project.env.converters.get(args.format)
333+
converter = project.env.converters[args.format]
334334
except KeyError:
335335
raise CliException("Converter for format '%s' is not found" % \
336336
args.format)
337337

338-
extra_args = converter.from_cmdline(args.extra_args)
339-
def converter_proxy(extractor, save_dir):
340-
return converter.convert(extractor, save_dir, **extra_args)
338+
extra_args = converter.parse_cmdline(args.extra_args)
341339

342340
filter_args = FilterModes.make_filter_args(args.filter_mode)
343341

344342
log.info("Loading the project...")
345343
dataset = project.make_dataset()
346344

347345
log.info("Exporting the project...")
348-
dataset.export_project(
349-
save_dir=dst_dir,
350-
converter=converter_proxy,
351-
filter_expr=args.filter,
352-
**filter_args)
346+
347+
if args.filter:
348+
dataset = dataset.filter(args.filter, **filter_args)
349+
dataset.export(args.format, save_dir=dst_dir, **extra_args)
350+
353351
log.info("Project exported to '%s' as '%s'" % \
354352
(dst_dir, args.format))
355353

@@ -674,13 +672,13 @@ def transform_command(args):
674672
dst_dir = osp.abspath(dst_dir)
675673

676674
try:
677-
transform = project.env.transforms.get(args.transform)
675+
transform = project.env.transforms[args.transform]
678676
except KeyError:
679677
raise CliException("Transform '%s' is not found" % args.transform)
680678

681679
extra_args = {}
682-
if hasattr(transform, 'from_cmdline'):
683-
extra_args = transform.from_cmdline(args.extra_args)
680+
if hasattr(transform, 'parse_cmdline'):
681+
extra_args = transform.parse_cmdline(args.extra_args)
684682

685683
log.info("Loading the project...")
686684
dataset = project.make_dataset()

datumaro/components/cli_plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def build_cmdline_parser(cls, **kwargs):
3131
return argparse.ArgumentParser(**args)
3232

3333
@classmethod
34-
def from_cmdline(cls, args=None):
34+
def parse_cmdline(cls, args=None):
3535
if args and args[0] == '--':
3636
args = args[1:]
3737
parser = cls.build_cmdline_parser()

datumaro/components/config.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,19 @@ def __setattr__(self, key, value):
150150

151151
def __eq__(self, other):
152152
try:
153-
for k, my_v in self.items(allow_internal=False):
153+
keys = set(self.keys()) | set(other.keys())
154+
for k in keys:
155+
my_v = self[k]
154156
other_v = other[k]
155157
if my_v != other_v:
156158
return False
157159
return True
158-
except Exception:
160+
except (KeyError, AttributeError):
159161
return False
160162

163+
def __repr__(self):
164+
return repr(dict(self))
165+
161166
def update(self, other):
162167
for k, v in other.items():
163168
self.set(k, v)
@@ -205,23 +210,29 @@ def set(self, key, value):
205210
return value
206211

207212
@staticmethod
208-
def parse(path):
209-
with open(path, 'r') as f:
210-
return Config(yaml.safe_load(f))
213+
def parse(path, *args, **kwargs):
214+
if isinstance(path, str):
215+
with open(path, 'r') as f:
216+
return Config(yaml.safe_load(f), *args, **kwargs)
217+
else:
218+
return Config(yaml.safe_load(path), *args, **kwargs)
211219

212220
@staticmethod
213221
def yaml_representer(dumper, value):
214222
return dumper.represent_data(
215223
value._items(allow_internal=False, allow_fallback=False))
216224

217225
def dump(self, path):
218-
with open(path, 'w+') as f:
219-
yaml.dump(self, f)
226+
if isinstance(path, str):
227+
with open(path, 'w') as f:
228+
yaml.dump(self, f)
229+
else:
230+
yaml.dump(self, path)
220231

221232
yaml.add_multi_representer(Config, Config.yaml_representer)
222233

223234

224-
class DefaultConfig(Config):
235+
class DictConfig(Config):
225236
def __init__(self, default=None):
226237
super().__init__()
227238
self.__dict__['_default'] = default

datumaro/components/config_model.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# SPDX-License-Identifier: MIT
55

66
from datumaro.components.config import Config, \
7-
DefaultConfig as _DefaultConfig, \
7+
DictConfig as _DictConfig, \
88
SchemaBuilder as _SchemaBuilder
99

1010

@@ -34,9 +34,9 @@ def __init__(self, config=None):
3434
.add('format_version', int) \
3535
\
3636
.add('subsets', list) \
37-
.add('sources', lambda: _DefaultConfig(
37+
.add('sources', lambda: _DictConfig(
3838
lambda v=None: Source(v))) \
39-
.add('models', lambda: _DefaultConfig(
39+
.add('models', lambda: _DictConfig(
4040
lambda v=None: Model(v))) \
4141
\
4242
.add('models_dir', str, internal=True) \

datumaro/components/converter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ def _save_image(self, item, path=None):
6868

6969
os.makedirs(osp.dirname(path), exist_ok=True)
7070
if src_ext == dst_ext and osp.isfile(item.image.path):
71-
shutil.copyfile(item.image.path, path)
71+
if item.image.path != path:
72+
shutil.copyfile(item.image.path, path)
7273
elif src_ext == dst_ext and isinstance(item.image, ByteImage):
7374
with open(path, 'wb') as f:
7475
f.write(item.image.get_bytes())

datumaro/plugins/voc_format/converter.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from lxml import etree as ET
1414

1515
from datumaro.components.converter import Converter
16-
from datumaro.components.extractor import (DEFAULT_SUBSET_NAME, AnnotationType,
16+
from datumaro.components.extractor import (AnnotationType,
1717
CompiledMask, LabelCategories)
1818
from datumaro.util import find, str_to_bool
1919
from datumaro.util.image import save_image
@@ -104,6 +104,7 @@ def __init__(self, extractor, save_dir,
104104

105105
if label_map is None:
106106
label_map = LabelmapType.source.name
107+
assert isinstance(label_map, (str, dict)), label_map
107108
self._load_categories(label_map)
108109

109110
def apply(self):
@@ -469,9 +470,9 @@ def _load_categories(self, label_map_source):
469470
label_map = parse_label_map(label_map_source)
470471

471472
else:
472-
raise Exception("Wrong labelmap specified, "
473+
raise Exception("Wrong labelmap specified: '%s', "
473474
"expected one of %s or a file path" % \
474-
', '.join(t.name for t in LabelmapType))
475+
(label_map_source, ', '.join(t.name for t in LabelmapType)))
475476

476477
# There must always be a label with color (0, 0, 0) at index 0
477478
bg_label = find(label_map.items(), lambda x: x[1][0] == (0, 0, 0))

datumaro/util/os_util.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
# Copyright (C) 2020 - 2021 Intel Corporation
1+
# Copyright (C) 2020-2021 Intel Corporation
32
#
43
# SPDX-License-Identifier: MIT
54

0 commit comments

Comments
 (0)