Skip to content

Commit fe54cad

Browse files
committed
Deprecate self.store in favor of self.storage
1 parent 59d0a18 commit fe54cad

File tree

10 files changed

+149
-206
lines changed

10 files changed

+149
-206
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
<!-- Please add changes under the Unreleased section that reads 'No current changes' otherwise -->
44

5-
# Unreleased
5+
# v2.6.0
66

7-
- Support static host info methods in Registration
7+
- Deprecates self.store in favor of self.storage
8+
- Support static host info methods in registration
89
- New `find_experiments` method to simplify recursive search for experiments in a given directory
910

1011
## v2.5.2

docs/guide/components.md

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ For convenience, the dict interface can be accessed using the `.` object notatio
9898

9999
Flags are configuration values that are associated with the particular execution, for example the random seeds or worker IDs. They are accessible via the `self.flags` object, that supports the `.` object notation. You can add your own flags through basic assignment, e.g. ``self.flags.counter = 1``. To avoid name collision, all native machinable flags use UPPERCASE (e.g. ``self.flags.SEED``).
100100

101-
## self.store
101+
## self.storage
102102

103-
The interface `self.store` allows for the storing of data and results of the components. Note that you don't have to specify where the data is being stored. machinable will manage unique directories automatically. The data can later be retrieved using the [Storage](./storage.md) interface.
103+
`self.storage` provides access to the storage directory of the component (each component directy name is unique and managed automatically so you don't have to specify where the data is being stored). The data can later be retrieved using the [storage interfaces](./storage.md).
104104

105105
**Log**
106106

107-
`self.store.log` or `self.log` provides a standard logger interface that outputs to the console and a log file.
107+
`self.storage.log` or `self.log` provides a standard logger interface that outputs to the console and a log file.
108108

109109
``` python
110110
self.log.info('Component created')
@@ -113,7 +113,7 @@ self.log.debug('Component initialized')
113113

114114
**Records**
115115

116-
`self.store.record` or `self.record` provides an interface for tabular logging, that is, storing recurring data points at each iteration. The results become available as a table where each row represents each iteration.
116+
`self.storage.record` or `self.record` provides an interface for tabular logging, that is, storing recurring data points at each iteration. The results become available as a table where each row represents each iteration.
117117

118118
``` python
119119
for iteration in range(10):
@@ -129,27 +129,22 @@ for iteration in range(10):
129129

130130
If you use the `on_execute_iteration` event, iteration information and `record.save()` will be triggered automatically at the end of each iteration.
131131

132-
Sometimes it is useful to have multiple tabular loggers, for example to record training and validation performance separately. You can create custom record loggers using `self.store.get_record_writer(scope)` which returns a new instance of a record writer that you can use just like the main record writer.
132+
Sometimes it is useful to have multiple tabular loggers, for example to record training and validation performance separately. You can create custom record loggers using `self.storage.get_record_writer(scope)` which returns a new instance of a record writer that you can use just like the main record writer.
133133

134-
**Store**
134+
**Custom data**
135135

136-
You can use `self.store.write()` to write any other Python object, for example:
136+
Any other data can be stored in the `data/` subdirectory.
137137

138-
```python
139-
self.store.write('final_accuracy', [0.85, 0.92])
140-
```
141-
Note that to protect unintended data loss, overwriting will fail unless the ``overwrite`` argument is explicitly set.
142-
143-
For larger data structures, it can be more suitable to write data in specific file formats by appending a file extension, i.e.:
138+
You can use `self.storage.write_data()` to write any other Python object, for example:
144139

145140
``` python
146-
self.store.write('data.txt', 'a string')
147-
self.store.write('data.p', generic_object)
148-
self.store.write('data.json', jsonable_object)
149-
self.store.write('data.npy', numpy_array)
141+
self.storage.save_data('data.txt', 'a string')
142+
self.storage.save_data('data.p', generic_object)
143+
self.storage.save_data('data.json', jsonable_object)
144+
self.storage.save_data('data.npy', numpy_array)
150145
```
151146

152-
Refer to the store [reference](./components.md#store) for more details.
147+
To protect against unintended data loss, you can set `overwrite=False`.
153148

154149
## Config methods
155150

src/machinable/core/component.py

Lines changed: 46 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ def unserialize(cls, serialized):
144144

145145
@staticmethod
146146
def save(component):
147-
if component.node is not None or component.store is None:
147+
if component.node is not None or component.storage is None:
148148
return False
149-
component.store.write(
149+
component.storage.write(
150150
"state.json",
151151
{
152152
"component": component.component_state.serialize(),
@@ -185,7 +185,7 @@ def __init__(self, config: dict = None, flags: dict = None, node=None):
185185

186186
self._node: Optional[Component] = node
187187
self._components: Optional[List[Component]] = None
188-
self._store: Optional[Store] = None
188+
self._storage = None
189189
self._events = Events()
190190
self._actor_config = None
191191
self._storage_config = None
@@ -261,25 +261,30 @@ def components(self, value):
261261
self._components = value
262262

263263
@property
264-
def store(self) -> Store:
265-
if self._store is None and isinstance(self.node, Component):
264+
def store(self):
265+
# deprecated alias
266+
return self.storage
267+
268+
@property
269+
def storage(self):
270+
if self._storage is None and isinstance(self.node, Component):
266271
# forward to node store if available
267-
return self.node.store
268-
return self._store
272+
return self.node.storage
273+
return self._storage
269274

270-
@store.setter
271-
def store(self, value):
272-
self._store = value
275+
@storage.setter
276+
def storage(self, value):
277+
self._storage = value
273278

274279
@property
275280
def record(self) -> Record:
276281
"""Record writer instance"""
277-
return self.store.record
282+
return self.storage.record
278283

279284
@property
280285
def log(self) -> Log:
281286
"""Log writer instance"""
282-
return self.store.log
287+
return self.storage.log
283288

284289
@property
285290
def events(self) -> Events:
@@ -308,26 +313,25 @@ def dispatch(
308313
self.on_init_storage(storage_config)
309314

310315
self._storage_config = storage_config
311-
self.store = Store(component=self, config=storage_config)
316+
self.storage = Store(component=self, config=storage_config)
312317

313318
if not storage_config["url"].startswith("mem://"):
314319
OutputRedirection.apply(
315320
self._storage_config["output_redirection"],
316-
self.store.get_stream,
321+
self.storage.get_stream,
317322
"output.log",
318323
)
319324

320-
if not self.store.exists("host.json", _meta=True):
321-
self.store.write("host.json", get_host_info(), _meta=True)
322-
if not self.store.exists("component.json", _meta=True):
323-
self.store.write("component.json", self.serialize(), _meta=True)
324-
if not self.store.exists("components.json", _meta=True):
325-
self.store.write(
325+
if not self.storage.has_file("host.json"):
326+
self.storage.save_file("host.json", get_host_info())
327+
if not self.storage.has_file("component.json"):
328+
self.storage.save_file("component.json", self.serialize())
329+
if not self.storage.has_file("components.json"):
330+
self.storage.save_file(
326331
"components.json",
327332
[component.serialize() for component in self.components]
328333
if self.components
329334
else [],
330-
_meta=True,
331335
)
332336
self.component_state.save(self)
333337

@@ -442,12 +446,12 @@ def execute(self):
442446
if self.on_after_execute_iteration(iteration) is not False:
443447
# trigger records.save() automatically
444448
if (
445-
self.store
446-
and self.store.has_records()
447-
and not self.store.record.empty()
449+
self.storage
450+
and self.storage.has_records()
451+
and not self.storage.record.empty()
448452
):
449-
self.store.record["_iteration"] = iteration
450-
self.store.record.save()
453+
self.record["_iteration"] = iteration
454+
self.record.save()
451455
except (KeyboardInterrupt, StopIteration):
452456
callback = StopIteration
453457

@@ -500,9 +504,7 @@ def refresh_status(self, log_errors=False):
500504
"""
501505
try:
502506
self.component_status["heartbeat_at"] = str(pendulum.now())
503-
self.store.write(
504-
"status.json", self.component_status, overwrite=True, _meta=True
505-
)
507+
self.storage.save_file("status.json", self.component_status)
506508
except (IOError, Exception) as ex:
507509
if log_errors:
508510
self.log.error(
@@ -513,29 +515,6 @@ def refresh_status(self, log_errors=False):
513515

514516
return True
515517

516-
def get_url(self, append=""):
517-
"""Returns the storage URL of the component"""
518-
return os.path.join(
519-
self._storage_config["url"],
520-
os.path.join(
521-
self._storage_config.get("directory", ""),
522-
self._storage_config["experiment"],
523-
self._storage_config.get("component", ""),
524-
append,
525-
),
526-
)
527-
528-
def local_directory(self, append=""):
529-
"""Returns the local storage filesystem path, or False if non-local
530-
531-
# Returns
532-
Local filesystem path, or False if non-local
533-
"""
534-
if not self._storage_config["url"].startswith("osfs://"):
535-
return False
536-
537-
return os.path.join(self.get_url().split("osfs://")[-1], append)
538-
539518
def set_seed(self, seed=None) -> bool:
540519
"""Applies a global random seed
541520
@@ -564,16 +543,16 @@ def save_checkpoint(self, path: str = None, timestep=None) -> Union[bool, str]:
564543
timestep: int = len(self.component_state.checkpoints)
565544

566545
if path is None:
567-
if not self.store:
546+
if not self.storage:
568547
raise ValueError("You need to specify a checkpoint path")
569548

570-
fs_prefix, basepath = self.store.config["url"].split("://")
549+
fs_prefix, basepath = self.storage.config["url"].split("://")
571550
if fs_prefix != "osfs":
572551
# todo: support non-local filesystems via automatic sync
573552
raise NotImplementedError(
574553
"Checkpointing to non-os file systems is currently not supported."
575554
)
576-
checkpoint_path = self.store.get_path("checkpoints", create=True)
555+
checkpoint_path = self.storage.get_path("checkpoints", create=True)
577556
path = os.path.join(os.path.expanduser(basepath), checkpoint_path)
578557

579558
checkpoint = self.on_save(path, timestep)
@@ -591,8 +570,8 @@ def restore_checkpoint(self, checkpoint):
591570
# Arguments
592571
filepath: Checkpoint filepath
593572
"""
594-
if self.store is not None:
595-
self.store.log.info(f"Restoring checkpoint `{checkpoint}`")
573+
if self.storage is not None:
574+
self.log.info(f"Restoring checkpoint `{checkpoint}`")
596575
return self.on_restore(checkpoint)
597576

598577
def serialize(self):
@@ -811,26 +790,24 @@ def dispatch(self, components_config, storage_config, actor_config=None):
811790
payload["components"] = [
812791
config_map(component) for component in components
813792
]
814-
elif key == "store" or key == "_store":
815-
if key == "_store":
816-
payload["store"] = storage_config
793+
elif key == "storage" or key == "_storage":
794+
if key == "_storage":
795+
payload["storage"] = storage_config
817796
else:
818-
store = Store(component=self, config=storage_config)
819-
store.write("host.json", get_host_info(), _meta=True)
820-
store.write(
821-
"component",
797+
storage = Store(component=self, config=storage_config)
798+
storage.save_file("host.json", get_host_info())
799+
storage.save_file(
800+
"component.json",
822801
{"config": self.node["config"], "flags": self.node["flags"]},
823-
_meta=True,
824802
)
825-
store.write(
826-
"components",
803+
storage.save_file(
804+
"components.json",
827805
[
828806
{"config": c["config"], "flags": c["flags"]}
829807
for c in components
830808
],
831-
_meta=True,
832809
)
833-
payload["store"] = store
810+
payload["storage"] = storage
834811
else:
835812
raise ValueError(
836813
f"Unrecognized argument: '{key}'. "

0 commit comments

Comments
 (0)