Wish list and ideas for xdol #1
Replies: 2 comments 1 reply
-
Register yaml ValueCodec when yaml availableimport yaml
def yaml_load(stream, Loader=yaml.SafeLoader):
"""Load a YAML stream."""
return yaml.load(stream, Loader)
def yaml_dump(data, Dumper=None, **kwds):
"""Dump data to a YAML stream."""
return yaml.dump(data, Dumper=Dumper, **kwds) |
Beta Was this translation helpful? Give feedback.
-
Appendables and AppendingSettablesIn So there, we have a Here, the problem we want to solve here is (partial dual) ability to have a For example, we're going through some files (indexed by Would be easier if the interface was (Note that I said partial dual because here all we're assuming is that Here are some ideas around that. First let's setup a few types to annotate our code with, and convey the concepts and language around them. from typing import Protocol, Iterable
class Settable(Protocol):
"""Objects where you can do self[k] = v"""
def __setitem__(self, k, v):
"""That is, self[k] = v"""
class Appendable(Protocol):
"""Objects that have an append method"""
def append(self, obj):
"""Usually has the effect of adding obj to self. Usually at "the end" of it"""
# In case we want to use it later:
class Extendable(Protocol):
def extend(self, objs: Iterable):
"""Usually has the effect of adding an iteralble of objs to self.
Usually at "the end" of it.""" Now we'll make a few appendables with different backends to them. # Append to a string------------------------------------
class AppendableString(str):
_repr = str
def __init__(self, initial_string=""):
self._chars = list(initial_string)
def append(self, string):
self._chars.extend(list(string))
def __str__(self):
return ''.join(self._chars)
def __eq__(self, __value: object) -> bool:
return str(self) == str(__value)
def __repr__(self) -> str:
return self._repr(self)
def ch_repr(self, repr_func):
"""To change the repr function
(for example, if strings are too big, you way want to contain their display)
"""
self._repr = repr_func
return self
# Usage
a = AppendableString()
assert isinstance(a, str)
a.append('app')
a.append('end')
assert str(a) == 'append'
a == 'append'
# Append to a file ------------------------------------
from dataclasses import dataclass
@dataclass
class AppendableFile:
filepath: str
def append(self, obj):
with open(self.filepath, 'a') as f:
f.write(obj)
return self
# Usage
from tempfile import NamedTemporaryFile
filepath = NamedTemporaryFile().name
a = AppendableFile(filepath)
a = a.append('app')
a = a.append('end')
from pathlib import Path
assert Path(filepath).read_text() == 'append'
# Append to an open file ------------------------------------
import contextlib
@dataclass
class AppendableFilePointer:
"""Objects where obj.append(v) appends v to the obj.filepath open file.
AppendableFilePointer is a context manager, so you can use it in a with statement,
which will have the effect of opening and closing the file for you.
Normal usage is:
>>> from tempfile import NamedTemporaryFile
>>> filepath = NamedTemporaryFile().name
>>> with AppendableFilePointer(filepath) as afp:
... afp.append('app')
... afp.append('end')
>>> from pathlib import Path
>>> assert Path(filepath).read_text() == 'append'
"""
filepath: str
def __enter__(self):
self.f = open(self.filepath, 'a')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
return False
def append(self, obj):
self.f.write(obj)
return self
# Usage
from tempfile import NamedTemporaryFile
filepath = NamedTemporaryFile().name
with AppendableFilePointer(filepath) as afp:
afp.append('app')
afp.append('end')
from pathlib import Path
assert Path(filepath).read_text() == 'append'
def return_kv_tuple(k, v):
return k, v
def repr_of_appendale_attr(obj):
return repr(obj.appendable)
def repr_of_obj(obj):
return obj.super().__repr__()
from typing import Callable
@dataclass
class AppendingSettable:
"""A MutableMapping s where s[k] = v has the effect of s.append((k, v)
The appendable is an object that has an append method.
The encoder is a function that encodes the (k, v) pair into whatever format the
appendable expects.
"""
appendable: Appendable
kv_encoder: Callable = return_kv_tuple
repr_func: Callable = repr_of_appendale_attr
def __setitem__(self, k, v):
encoded_kv = self.kv_encoder(k, v)
self.appendable.append(encoded_kv)
def __repr__(self) -> str:
return self.repr_func(self)
def __eq__(self, __value: object) -> bool:
if isinstance(__value, AppendingSettable):
return self.appendable == __value.appendable
else:
return self.appendable == __value
# Usage
s = AppendingSettable(appendable=[])
s['a'] = 1
s['b'] = 2
s.appendable == [('a', 1), ('b', 2)] Here are now a few examples using def csv_kv_encoder(k, v):
return f"{k},{v}\n"
s = AppendingSettable(appendable=list(), kv_encoder=csv_kv_encoder)
s['a'] = 1
s['b'] = 2
assert s == ['a,1\n', 'b,2\n']
s = AppendingSettable(appendable=AppendableString(), kv_encoder=csv_kv_encoder)
s['a'] = 1
s['b'] = 2
assert s == 'a,1\nb,2\n'
import yaml
def yaml_kv_encoder(k, v):
return yaml.dump({k: v})
s = AppendingSettable(AppendableString(), yaml_kv_encoder)
s['a'] = 1
s['b'] = 2
assert s == '''a: 1
b: 2
''' |
Beta Was this translation helpful? Give feedback.
-
To collect ideas and code that we may want to add to xdol
Beta Was this translation helpful? Give feedback.
All reactions