[PATCH 2 of 3] repoview: extract a factory function of proxy class
Yuya Nishihara
yuya at tcha.org
Tue Dec 5 08:40:35 EST 2017
# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1512478233 -32400
# Tue Dec 05 21:50:33 2017 +0900
# Node ID 4c2ec6b9d65bd38a7ac9138241a42a2e60d0a605
# Parent ac2f7bb76d318b3f32d83f4674d99a78bb3ea42b
repoview: extract a factory function of proxy class
This makes sure that dynamically-created class objects are isolated from
local binding of repo instances. The type cache is moved to module level
as it isn't tied to each instance.
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -502,9 +502,6 @@ class localrepository(object):
# post-dirstate-status hooks
self._postdsstatus = []
- # Cache of types representing filtered repos.
- self._filteredrepotypes = weakref.WeakKeyDictionary()
-
# generic mapping between names and nodes
self.names = namespaces.namespaces()
@@ -680,20 +677,8 @@ class localrepository(object):
def filtered(self, name):
"""Return a filtered version of a repository"""
- # Python <3.4 easily leaks types via __mro__. See
- # https://bugs.python.org/issue17950. We cache dynamically
- # created types so this method doesn't leak on every
- # invocation.
-
- key = self.unfiltered().__class__
- if key not in self._filteredrepotypes:
- # Build a new type with the repoview mixin and the base
- # class of this repo.
- class filteredrepo(repoview.repoview, key):
- pass
- self._filteredrepotypes[key] = filteredrepo
-
- return self._filteredrepotypes[key](self, name)
+ cls = repoview.newtype(self.unfiltered().__class__)
+ return cls(self, name)
@repofilecache('bookmarks', 'bookmarks.current')
def _bookmarks(self):
diff --git a/mercurial/repoview.py b/mercurial/repoview.py
--- a/mercurial/repoview.py
+++ b/mercurial/repoview.py
@@ -9,6 +9,7 @@
from __future__ import absolute_import
import copy
+import weakref
from .node import nullrev
from . import (
@@ -240,3 +241,16 @@ class repoview(object):
def __delattr__(self, attr):
return delattr(self._unfilteredrepo, attr)
+
+# Python <3.4 easily leaks types via __mro__. See
+# https://bugs.python.org/issue17950. We cache dynamically created types
+# so they won't be leaked on every invocation of repo.filtered().
+_filteredrepotypes = weakref.WeakKeyDictionary()
+
+def newtype(base):
+ """Create a new type with the repoview mixin and the given base class"""
+ if base not in _filteredrepotypes:
+ class filteredrepo(repoview, base):
+ pass
+ _filteredrepotypes[base] = filteredrepo
+ return _filteredrepotypes[base]
diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
--- a/mercurial/statichttprepo.py
+++ b/mercurial/statichttprepo.py
@@ -166,8 +166,6 @@ class statichttprepository(localrepo.loc
self.encodepats = None
self.decodepats = None
self._transref = None
- # Cache of types representing filtered repos.
- self._filteredrepotypes = {}
def _restrictcapabilities(self, caps):
caps = super(statichttprepository, self)._restrictcapabilities(caps)
More information about the Mercurial-devel
mailing list