Reputation: 2945
I'm using the attrs library to create data structure for paths. I want the first attribute to be the root directory which other are automatically joined with. I'd like to have something like that:
def my_converter(obj, value):
return os.path.join(obj.root, value)
class Paths:
root = attr.ib()
relative = attr.ib(converter=my_converter)
This would do the trick, but converter
function is given one argument only.
Is there a clean way to convert the value using other attributes before validation?
The validator
takes three arguments (one of which is the object) but it is not the right place to convert values. Also putting everything into __attrs_post_init__
defeats the purpose of using attrs.
Upvotes: 2
Views: 1312
Reputation: 4146
You could use a third attribute and a default:
import os
import attr
@attr.s
class Paths:
root = attr.ib()
_relative = attr.ib(repr=False)
full = attr.ib()
@full.default
def _full_factory(self):
return os.path.join(self.root, self._relative)
Which gives you:
>>> Paths("/home", "foo")
Paths(root='/home', full='/home/foo')
I personally prefer straight-forward and well-named @classmethod
factory methods in cases like this. They tend to be more readable and you can easily dodge them when writing tests.
Upvotes: 1