Commits

Michał Górny  committed 505975f

Support getting atom parts.

  • Participants
  • Parent commits 006e3f6

Comments (0)

Files changed (5)

File gentoopm/basepm/atom.py

 
 from gentoopm.util import ABCObject
 
+class PMPackageKey(ABCObject):
+	"""
+	A base class for a package key (CP/qualified package name).
+	"""
+
+	@abstractproperty
+	def category(self):
+		"""
+		The package category.
+
+		@type: string/C{None}
+		"""
+		pass
+
+	@abstractproperty
+	def package(self):
+		"""
+		The package name.
+
+		@type: string
+		"""
+		pass
+
+	@abstractmethod
+	def __str__(self):
+		"""
+		Return the stringified package key.
+
+		@return: Stringified package key.
+		@rtype: string
+		"""
+		pass
+
+	def __eq__(self, other):
+		return str(self) == str(other)
+
+	def __ne__(self, other):
+		return not self.__eq__(other)
+
+	def __hash__(self):
+		return hash(str(self))
+
+class PMIncompletePackageKey(PMPackageKey):
+	"""
+	An incomplete package key (without a category).
+
+	This is just a helper class to simplify implementations. You should not
+	rely on this particular class being used, implementations are free to
+	implement incomplete keys using plain L{PMPackageKey}.
+	"""
+
+	@property
+	def category(self):
+		return None
+
+	def __str__(self):
+		return self.package
+
+class PMPackageVersion(ABCObject):
+	"""
+	A base class for a package version.
+	"""
+
+	@abstractproperty
+	def without_revision(self):
+		"""
+		The actual package version.
+
+		@type: string
+		"""
+		pass
+
+	@abstractproperty
+	def revision(self):
+		"""
+		The ebuild revision.
+
+		@type: int
+		"""
+		pass
+
+	@abstractmethod
+	def __str__(self):
+		"""
+		Return the stringified package version.
+
+		@return: Stringified package version.
+		@rtype: string
+		"""
+		pass
+
+	def __eq__(self, other):
+		return str(self) == str(other)
+
+	def __ne__(self, other):
+		return not self.__eq__(other)
+
+	def __hash__(self):
+		return hash(str(self))
+
 class PMAtom(ABCObject):
 	"""
 	A base class for PM-specific atom (dependency specification).
 		"""
 		pass
 
+	@abstractproperty
+	def key(self):
+		"""
+		The package key.
+
+		@type: L{PMPackageKey}
+		"""
+		pass
+
+	@abstractproperty
+	def version(self):
+		"""
+		The package version.
+
+		@type: L{PMPackageVersion}/C{None}
+		"""
+		pass

File gentoopm/paludispm/atom.py

 
 import paludis, re
 
-from gentoopm.basepm.atom import PMAtom
+from gentoopm.basepm.atom import PMAtom, PMPackageKey, PMPackageVersion, \
+		PMIncompletePackageKey
 from gentoopm.exceptions import InvalidAtomStringError
 
 _category_wildcard_re = re.compile(r'\w')
 
+class PaludisPackageKey(PMPackageKey):
+	def __init__(self, key):
+		self._k = key
+
+	@property
+	def category(self):
+		return str(self._k.category)
+
+	@property
+	def package(self):
+		return str(self._k.package)
+
+	def __str__(self):
+		return str(self._k)
+
+class PaludisIncompletePackageKey(PMIncompletePackageKey):
+	def __init__(self, key):
+		self._k = key
+
+	@property
+	def package(self):
+		return str(self._k)
+
+class PaludisPackageVersion(PMPackageVersion):
+	def __init__(self, ver):
+		self._v = ver
+
+	@property
+	def without_revision(self):
+		return str(self._v.remove_revision())
+
+	@property
+	def revision(self):
+		rs = self._v.revision_only()
+		assert(rs.startswith('r'))
+		return int(rs[1:])
+
+	def __str__(self):
+		return str(self._v)
+
 class PaludisAtom(PMAtom):
 	def _init_atom(self, s, env, wildcards = False):
 		opts = paludis.UserPackageDepSpecOptions() \
 	def unversioned(self):
 		assert(self.associated)
 		return PaludisAtom(str(self._atom.package), self._env)
+
+	@property
+	def key(self):
+		if self.complete:
+			return PaludisPackageKey(self._atom.package)
+		else:
+			return PaludisIncompletePackageKey(self._atom.package_name_part)
+
+	@property
+	def version(self):
+		try:
+			vr = next(iter(self._atom.version_requirements))
+		except StopIteration:
+			return None
+		return PaludisPackageVersion(vr.version_spec)

File gentoopm/pkgcorepm/atom.py

 # Released under the terms of the 2-clause BSD license.
 
 from pkgcore.ebuild.atom import atom
+from pkgcore.ebuild.restricts import PackageDep, VersionMatch
+from pkgcore.restrictions.boolean import AndRestriction
 from pkgcore.util.parserestrict import parse_match, ParseError
 
-from gentoopm.basepm.atom import PMAtom
+from gentoopm.basepm.atom import PMAtom, PMPackageKey, PMPackageVersion, \
+		PMIncompletePackageKey
 from gentoopm.exceptions import InvalidAtomStringError
 
+class PkgCorePackageKey(PMPackageKey):
+	def __init__(self, atom):
+		self._atom = atom
+
+	@property
+	def category(self):
+		return self._atom.category
+
+	@property
+	def package(self):
+		return self._atom.package
+
+	def __str__(self):
+		return self._atom.key
+
+class PkgCoreIncompletePackageKey(PMIncompletePackageKey):
+	def __init__(self, r):
+		if isinstance(r, AndRestriction):
+			for r in r.restrictions:
+				if isinstance(r, PackageDep):
+					break
+			else:
+				raise AssertionError('No PackageDep in restrictions.')
+
+		self._r = r
+
+	@property
+	def package(self):
+		return self._r.restriction.exact
+
+class PkgCorePackageVersion(PMPackageVersion):
+	def __init__(self, atom):
+		if atom.version is None:
+			raise AssertionError('Empty version in atom')
+		self._atom = atom
+
+	@property
+	def without_revision(self):
+		return self._atom.version
+
+	@property
+	def revision(self):
+		return self._atom.revision or 0
+
+	def __str__(self):
+		return self._atom.fullver
+
+class PkgCoreIncompletePackageVersion(PMPackageVersion):
+	def __init__(self, r):
+		if isinstance(r, AndRestriction):
+			for r in r.restrictions:
+				if isinstance(r, VersionMatch):
+					break
+			else:
+				raise AssertionError('No VersionMatch in restrictions.')
+
+		self._r = r
+
+	@property
+	def without_revision(self):
+		return self._r.ver
+
+	@property
+	def revision(self):
+		return self._r.rev or 0
+
+	def __str__(self):
+		# XXX: ugly?
+		return str(self._r).split()[-1]
+
 class PkgCoreAtom(PMAtom):
 	def __init__(self, s, pkg = None):
 		if isinstance(s, atom):
 	def unversioned(self):
 		assert(self.associated)
 		return PkgCoreAtom(self._pkg._pkg.unversioned_atom, self._pkg)
+
+	@property
+	def key(self):
+		if self.complete:
+			return PkgCorePackageKey(self._r)
+		else:
+			return PkgCoreIncompletePackageKey(self._r)
+
+	@property
+	def version(self):
+		try:
+			if self.complete:
+				return PkgCorePackageVersion(self._r)
+			else:
+				return PkgCoreIncompletePackageVersion(self._r)
+		except AssertionError:
+			return None

File gentoopm/portagepm/atom.py

 import portage.exception as pe
 from portage.dbapi.dep_expand import dep_expand
 from portage.dep import match_from_list
-from portage.versions import catsplit
+from portage.versions import catsplit, pkgsplit, cpv_getversion
 
-from gentoopm.basepm.atom import PMAtom
+from gentoopm.basepm.atom import PMAtom, PMPackageKey, PMPackageVersion, \
+		PMIncompletePackageKey
 from gentoopm.exceptions import InvalidAtomStringError
 
+class PortagePackageKey(PMPackageKey):
+	def __init__(self, cp):
+		self._cp = cp
+
+	@property
+	def category(self):
+		return catsplit(self._cp)[0]
+
+	@property
+	def package(self):
+		return catsplit(self._cp)[1]
+
+	def __str__(self):
+		return str(self._cp)
+
+class PortageIncompletePackageKey(PMIncompletePackageKey, PortagePackageKey):
+	pass
+
+class PortagePackageVersion(PMPackageVersion):
+	def __init__(self, cpv):
+		self._cpv = cpv
+
+	@property
+	def without_revision(self):
+		return pkgsplit(self._cpv)[1]
+
+	@property
+	def revision(self):
+		rs = pkgsplit(self._cpv)[2]
+		assert(rs.startswith('r'))
+		return int(rs[1:])
+
+	def __str__(self):
+		return cpv_getversion(self._cpv)
+
 class FakeSettings(object):
 	"""
 	Fake settings object, to satisfy cpv_expand().
 		assert(self.associated)
 		return PortageAtom(self._atom.cp)
 
+	@property
+	def key(self):
+		return PortagePackageKey(self._atom.cp)
+
+	@property
+	def version(self):
+		if self._atom.cp == self._atom.cpv:
+			return None
+		else:
+			return PortagePackageVersion(self._atom.cpv)
+
 class UncategorisedPackageWrapper(object):
 	def __init__(self, pkg):
 		self._pkg = pkg
 	@property
 	def complete(self):
 		return False
+
+	@property
+	def key(self):
+		return PortageIncompletePackageKey(self._atom.cp)

File gentoopm/tests/atom.py

 		self.assertEqual(str(a.slotted), '%s:0' % cas)
 		self.assertEqual(str(a.unversioned), cas)
 
+	def test_atom_parts(self):
+		a = self.pm.Atom('>=app-foo/bar-19-r1')
+		self.assertEqual(a.key.category, 'app-foo')
+		self.assertEqual(a.key.package, 'bar')
+		self.assertEqual(a.key, 'app-foo/bar')
+		self.assertEqual(a.version.without_revision, '19')
+		self.assertEqual(a.version.revision, 1)
+		self.assertEqual(a.version, '19-r1')
+
+	def test_atom_parts_incomplete(self):
+		a = self.pm.Atom('>=bar-19-r1')
+		self.assertTrue(a.key.category is None)
+		self.assertEqual(a.key.package, 'bar')
+		self.assertEqual(a.key, 'bar')
+		self.assertEqual(a.version.without_revision, '19')
+		self.assertEqual(a.version.revision, 1)
+		self.assertEqual(a.version, '19-r1')
+
+	def test_atom_parts_without_rev(self):
+		a = self.pm.Atom('>=app-foo/bar-19')
+		self.assertEqual(a.key.category, 'app-foo')
+		self.assertEqual(a.key.package, 'bar')
+		self.assertEqual(a.key, 'app-foo/bar')
+		self.assertEqual(a.version.without_revision, '19')
+		self.assertEqual(a.version.revision, 0)
+		self.assertEqual(a.version, '19')
+
+	def test_atom_parts_without_version(self):
+		a = self.pm.Atom('app-foo/bar')
+		self.assertEqual(a.key.category, 'app-foo')
+		self.assertEqual(a.key.package, 'bar')
+		self.assertEqual(a.key, 'app-foo/bar')
+		self.assertTrue(a.version is None)
+
 	def tearDown(self):
 		pass