Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH v2 1/2] dblink: case insensitive support for bug #524236
Date: Mon, 17 Nov 2014 04:58:23
Message-Id: 20141116205810.24331079.dolsen@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH v2 1/2] dblink: case insensitive support for bug #524236 by Zac Medico
1 On Sun, 16 Nov 2014 17:29:26 -0800
2 Zac Medico <zmedico@g.o> wrote:
3
4 > This adds dblink._contents_contains, _contents_keys, and
5 > _contents_map_key methods that provide an interface for contents
6 > operations with "implicit" case handling. The new methods are
7 > implemented in a separate ContentsCaseSensitivityManager class,
8 > in order to avoid adding more bloat to vartree.py.
9 >
10 > X-Gentoo-Bug: 524236
11 > X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=524236
12 > ---
13 > .../dbapi/_ContentsCaseSensitivityManager.py | 54
14 > ++++++++++++++++++++++
15 > pym/portage/dbapi/vartree.py | 8 ++++ 2 files
16 > changed, 62 insertions(+) create mode 100644
17 > pym/portage/dbapi/_ContentsCaseSensitivityManager.py
18 >
19 > diff --git a/pym/portage/dbapi/_ContentsCaseSensitivityManager.py
20 > b/pym/portage/dbapi/_ContentsCaseSensitivityManager.py new file mode
21 > 100644 index 0000000..6b8301d
22 > --- /dev/null
23 > +++ b/pym/portage/dbapi/_ContentsCaseSensitivityManager.py
24 > @@ -0,0 +1,54 @@
25 > +# Copyright 2014 Gentoo Foundation
26 > +# Distributed under the terms of the GNU General Public License v2
27 > +
28 > +class ContentsCaseSensitivityManager(object):
29 > +
30 > + def __init__(self, db):
31 > +
32 > + self.getcontents = db.getcontents
33 > +
34 > + if "case-insensitive-fs" in db.settings.features:
35 > + self.unmap_key =
36 > self._unmap_key_case_insensitive
37 > + self.contains =
38 > self._contains_case_insensitive
39 > + self.keys = self._keys_case_insensitive
40 > + else:
41 > + self.unmap_key =
42 > self._unmap_key_case_sensitive
43 > + self.contains = self._contains_case_sensitive
44 > + self.keys = self._keys_case_sensitive
45 > +
46 > + self._contents_insensitive = None
47 > + self._reverse_key_map = None
48 > +
49 > + def clear_cache(self):
50 > + self._contents_insensitive = None
51 > + self._reverse_key_map = None
52 > +
53 > + def _case_insensitive_init(self):
54 > + self._contents_insensitive = dict(
55 > + (k.lower(), v) for k, v in
56 > self.getcontents().items())
57 > + self._reverse_key_map = dict(
58 > + (k.lower(), k) for k in self.getcontents())
59 > +
60 > + def _keys_case_insensitive(self):
61 > + if self._contents_insensitive is None:
62 > + self._case_insensitive_init()
63 > + return iter(self._contents_insensitive)
64 > +
65 > + def _contains_case_insensitive(self, key):
66 > + if self._contents_insensitive is None:
67 > + self._case_insensitive_init()
68 > + return key.lower() in self._contents_insensitive
69 > +
70 > + def _unmap_key_case_insensitive(self, key):
71 > + if self._reverse_key_map is None:
72 > + self._case_insensitive_init()
73 > + return self._reverse_key_map[key]
74 > +
75 > + def _keys_case_sensitive(self):
76 > + return iter(self.getcontents())
77 > +
78 > + def _contains_case_sensitive(self, key):
79 > + return key in self.getcontents()
80 > +
81 > + def _unmap_key_case_sensitive(self, key):
82 > + return key
83
84
85 Very nice, much better this way than adding to the dblink class
86 directly.
87
88 Just one thing left to do... Docstrings please. While normally you
89 don't NEED them for private functions, in this case they are exported
90 using the function pointer assignments. They are named quite well to
91 indicate their function, but document them anyway please.
92
93
94
95
96 > diff --git a/pym/portage/dbapi/vartree.py
97 > b/pym/portage/dbapi/vartree.py index 8b06f4c..22f41d0 100644
98 > --- a/pym/portage/dbapi/vartree.py
99 > +++ b/pym/portage/dbapi/vartree.py
100 > @@ -69,6 +69,7 @@ from _emerge.EbuildPhase import EbuildPhase
101 > from _emerge.emergelog import emergelog
102 > from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
103 > from _emerge.SpawnProcess import SpawnProcess
104 > +from ._ContentsCaseSensitivityManager import
105 > ContentsCaseSensitivityManager
106 > import errno
107 > import fnmatch
108 > @@ -1526,6 +1527,12 @@ class dblink(object):
109 > # compliance with RESTRICT=preserve-libs.
110 > self._preserve_libs = "preserve-libs" in
111 > mysettings.features
112 > + manager = ContentsCaseSensitivityManager(self)
113 > + self._contents_case_sensitivity_manager = manager
114 > + self._contents_unmap_key = manager.unmap_key
115 > + self._contents_contains = manager.contains
116 > + self._contents_keys = manager.keys
117 > +
118
119 Rather than so many function pointer assignments, why not
120
121 + self._contents = ContentsCaseSensitivityManager(self)
122
123 Then later use it like so...
124
125 + self._contents.unmap_key(...)
126 + self._contents.contains(...)
127 + self._contents.keys()
128 +
129
130 vardbapi calls will just get a similar one additional level of
131 direction.
132
133 <snipped from patch V2 2/2>
134 - for p in dblink(cpv).getcontents():
135 + for p in dblink(cpv)._contents_keys():
136
137 to:
138 - for p in dblink(cpv).getcontents():
139 + for p in dblink(cpv)._contents.keys():
140
141 It should be less confusing for future maintenance by having to track all the
142 pointer assignments to know what it is actually pointing at. It is a lot easier to find that _contents is a
143 ContentsCaseSensitivityManager class instance. Then all function calls directly refer to those functions
144 or the sensitivity set exported versions of them.
145
146
147 > def __hash__(self):
148 > return hash(self._hash_key)
149 >
150 > @@ -1612,6 +1619,7 @@ class dblink(object):
151 > self.contentscache = None
152 > self._contents_inodes = None
153 > self._contents_basenames = None
154 > + self._contents_case_sensitivity_manager.clear_cache()
155
156 again...
157
158 + self._contents.clear_cache()
159
160 >
161 > def getcontents(self):
162 > """
163
164
165
166 --
167 Brian Dolbec <dolsen>

Replies