# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

import sys
from itertools import chain
import warnings

import portage
from portage import _encodings, _unicode_decode, _unicode_encode
from portage.cache.mappings import slot_dict_class
from portage.const import EBUILD_PHASES
from portage.dep import Atom, check_required_use, use_reduce, \
	paren_enclose, _slot_separator, _repo_separator
from portage.versions import _pkg_str, _unknown_repo
from portage.eapi import _get_eapi_attrs, eapi_has_use_aliases
from portage.exception import InvalidDependString
from portage.localization import _
from _emerge.Task import Task

if sys.hexversion >= 0x3000000:
	basestring = str
	long = int
	_unicode = str
else:
	_unicode = unicode

class Package(Task):

	__hash__ = Task.__hash__
	__slots__ = ("built", "cpv", "depth",
		"installed", "onlydeps", "operation",
		"root_config", "type_name",
		"category", "counter", "cp", "cpv_split",
		"inherited", "iuse", "mtime",
		"pf", "root", "slot", "sub_slot", "slot_atom", "version") + \
		("_invalid", "_masks", "_metadata", "_raw_metadata", "_use",
		"_validated_atoms", "_visible")

	metadata_keys = [
		"BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "EAPI",
		"HDEPEND", "INHERITED", "IUSE", "KEYWORDS",
		"LICENSE", "PDEPEND", "PROVIDE", "RDEPEND",
		"repository", "PROPERTIES", "RESTRICT", "SLOT", "USE",
		"_mtime_", "DEFINED_PHASES", "REQUIRED_USE"]

	_dep_keys = ('DEPEND', 'HDEPEND', 'PDEPEND', 'RDEPEND')
	_buildtime_keys = ('DEPEND', 'HDEPEND')
	_runtime_keys = ('PDEPEND', 'RDEPEND')
	_use_conditional_misc_keys = ('LICENSE', 'PROPERTIES', 'RESTRICT')
	UNKNOWN_REPO = _unknown_repo

	def __init__(self, **kwargs):
		metadata = _PackageMetadataWrapperBase(kwargs.pop('metadata'))
		Task.__init__(self, **kwargs)
		# the SlotObject constructor assigns self.root_config from keyword args
		# and is an instance of a '_emerge.RootConfig.RootConfig class
		self.root = self.root_config.root
		self._raw_metadata = metadata
		self._metadata = _PackageMetadataWrapper(self, metadata)
		if not self.built:
			self._metadata['CHOST'] = self.root_config.settings.get('CHOST', '')
		eapi_attrs = _get_eapi_attrs(self.eapi)
		self.cpv = _pkg_str(self.cpv, metadata=self._metadata,
			settings=self.root_config.settings)
		if hasattr(self.cpv, 'slot_invalid'):
			self._invalid_metadata('SLOT.invalid',
				"SLOT: invalid value: '%s'" % self._metadata["SLOT"])
		self.cpv_split = self.cpv.cpv_split
		self.category, self.pf = portage.catsplit(self.cpv)
		self.cp = self.cpv.cp
		self.version = self.cpv.version
		self.slot = self.cpv.slot
		self.sub_slot = self.cpv.sub_slot
		self.slot_atom = Atom("%s%s%s" % (self.cp, _slot_separator, self.slot))
		# sync metadata with validated repo (may be UNKNOWN_REPO)
		self._metadata['repository'] = self.cpv.repo

		if eapi_attrs.iuse_effective:
			implicit_match = self.root_config.settings._iuse_effective_match
		else:
			implicit_match = self.root_config.settings._iuse_implicit_match
		usealiases = self.root_config.settings._use_manager.getUseAliases(self)
		self.iuse = self._iuse(self, self._metadata["IUSE"].split(), implicit_match,
			usealiases, self.eapi)

		if (self.iuse.enabled or self.iuse.disabled) and \
			not eapi_attrs.iuse_defaults:
			if not self.installed:
				self._invalid_metadata('EAPI.incompatible',
					"IUSE contains defaults, but EAPI doesn't allow them")
		if self.inherited is None:
			self.inherited = frozenset()

		if self.operation is None:
			if self.onlydeps or self.installed:
				self.operation = "nomerge"
			else:
				self.operation = "merge"

		self._hash_key = Package._gen_hash_key(cpv=self.cpv,
			installed=self.installed, onlydeps=self.onlydeps,
			operation=self.operation, repo_name=self.cpv.repo,
			root_config=self.root_config,
			type_name=self.type_name)
		self._hash_value = hash(self._hash_key)

	@property
	def eapi(self):
		return self._metadata["EAPI"]

	@property
	def build_time(self):
		if not self.built:
			raise AttributeError('build_time')
		try:
			return long(self._metadata['BUILD_TIME'])
		except (KeyError, ValueError):
			return 0

	@property
	def defined_phases(self):
		return self._metadata.defined_phases

	@property
	def properties(self):
		return self._metadata.properties

	@property
	def restrict(self):
		return self._metadata.restrict

	@property
	def metadata(self):
		warnings.warn("_emerge.Package.Package.metadata is deprecated",
			DeprecationWarning, stacklevel=3)
		return self._metadata

	# These are calculated on-demand, so that they are calculated
	# after FakeVartree applies its metadata tweaks.
	@property
	def invalid(self):
		if self._invalid is None:
			self._validate_deps()
			if self._invalid is None:
				self._invalid = False
		return self._invalid

	@property
	def masks(self):
		if self._masks is None:
			self._masks = self._eval_masks()
		return self._masks

	@property
	def visible(self):
		if self._visible is None:
			self._visible = self._eval_visiblity(self.masks)
		return self._visible

	@property
	def validated_atoms(self):
		"""
		Returns *all* validated atoms from the deps, regardless
		of USE conditionals, with USE conditionals inside
		atoms left unevaluated.
		"""
		if self._validated_atoms is None:
			self._validate_deps()
		return self._validated_atoms

	@property
	def stable(self):
		return self.cpv.stable

	@classmethod
	def _gen_hash_key(cls, cpv=None, installed=None, onlydeps=None,
		operation=None, repo_name=None, root_config=None,
		type_name=None, **kwargs):

		if operation is None:
			if installed or onlydeps:
				operation = "nomerge"
			else:
				operation = "merge"

		root = None
		if root_config is not None:
			root = root_config.root
		else:
			raise TypeError("root_config argument is required")

		# For installed (and binary) packages we don't care for the repo
		# when it comes to hashing, because there can only be one cpv.
		# So overwrite the repo_key with type_name.
		if type_name is None:
			raise TypeError("type_name argument is required")
		elif type_name == "ebuild":
			if repo_name is None:
				raise AssertionError(
					"Package._gen_hash_key() " + \
					"called without 'repo_name' argument")
			repo_key = repo_name
		else:
			# For installed (and binary) packages we don't care for the repo
			# when it comes to hashing, because there can only be one cpv.
			# So overwrite the repo_key with type_name.
			repo_key = type_name

		return (type_name, root, _unicode(cpv), operation, repo_key)

	def _validate_deps(self):
		"""
		Validate deps. This does not trigger USE calculation since that
		is expensive for ebuilds and therefore we want to avoid doing
		it unnecessarily (like for masked packages).
		"""
		eapi = self.eapi
		dep_eapi = eapi
		dep_valid_flag = self.iuse.is_valid_flag
		if self.installed:
			# Ignore EAPI.incompatible and conditionals missing
			# from IUSE for installed packages since these issues
			# aren't relevant now (re-evaluate when new EAPIs are
			# deployed).
			dep_eapi = None
			dep_valid_flag = None

		validated_atoms = []
		for k in self._dep_keys:
			v = self._metadata.get(k)
			if not v:
				continue
			try:
				atoms = use_reduce(v, eapi=dep_eapi,
					matchall=True, is_valid_flag=dep_valid_flag,
					token_class=Atom, flat=True)
			except InvalidDependString as e:
				self._metadata_exception(k, e)
			else:
				validated_atoms.extend(atoms)
				if not self.built:
					for atom in atoms:
						if not isinstance(atom, Atom):
							continue
						if atom.slot_operator_built:
							e = InvalidDependString(
								_("Improper context for slot-operator "
								"\"built\" atom syntax: %s") %
								(atom.unevaluated_atom,))
							self._metadata_exception(k, e)

		self._validated_atoms = tuple(set(atom for atom in
			validated_atoms if isinstance(atom, Atom)))

		k = 'PROVIDE'
		v = self._metadata.get(k)
		if v:
			try:
				use_reduce(v, eapi=dep_eapi, matchall=True,
					is_valid_flag=dep_valid_flag, token_class=Atom)
			except InvalidDependString as e:
				self._invalid_metadata("PROVIDE.syntax",
					_unicode_decode("%s: %s") % (k, e))

		for k in self._use_conditional_misc_keys:
			v = self._metadata.get(k)
			if not v:
				continue
			try:
				use_reduce(v, eapi=dep_eapi, matchall=True,
					is_valid_flag=dep_valid_flag)
			except InvalidDependString as e:
				self._metadata_exception(k, e)

		k = 'REQUIRED_USE'
		v = self._metadata.get(k)
		if v and not self.built:
			if not _get_eapi_attrs(eapi).required_use:
				self._invalid_metadata('EAPI.incompatible',
					"REQUIRED_USE set, but EAPI='%s' doesn't allow it" % eapi)
			else:
				try:
					check_required_use(v, (),
						self.iuse.is_valid_flag, eapi=eapi)
				except InvalidDependString as e:
					# Force unicode format string for python-2.x safety,
					# ensuring that PortageException.__unicode__() is used
					# when necessary.
					self._invalid_metadata(k + ".syntax",
						_unicode_decode("%s: %s") % (k, e))

		k = 'SRC_URI'
		v = self._metadata.get(k)
		if v:
			try:
				use_reduce(v, is_src_uri=True, eapi=eapi, matchall=True,
					is_valid_flag=self.iuse.is_valid_flag)
			except InvalidDependString as e:
				if not self.installed:
					self._metadata_exception(k, e)

	def copy(self):
		return Package(built=self.built, cpv=self.cpv, depth=self.depth,
			installed=self.installed, metadata=self._raw_metadata,
			onlydeps=self.onlydeps, operation=self.operation,
			root_config=self.root_config, type_name=self.type_name)

	def _eval_masks(self):
		masks = {}
		settings = self.root_config.settings

		if self.invalid is not False:
			masks['invalid'] = self.invalid

		if not settings._accept_chost(self.cpv, self._metadata):
			masks['CHOST'] = self._metadata['CHOST']

		eapi = self.eapi
		if not portage.eapi_is_supported(eapi):
			masks['EAPI.unsupported'] = eapi
		if portage._eapi_is_deprecated(eapi):
			masks['EAPI.deprecated'] = eapi

		missing_keywords = settings._getMissingKeywords(
			self.cpv, self._metadata)
		if missing_keywords:
			masks['KEYWORDS'] = missing_keywords

		try:
			missing_properties = settings._getMissingProperties(
				self.cpv, self._metadata)
			if missing_properties:
				masks['PROPERTIES'] = missing_properties
		except InvalidDependString:
			# already recorded as 'invalid'
			pass

		mask_atom = settings._getMaskAtom(self.cpv, self._metadata)
		if mask_atom is not None:
			masks['package.mask'] = mask_atom

		try:
			missing_licenses = settings._getMissingLicenses(
				self.cpv, self._metadata)
			if missing_licenses:
				masks['LICENSE'] = missing_licenses
		except InvalidDependString:
			# already recorded as 'invalid'
			pass

		if not masks:
			masks = False

		return masks

	def _eval_visiblity(self, masks):

		if masks is not False:

			if 'EAPI.unsupported' in masks:
				return False

			if 'invalid' in masks:
				return False

			if not self.installed and ( \
				'CHOST' in masks or \
				'EAPI.deprecated' in masks or \
				'KEYWORDS' in masks or \
				'PROPERTIES' in masks):
				return False

			if 'package.mask' in masks or \
				'LICENSE' in masks:
				return False

		return True

	def get_keyword_mask(self):
		"""returns None, 'missing', or 'unstable'."""

		missing = self.root_config.settings._getRawMissingKeywords(
				self.cpv, self._metadata)

		if not missing:
			return None

		if '**' in missing:
			return 'missing'

		global_accept_keywords = frozenset(
			self.root_config.settings.get("ACCEPT_KEYWORDS", "").split())

		for keyword in missing:
			if keyword.lstrip("~") in global_accept_keywords:
				return 'unstable'

		return 'missing'

	def isHardMasked(self):
		"""returns a bool if the cpv is in the list of
		expanded pmaskdict[cp] available ebuilds"""
		pmask = self.root_config.settings._getRawMaskAtom(
			self.cpv, self._metadata)
		return pmask is not None

	def _metadata_exception(self, k, e):

		if k.endswith('DEPEND'):
			qacat = 'dependency.syntax'
		else:
			qacat = k + ".syntax"

		# For unicode safety with python-2.x we need to avoid
		# using the string format operator with a non-unicode
		# format string, since that will result in the
		# PortageException.__str__() method being invoked,
		# followed by unsafe decoding that may result in a
		# UnicodeDecodeError. Therefore, use _unicode_decode()
		# to ensure that format strings are unicode, so that
		# PortageException.__unicode__() is used when necessary
		# in python-2.x.
		if not self.installed:
			categorized_error = False
			if e.errors:
				for error in e.errors:
					if getattr(error, 'category', None) is None:
						continue
					categorized_error = True
					self._invalid_metadata(error.category,
						_unicode_decode("%s: %s") % (k, error))

			if not categorized_error:
				self._invalid_metadata(qacat,
					_unicode_decode("%s: %s") % (k, e))
		else:
			# For installed packages, show the path of the file
			# containing the invalid metadata, since the user may
			# want to fix the deps by hand.
			vardb = self.root_config.trees['vartree'].dbapi
			path = vardb.getpath(self.cpv, filename=k)
			self._invalid_metadata(qacat,
				_unicode_decode("%s: %s in '%s'") % (k, e, path))

	def _invalid_metadata(self, msg_type, msg):
		if self._invalid is None:
			self._invalid = {}
		msgs = self._invalid.get(msg_type)
		if msgs is None:
			msgs = []
			self._invalid[msg_type] = msgs
		msgs.append(msg)

	def __str__(self):
		if self.operation == "merge":
			if self.type_name == "binary":
				cpv_color = "PKG_BINARY_MERGE"
			else:
				cpv_color = "PKG_MERGE"
		elif self.operation == "uninstall":
			cpv_color = "PKG_UNINSTALL"
		else:
			cpv_color = "PKG_NOMERGE"

		s = "(%s, %s" \
			% (portage.output.colorize(cpv_color, self.cpv + _repo_separator + self.repo) , self.type_name)

		if self.type_name == "installed":
			if self.root_config.settings['ROOT'] != "/":
				s += " in '%s'" % self.root_config.settings['ROOT']
			if self.operation == "uninstall":
				s += " scheduled for uninstall"
		else:
			if self.operation == "merge":
				s += " scheduled for merge"
				if self.root_config.settings['ROOT'] != "/":
					s += " to '%s'" % self.root_config.settings['ROOT']
		s += ")"
		return s

	if sys.hexversion < 0x3000000:

		__unicode__ = __str__

		def __str__(self):
			return _unicode_encode(self.__unicode__(),
				encoding=_encodings['content'])

	class _use_class(object):

		__slots__ = ("enabled", "_expand", "_expand_hidden",
			"_force", "_pkg", "_mask")

		# Share identical frozenset instances when available.
		_frozensets = {}

		def __init__(self, pkg, use_str):
			self._pkg = pkg
			self._expand = None
			self._expand_hidden = None
			self._force = None
			self._mask = None
			enabled_flags = use_str.split()
			if eapi_has_use_aliases(pkg.eapi):
				for enabled_flag in enabled_flags:
					enabled_flags.extend(pkg.iuse.alias_mapping.get(enabled_flag, []))
			self.enabled = frozenset(enabled_flags)
			if pkg.built:
				# Use IUSE to validate USE settings for built packages,
				# in case the package manager that built this package
				# failed to do that for some reason (or in case of
				# data corruption).
				missing_iuse = pkg.iuse.get_missing_iuse(self.enabled)
				if missing_iuse:
					self.enabled = self.enabled.difference(missing_iuse)

		def _init_force_mask(self):
			pkgsettings = self._pkg._get_pkgsettings()
			frozensets = self._frozensets
			s = frozenset(
				pkgsettings.get("USE_EXPAND", "").lower().split())
			self._expand = frozensets.setdefault(s, s)
			s = frozenset(
				pkgsettings.get("USE_EXPAND_HIDDEN", "").lower().split())
			self._expand_hidden = frozensets.setdefault(s, s)
			s = pkgsettings.useforce
			self._force = frozensets.setdefault(s, s)
			s = pkgsettings.usemask
			self._mask = frozensets.setdefault(s, s)

		@property
		def expand(self):
			if self._expand is None:
				self._init_force_mask()
			return self._expand

		@property
		def expand_hidden(self):
			if self._expand_hidden is None:
				self._init_force_mask()
			return self._expand_hidden

		@property
		def force(self):
			if self._force is None:
				self._init_force_mask()
			return self._force

		@property
		def mask(self):
			if self._mask is None:
				self._init_force_mask()
			return self._mask

	@property
	def repo(self):
		return self._metadata['repository']

	@property
	def repo_priority(self):
		repo_info = self.root_config.settings.repositories.prepos.get(self.repo)
		if repo_info is None:
			return None
		return repo_info.priority

	@property
	def use(self):
		if self._use is None:
			self._metadata._init_use()
		return self._use

	def _get_pkgsettings(self):
		pkgsettings = self.root_config.trees[
			'porttree'].dbapi.doebuild_settings
		pkgsettings.setcpv(self)
		return pkgsettings

	class _iuse(object):

		__slots__ = ("__weakref__", "_iuse_implicit_match", "_pkg", "alias_mapping",
			"all", "all_aliases", "enabled", "disabled", "tokens")

		def __init__(self, pkg, tokens, iuse_implicit_match, aliases, eapi):
			self._pkg = pkg
			self.tokens = tuple(tokens)
			self._iuse_implicit_match = iuse_implicit_match
			enabled = []
			disabled = []
			other = []
			enabled_aliases = []
			disabled_aliases = []
			other_aliases = []
			aliases_supported = eapi_has_use_aliases(eapi)
			self.alias_mapping = {}
			for x in tokens:
				prefix = x[:1]
				if prefix == "+":
					enabled.append(x[1:])
					if aliases_supported:
						self.alias_mapping[x[1:]] = aliases.get(x[1:], [])
						enabled_aliases.extend(self.alias_mapping[x[1:]])
				elif prefix == "-":
					disabled.append(x[1:])
					if aliases_supported:
						self.alias_mapping[x[1:]] = aliases.get(x[1:], [])
						disabled_aliases.extend(self.alias_mapping[x[1:]])
				else:
					other.append(x)
					if aliases_supported:
						self.alias_mapping[x] = aliases.get(x, [])
						other_aliases.extend(self.alias_mapping[x])
			self.enabled = frozenset(chain(enabled, enabled_aliases))
			self.disabled = frozenset(chain(disabled, disabled_aliases))
			self.all = frozenset(chain(enabled, disabled, other))
			self.all_aliases = frozenset(chain(enabled_aliases, disabled_aliases, other_aliases))

		def is_valid_flag(self, flags):
			"""
			@return: True if all flags are valid USE values which may
				be specified in USE dependencies, False otherwise.
			"""
			if isinstance(flags, basestring):
				flags = [flags]

			for flag in flags:
				if not flag in self.all and not flag in self.all_aliases and \
					not self._iuse_implicit_match(flag):
					return False
			return True

		def get_missing_iuse(self, flags):
			"""
			@return: A list of flags missing from IUSE.
			"""
			if isinstance(flags, basestring):
				flags = [flags]
			missing_iuse = []
			for flag in flags:
				if not flag in self.all and not flag in self.all_aliases and \
					not self._iuse_implicit_match(flag):
					missing_iuse.append(flag)
			return missing_iuse

		def get_real_flag(self, flag):
			"""
			Returns the flag's name within the scope of this package
			(accounting for aliases), or None if the flag is unknown.
			"""
			if flag in self.all:
				return flag
			elif flag in self.all_aliases:
				for k, v in self.alias_mapping.items():
					if flag in v:
						return k

			if self._iuse_implicit_match(flag):
				return flag

			return None

	def __len__(self):
		return 4

	def __iter__(self):
		"""
		This is used to generate mtimedb resume mergelist entries, so we
		limit it to 4 items for backward compatibility.
		"""
		return iter(self._hash_key[:4])

	def __lt__(self, other):
		if other.cp != self.cp:
			return False
		if portage.vercmp(self.version, other.version) < 0:
			return True
		return False

	def __le__(self, other):
		if other.cp != self.cp:
			return False
		if portage.vercmp(self.version, other.version) <= 0:
			return True
		return False

	def __gt__(self, other):
		if other.cp != self.cp:
			return False
		if portage.vercmp(self.version, other.version) > 0:
			return True
		return False

	def __ge__(self, other):
		if other.cp != self.cp:
			return False
		if portage.vercmp(self.version, other.version) >= 0:
			return True
		return False

_all_metadata_keys = set(x for x in portage.auxdbkeys \
	if not x.startswith("UNUSED_"))
_all_metadata_keys.update(Package.metadata_keys)
_all_metadata_keys = frozenset(_all_metadata_keys)

_PackageMetadataWrapperBase = slot_dict_class(_all_metadata_keys)

class _PackageMetadataWrapper(_PackageMetadataWrapperBase):
	"""
	Detect metadata updates and synchronize Package attributes.
	"""

	__slots__ = ("_pkg",)
	_wrapped_keys = frozenset(
		["COUNTER", "INHERITED", "USE", "_mtime_"])
	_use_conditional_keys = frozenset(
		['LICENSE', 'PROPERTIES', 'PROVIDE', 'RESTRICT',])

	def __init__(self, pkg, metadata):
		_PackageMetadataWrapperBase.__init__(self)
		self._pkg = pkg
		if not pkg.built:
			# USE is lazy, but we want it to show up in self.keys().
			_PackageMetadataWrapperBase.__setitem__(self, 'USE', '')

		self.update(metadata)

	def _init_use(self):
		if self._pkg.built:
			use_str = self['USE']
			self._pkg._use = self._pkg._use_class(
				self._pkg, use_str)
		else:
			try:
				use_str = _PackageMetadataWrapperBase.__getitem__(self, 'USE')
			except KeyError:
				use_str = None
			calculated_use = False
			if not use_str:
				use_str = self._pkg._get_pkgsettings()["PORTAGE_USE"]
				calculated_use = True
			_PackageMetadataWrapperBase.__setitem__(self, 'USE', use_str)
			self._pkg._use = self._pkg._use_class(
				self._pkg, use_str)
			# Initialize these now, since USE access has just triggered
			# setcpv, and we want to cache the result of the force/mask
			# calculations that were done.
			if calculated_use:
				self._pkg._use._init_force_mask()

		return use_str

	def __getitem__(self, k):
		v = _PackageMetadataWrapperBase.__getitem__(self, k)
		if k in self._use_conditional_keys:
			if self._pkg.root_config.settings.local_config and '?' in v:
				try:
					v = paren_enclose(use_reduce(v, uselist=self._pkg.use.enabled, \
						is_valid_flag=self._pkg.iuse.is_valid_flag))
				except InvalidDependString:
					# This error should already have been registered via
					# self._pkg._invalid_metadata().
					pass
				else:
					self[k] = v

		elif k == 'USE' and not self._pkg.built:
			if not v:
				# This is lazy because it's expensive.
				v = self._init_use()

		return v

	def __setitem__(self, k, v):
		_PackageMetadataWrapperBase.__setitem__(self, k, v)
		if k in self._wrapped_keys:
			getattr(self, "_set_" + k.lower())(k, v)

	def _set_inherited(self, k, v):
		if isinstance(v, basestring):
			v = frozenset(v.split())
		self._pkg.inherited = v

	def _set_counter(self, k, v):
		if isinstance(v, basestring):
			try:
				v = long(v.strip())
			except ValueError:
				v = 0
		self._pkg.counter = v

	def _set_use(self, k, v):
		# Force regeneration of _use attribute
		self._pkg._use = None
		# Use raw metadata to restore USE conditional values
		# to unevaluated state
		raw_metadata = self._pkg._raw_metadata
		for x in self._use_conditional_keys:
			try:
				self[x] = raw_metadata[x]
			except KeyError:
				pass

	def _set__mtime_(self, k, v):
		if isinstance(v, basestring):
			try:
				v = long(v.strip())
			except ValueError:
				v = 0
		self._pkg.mtime = v

	@property
	def properties(self):
		return self['PROPERTIES'].split()

	@property
	def restrict(self):
		return self['RESTRICT'].split()

	@property
	def defined_phases(self):
		"""
		Returns tokens from DEFINED_PHASES metadata if it is defined,
		otherwise returns a tuple containing all possible phases. This
		makes it easy to do containment checks to see if it's safe to
		skip execution of a given phase.
		"""
		s = self['DEFINED_PHASES']
		if s:
			return s.split()
		return EBUILD_PHASES
