The previous fix to this area worked, but was dropping bytes in
dict on Python 3. This was causing subtle breakage in
test-check-interfaces.py, and probably other things too.
Fixed now.
hg-reviewers |
The previous fix to this area worked, but was dropping bytes in
dict on Python 3. This was causing subtle breakage in
test-check-interfaces.py, and probably other things too.
Fixed now.
Automatic diff as part of commit; lint not applicable. |
Automatic diff as part of commit; unit tests not applicable. |
Users should subclass filecache and provide their own version of this | Users should subclass filecache and provide their own version of this | ||||
function to call the appropriate join function on 'obj' (an instance | function to call the appropriate join function on 'obj' (an instance | ||||
of the class that its member function was decorated). | of the class that its member function was decorated). | ||||
""" | """ | ||||
raise NotImplementedError | raise NotImplementedError | ||||
def __call__(self, func): | def __call__(self, func): | ||||
self.func = func | self.func = func | ||||
self.name = func.__name__.encode('ascii') | self.sname = func.__name__ | ||||
self.name = pycompat.sysbytes(self.sname) | |||||
return self | return self | ||||
def __get__(self, obj, type=None): | def __get__(self, obj, type=None): | ||||
# if accessed on the class, return the descriptor itself. | # if accessed on the class, return the descriptor itself. | ||||
if obj is None: | if obj is None: | ||||
return self | return self | ||||
# do we need to check if the file changed? | # do we need to check if the file changed? | ||||
if self.name in obj.__dict__: | if self.sname in obj.__dict__: | ||||
assert self.name in obj._filecache, self.name | assert self.name in obj._filecache, self.name | ||||
return obj.__dict__[self.name] | return obj.__dict__[self.sname] | ||||
entry = obj._filecache.get(self.name) | entry = obj._filecache.get(self.name) | ||||
if entry: | if entry: | ||||
if entry.changed(): | if entry.changed(): | ||||
entry.obj = self.func(obj) | entry.obj = self.func(obj) | ||||
else: | else: | ||||
paths = [self.join(obj, path) for path in self.paths] | paths = [self.join(obj, path) for path in self.paths] | ||||
# We stat -before- creating the object so our cache doesn't lie if | # We stat -before- creating the object so our cache doesn't lie if | ||||
# a writer modified between the time we read and stat | # a writer modified between the time we read and stat | ||||
entry = filecacheentry(paths, True) | entry = filecacheentry(paths, True) | ||||
entry.obj = self.func(obj) | entry.obj = self.func(obj) | ||||
obj._filecache[self.name] = entry | obj._filecache[self.name] = entry | ||||
obj.__dict__[self.name] = entry.obj | obj.__dict__[self.sname] = entry.obj | ||||
return entry.obj | return entry.obj | ||||
def __set__(self, obj, value): | def __set__(self, obj, value): | ||||
if self.name not in obj._filecache: | if self.name not in obj._filecache: | ||||
# we add an entry for the missing value because X in __dict__ | # we add an entry for the missing value because X in __dict__ | ||||
# implies X in _filecache | # implies X in _filecache | ||||
paths = [self.join(obj, path) for path in self.paths] | paths = [self.join(obj, path) for path in self.paths] | ||||
ce = filecacheentry(paths, False) | ce = filecacheentry(paths, False) | ||||
obj._filecache[self.name] = ce | obj._filecache[self.name] = ce | ||||
else: | else: | ||||
ce = obj._filecache[self.name] | ce = obj._filecache[self.name] | ||||
ce.obj = value # update cached copy | ce.obj = value # update cached copy | ||||
obj.__dict__[self.name] = value # update copy returned by obj.x | obj.__dict__[self.sname] = value # update copy returned by obj.x | ||||
def __delete__(self, obj): | def __delete__(self, obj): | ||||
try: | try: | ||||
del obj.__dict__[self.name] | del obj.__dict__[self.sname] | ||||
except KeyError: | except KeyError: | ||||
raise AttributeError(self.name) | raise AttributeError(self.sname) | ||||
def extdatasource(repo, source): | def extdatasource(repo, source): | ||||
"""Gather a map of rev -> value dict from the specified source | """Gather a map of rev -> value dict from the specified source | ||||
A source spec is treated as a URL, with a special case shell: type | A source spec is treated as a URL, with a special case shell: type | ||||
for parsing the output from a shell command. | for parsing the output from a shell command. | ||||
The data is parsed as a series of newline-separated records where | The data is parsed as a series of newline-separated records where |