public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] portage r12933 - main/branches/2.1.6/pym/portage
@ 2009-03-11  6:05 Zac Medico (zmedico)
  0 siblings, 0 replies; only message in thread
From: Zac Medico (zmedico) @ 2009-03-11  6:05 UTC (permalink / raw
  To: gentoo-commits

Author: zmedico
Date: 2009-03-11 06:05:37 +0000 (Wed, 11 Mar 2009)
New Revision: 12933

Modified:
   main/branches/2.1.6/pym/portage/__init__.py
   main/branches/2.1.6/pym/portage/util.py
Log:
In config.setcpv(), use LazyItemsDict to implement lazy evaluation of
PORTAGE_IUSE. The PORTAGE_IUSE value is lazily evaluated since re.escape()
is slow and the value is only used when an ebuild phase needs to be executed
(it's used only to generate QA notices). Thanks to Marat Radchenko
<slonopotamusorama@gmail.com> for identifying this performance issue and
submitting the initial patch which used a memoization approach instead of
lazy evaluation. (trunk r12673)

Modified: main/branches/2.1.6/pym/portage/__init__.py
===================================================================
--- main/branches/2.1.6/pym/portage/__init__.py	2009-03-11 06:05:17 UTC (rev 12932)
+++ main/branches/2.1.6/pym/portage/__init__.py	2009-03-11 06:05:37 UTC (rev 12933)
@@ -958,6 +958,19 @@
 	if not isinstance(test, config):
 		raise TypeError("Invalid type for config object: %s (should be %s)" % (test.__class__, config))
 
+def _lazy_iuse_regex(iuse_implicit):
+	"""
+	The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow
+	and the value is only used when an ebuild phase needs to be executed
+	(it's used only to generate QA notices).
+	"""
+	# Escape anything except ".*" which is supposed to pass through from
+	# _get_implicit_iuse().
+	regex = sorted(re.escape(x) for x in iuse_implicit)
+	regex = "^(%s)$" % "|".join(regex)
+	regex = regex.replace("\\.\\*", ".*")
+	return regex
+
 class config(object):
 	"""
 	This class encompasses the main portage configuration.  Data is pulled from
@@ -1484,7 +1497,7 @@
 			self.configlist.append(self.mygcfg)
 			self.configdict["conf"]=self.configlist[-1]
 
-			self.configlist.append({})
+			self.configlist.append(util.LazyItemsDict())
 			self.configdict["pkg"]=self.configlist[-1]
 
 			#auto-use:
@@ -2067,12 +2080,9 @@
 		iuse_implicit = self._get_implicit_iuse()
 		iuse_implicit.update(x.lstrip("+-") for x in iuse.split())
 
-		# Escape anything except ".*" which is supposed
-		# to pass through from _get_implicit_iuse()
-		regex = sorted(re.escape(x) for x in iuse_implicit)
-		regex = "^(%s)$" % "|".join(regex)
-		regex = regex.replace("\\.\\*", ".*")
-		self.configdict["pkg"]["PORTAGE_IUSE"] = regex
+		# PORTAGE_IUSE is not always needed so it's lazily evaluated.
+		self.configdict["pkg"].addLazySingleton(
+			"PORTAGE_IUSE", _lazy_iuse_regex, iuse_implicit)
 
 		ebuild_force_test = self.get("EBUILD_FORCE_TEST") == "1"
 		if ebuild_force_test and \

Modified: main/branches/2.1.6/pym/portage/util.py
===================================================================
--- main/branches/2.1.6/pym/portage/util.py	2009-03-11 06:05:17 UTC (rev 12932)
+++ main/branches/2.1.6/pym/portage/util.py	2009-03-11 06:05:37 UTC (rev 12933)
@@ -2,7 +2,6 @@
 # Distributed under the terms of the GNU General Public License v2
 # $Id$
 
-
 import os
 import errno
 import logging
@@ -1244,6 +1243,47 @@
 			del self.lazy_items[item_key]
 		dict.__delitem__(self, item_key)
 
+	def clear(self):
+		self.lazy_items.clear()
+		dict.clear(self)
+
+	def copy(self):
+		return self.__copy__()
+
+	def __copy__(self):
+		return self.__class__(self)
+
+	def __deepcopy__(self, memo=None):
+		"""
+		WARNING: If any of the lazy items contains a bound method then it's
+		typical for deepcopy() to raise an exception like this:
+
+			File "/usr/lib/python2.5/copy.py", line 189, in deepcopy
+				y = _reconstruct(x, rv, 1, memo)
+			File "/usr/lib/python2.5/copy.py", line 322, in _reconstruct
+				y = callable(*args)
+			File "/usr/lib/python2.5/copy_reg.py", line 92, in __newobj__
+				return cls.__new__(cls, *args)
+			TypeError: instancemethod expected at least 2 arguments, got 0
+
+		If deepcopy() needs to work, this problem can be avoided by
+		implementing lazy items with normal (non-bound) functions.
+		"""
+		if memo is None:
+			memo = {}
+		from copy import deepcopy
+		result = self.__class__()
+		memo[id(self)] = result
+		for k in self:
+			k_copy = deepcopy(k, memo)
+			if k in self.lazy_items:
+				dict.__setitem__(result, k_copy, None)
+				result.lazy_items[k_copy] = \
+					deepcopy(self.lazy_items[k], memo)
+			else:
+				dict.__setitem__(result, k_copy, deepcopy(self[k], memo))
+		return result
+
 	class _SingletonWrapper(object):
 
 		__slots__ = ('_parent', '_key', '_callable', '_pargs', '_kwargs')




^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-03-11  6:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-11  6:05 [gentoo-commits] portage r12933 - main/branches/2.1.6/pym/portage Zac Medico (zmedico)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox