vberlier / nbtlib

A python library to read and edit nbt data.
MIT License
119 stars 16 forks source link

Allow integers to create and add with Path. Fix #146 #148

Closed MestreLion closed 2 years ago

MestreLion commented 2 years ago

This effectively treats an integer x as if it were the string "[x]", allowing Path(x) and x + Path(...) + x in addition to current Path(...)[x].

There are several possible implementation approaches, including a straightforward if isinstance(x, int): x = f"[{int(x)}]" in __new__, __add__ and __radd__, then letting it parse as an actual string.

However, not only that approach is very inefficient, as it calls the parser and tokenization for a known outcome, but also this was not the approach taken by __getitem__, currently the only method that can be used as reference on how to properly handle integers.

It is also important be consistent with the current semantics of Path(x) and Path + x, as they're different from Path[x] for strings and Paths, so do not converge to using Path[x] for both. Even if for integers it ends up being the same result, as integers can only be a single index, do not rely on that and keep semantics distinct and consistent with the string code path.

So in __new__, instead of resorting to a return cls()[x] shortcut, we call the same classmethod as str and Path do, cls.from_accessors(), passing the same argument as getitem uses: a tuple with a single element ListIndex(index=x), which is also, not coincidentally, the same result of parsing "[x]".

As for __add__/__radd__, again we use the same semantics as used by str: Path(...) + x == Path(...)[Path(x)], and x + Path(...) == Path(x)[Path(...)] And, as we just defined Path(x) for an integer x, we can simply extend the isinstance(x, str) check to include int, without creating a new case, thus enforcing consistent semantics.