コード例 #1
0
class Event(DictSQLObject):
    """
    Collects information about Events
    Referenced to by the Guest and ChatMsg Tables
    """
    name = so.UnicodeCol()
    description = so.UnicodeCol()
コード例 #2
0
class CswFile(sqlobject.SQLObject):
    """Represents a file in a catalog.

  There can be multiple files with the same basename and the same path,
  belonging to different packages.

  This class needs to also contain files from the operating system,
  coming from SUNW packages, for which we don't have the original srv4
  files.  (Even if we could, they are generally not accessible.)  They
  need to be specific to Solaris release and architecture, so we need
  a way to link CswFile with a specific catalog.

  Fake registered Srv4FileStats object would do, but we would have to
  ensure that they can't be associated with a catalog.  Also, we'd have
  to generate fake md5 sums for them.
  """
    basename = sqlobject.UnicodeCol(length=255, notNone=True)
    path = sqlobject.UnicodeCol(notNone=True, length=900)
    line = sqlobject.UnicodeCol(notNone=True, length=900)
    pkginst = sqlobject.ForeignKey('Pkginst', notNone=True)
    srv4_file = sqlobject.ForeignKey('Srv4FileStats')
    basename_idx = sqlobject.DatabaseIndex('basename')

    def __unicode__(self):
        return u"File: %s" % os.path.join(self.path, self.basename)
コード例 #3
0
class CheckpkgOverride(sqlobject.SQLObject):
  # Overrides don't need to contain catalog parameters.
  srv4_file = sqlobject.ForeignKey('Srv4FileStats', notNone=True)
  pkgname = sqlobject.UnicodeCol(default=None, length=250)
  tag_name = sqlobject.UnicodeCol(notNone=True, length=250)
  tag_info = sqlobject.UnicodeCol(default=None, length=250)

  def __unicode__(self):
    return (u"Override: %s: %s %s" %
            (self.pkgname,
             self.tag_name,
             self.tag_info or ""))

  def DoesApply(self, tag):
    """Figures out if this override applies to the given tag."""
    basket_a = {}
    basket_b = {}
    if self.pkgname:
      basket_a["pkgname"] = self.pkgname
      basket_b["pkgname"] = tag.pkgname
    if self.tag_info:
      basket_a["tag_info"] = self.tag_info
      basket_b["tag_info"] = tag.tag_info
    basket_a["tag_name"] = self.tag_name
    basket_b["tag_name"] = tag.tag_name
    return basket_a == basket_b
コード例 #4
0
class OsRelease(sqlobject.SQLObject):
  "Short name: SunOS5.9, long name: Solaris 9"
  short_name = sqlobject.UnicodeCol(length=40, unique=True, notNone=True)
  full_name = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)

  def __unicode__(self):
    return u"OS release: %s" % self.full_name
コード例 #5
0
ファイル: models.py プロジェクト: jubalskaggs/opencsw
class Maintainer(sqlobject.SQLObject):
    """The maintainer of the package, identified by the e-mail address."""
    email = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
    full_name = sqlobject.UnicodeCol(length=255, default=None)

    # TODO: Add more fields: status (active/retired/unregistered)
    # There are some emails that are just errors, it would be good to
    # distinguish emails that once were velid @opencsw.org addresses from pure
    # bugs, e.g. "*****@*****.**".

    def ObfuscatedEmail(self):
        if self.email:
            email = self.email.split("@")
        else:
            email = ["unknown"]
        if len(email) == 2:
            username, domain = email
        else:
            username, domain = email[0], "no domain"
        username = username[:-3] + "..."
        return "@".join((username, domain))

    def __unicode__(self):
        return u"%s <%s>" % (self.full_name or "Maintainer full name unknown",
                             self.ObfuscatedEmail())

    def GetRestRepr(self):
        return {
            'maintainer_email': self.email,
            'maintainer_full_name': self.full_name,
            'maintainer_id': self.id,
        }
コード例 #6
0
class CatalogGenData(sqlobject.SQLObject):
  """Fields required to generate the catalog.

  Having this smaller table lets us avoid fetching the main big data
  structure.
  """
  deps = sqlobject.BLOBCol(notNone=True, length=(2 ** 14 - 1))
  i_deps = sqlobject.BLOBCol(notNone=True, length=(2 ** 14 - 1))
  pkginfo_name = sqlobject.BLOBCol(notNone=True, length=(2 ** 14 - 1))
  pkgname = sqlobject.UnicodeCol(default=None, length=250)
  md5_sum = sqlobject.UnicodeCol(notNone=True, unique=True, length=32)
コード例 #7
0
class ElfdumpInfoBlob(sqlobject.SQLObject):
  """Holds JSON with elfdump information for a package.

  Indexed by the md5 sum of the binary.
  """
  class sqlmeta:
    cacheValues = False
  md5_sum = sqlobject.UnicodeCol(notNone=True, unique=True, length=32)
  json = sqlobject.BLOBCol(notNone=True, length=(2**24 - 1))
  content_md5_sum = sqlobject.UnicodeCol(notNone=True, unique=False, length=32)
  mime_type = sqlobject.UnicodeCol(notNone=True, length=250)
コード例 #8
0
ファイル: lyric.py プロジェクト: weiguobin/weixin-app
class Lyric(sqlobject.SQLObject):
    _connection = conn
    sid = sqlobject.IntCol(length=14, unique=True)
    song = sqlobject.UnicodeCol(length=255)
    lrc = sqlobject.UnicodeCol(length=255)
    artist_id = sqlobject.ForeignKey('Artist')
    aid = sqlobject.IntCol(length=14)

    #new add field
    local_path = sqlobject.UnicodeCol(length=255, default=None)
    sizes = sqlobject.IntCol(default=None)
    source = sqlobject.UnicodeCol(default=None)
コード例 #9
0
class Maintainer(sqlobject.SQLObject):
    """The maintainer of the package, identified by the e-mail address."""
    email = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
    full_name = sqlobject.UnicodeCol(length=255, default=None)

    def ObfuscatedEmail(self):
        username, domain = self.email.split("@")
        username = username[:-3] + "..."
        return "@".join((username, domain))

    def __unicode__(self):
        return u"%s <%s>" % (self.full_name or "Maintainer full name unknown",
                             self.ObfuscatedEmail())
コード例 #10
0
class Page(so.SQLObject):
    """
    Model a URI for a webpage on the internet.

    Do not worry about duplicate pairs of domain and path, since we want
    to allow those to occur on an import and to clean them up later.

    A page may have a null Folder (as unsorted), though a folder must always
    have a parent folder, even if the top folder is "root".
    """

    # The host website for the page.
    # TODO: Ensure this is always converted lowercase rather than raising
    # an error.
    domain = so.ForeignKey('Domain', notNull=True)

    # The location of the webpage relative to the domain.
    # TODO: Should this start with forwardslash? Check what happens when
    # splitting and joining.
    # TODO: Create custom validator?
    path = so.UnicodeCol(notNull=True)

    # Webpage title, usually taken from the metadata of the HTML head section.
    title = so.UnicodeCol(default=None)

    # The date and time when the record was created. Defaults to the
    # current time.
    created_at = so.DateTimeCol(notNull=True, default=so.DateTimeCol.now)

    # Optional preview image for the link, scraped from the metadata.
    image_url = so.UnicodeCol(default=None)

    description = so.UnicodeCol(default=None)

    # The folder this link is placed into. If null then the link must still
    # be sorted. Domain and path pairs must be unique in a folder.
    folder = so.ForeignKey('Folder')
    unique_idx = so.DatabaseIndex(domain, path, folder, unique=True)

    source = so.ForeignKey('Source', notNull=True)

    # Link to labels which this page is assigned to.
    labels = so.SQLRelatedJoin('Labels',
                               intermediateTable='page_label',
                               createRelatedTable=False)

    def get_url(self):
        return "".join((self.domain.value, self.path))
コード例 #11
0
class Srv4FileInCatalog(sqlobject.SQLObject):
  """Assignment of a particular srv4 file to a specific catalog.

  There could be one more layer, to which arch and osrel could be moved.
  But for now, it's going to be a not-normalized structure.
  """
  arch = sqlobject.ForeignKey('Architecture', notNone=True)
  osrel = sqlobject.ForeignKey('OsRelease', notNone=True)
  catrel = sqlobject.ForeignKey('CatalogRelease', notNone=True)
  srv4file = sqlobject.ForeignKey('Srv4FileStats', notNone=True)
  created_on = sqlobject.DateTimeCol(
      notNone=True,
      default=sqlobject.DateTimeCol.now)
  created_by = sqlobject.UnicodeCol(length=50, notNone=True)
  uniqueness_idx = sqlobject.DatabaseIndex(
          'arch', 'osrel', 'catrel', 'srv4file',
          unique=True)

  # http://turbogears.org/1.0/docs/SQLObject/Caching.html#what-does-cache-false-do
  class sqlmeta:
    cacheValues = False

  def __unicode__(self):
    return (u"%s is in catalog %s %s %s"
            % (self.srv4file,
               self.arch.name, self.osrel.full_name, self.catrel.name))
コード例 #12
0
class CatalogRelease(sqlobject.SQLObject):
    "Release names: potato, etc."
    name = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
    type = sqlobject.ForeignKey('CatalogReleaseType', notNone=True)

    def __unicode__(self):
        return u"Catalog release: %s" % self.name
コード例 #13
0
class DataSource(sqlobject.SQLObject):
    """Represents: a /var/sadm/install/contents file, or CSW catalog.

  - "filesystem"
  - "catalog"
  """
    name = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
コード例 #14
0
class Folder(so.SQLObject):
    """
    Model a folder, which can contain Page objects.

    A folder can be a tree structure with one parent and many children. A
    folder may contain zero or more Page objects.

    Folder name has a unique constrainst. If the same folder name needs
    to be used in different parts of the folder tree, it should probably
    by a label instead.
    """

    name = so.UnicodeCol(alternateID=True)

    # Self-join to an optional parent folder. If NULL, then it is at the top
    # level.
    # TODO: Unique constraint to prevent multiple top level folders?
    # Or use "root" instead and the res are unsorted?
    parent = so.ForeignKey('Folder', default=None)

    # Link to the child Folder records of a Folder.
    children = so.SQLMultipleJoin('Folder')

    # Link to Page records within a Folder.
    pages = so.SQLMultipleJoin('Page')
コード例 #15
0
class Srv4FileStatsBlob(sqlobject.SQLObject):
  """Holds serialized data structures in JSON.

  This table holds potentially large amounts of data (>1MB per row),
  and is separated to make Srv4FileStats lighter.  Sometimes, we don't
  need to retrieve the heavy pickled data if we want to read just a few
  text fields.
  """
  class sqlmeta:
    cacheValues = False
  md5_sum = sqlobject.UnicodeCol(notNone=True, unique=True, length=32)
  json = sqlobject.BLOBCol(notNone=True, length=(2**24))
  content_md5_sum = sqlobject.UnicodeCol(notNone=True, unique=False, length=32)
  mime_type = sqlobject.UnicodeCol(notNone=True, length=250)
  created_on = sqlobject.DateTimeCol(
      notNone=True,
      default=sqlobject.DateTimeCol.now)
コード例 #16
0
class CheckpkgErrorTag(CheckpkgErrorTagMixin, sqlobject.SQLObject):
  srv4_file = sqlobject.ForeignKey('Srv4FileStats', notNone=True)
  pkgname = sqlobject.UnicodeCol(default=None, length=250)
  tag_name = sqlobject.UnicodeCol(notNone=True, length=250)
  tag_info = sqlobject.UnicodeCol(default=None, length=250)
  msg = sqlobject.UnicodeCol(default=None, length=250)
  # To cache results from checkpkg
  overridden = sqlobject.BoolCol(default=False)
  # The same package might have different sets of errors for different
  # catalogs or Solaris releases.
  os_rel = sqlobject.ForeignKey('OsRelease', notNone=True)
  arch = sqlobject.ForeignKey('Architecture', notNone=True)
  catrel = sqlobject.ForeignKey('CatalogRelease', notNone=True)

  def __unicode__(self):
    return (u"CheckpkgErrorTag: %s %s %s"
            % (self.pkgname, self.tag_name, self.tag_info))
コード例 #17
0
class Format(so.SQLObject):
    """
    Model a datasource format.

    For example, a manual entry, user-created CSV, bookmark export,
    history export, or OneTab export.
    """

    name = so.UnicodeCol(alternateID=True, validator=validators.LowerCaseStr)
コード例 #18
0
class Guest(DictSQLObject):
    """
    Collects information about Guests
    Refrenced to by the ChatMsg Table
    """
    name = so.UnicodeCol()
    admin = so.BoolCol(default=False)
    parprop = so.IntCol(default=-1)
    token = so.StringCol(length=8)
    event = so.ForeignKey('Event')
コード例 #19
0
class CswFile(sqlobject.SQLObject):
  """Represents a file in a catalog.

  There can be multiple files with the same basename and the same path,
  belonging to different packages.

  This class needs to also contain files from the operating system,
  coming from SUNW packages, for which we don't have the original srv4
  files.  (Even if we could, they are generally not accessible.)  They
  need to be specific to Solaris release and architecture, so we need
  a way to link CswFile with a specific catalog.

  Fake registered Srv4FileStats object would do, but we would have to
  ensure that they can't be associated with a catalog.  Also, we'd have
  to generate fake md5 sums for them.
  """
  class sqlmeta:
    # MySQL uses case-insensitive collation by default, which doesn't make sense
    # for file names. If the utf8_bin (or other case sensitive) collation is not
    # used, it reports e.g. Zcat and zcat as a file collision, while it really
    # isn't one.
    createSQL = {
        'mysql' : [
        'ALTER TABLE csw_file CONVERT TO CHARACTER SET utf8 '
        'COLLATE utf8_bin']
    }
  basename = sqlobject.UnicodeCol(length=255, notNone=True)
  path = sqlobject.UnicodeCol(notNone=True, length=900)
  line = sqlobject.UnicodeCol(notNone=True, length=900)
  # Symlinks don't have permissions on their own
  perm_user = sqlobject.UnicodeCol(notNone=False, length=255)
  perm_group = sqlobject.UnicodeCol(notNone=False, length=255)
  perm_mode = sqlobject.UnicodeCol(notNone=False, length=5)
  target = sqlobject.UnicodeCol(notNone=False, length=900)
  mimetype = sqlobject.UnicodeCol(notNone=False, length=255)
  machine = sqlobject.UnicodeCol(notNone=False, length=255)
  pkginst = sqlobject.ForeignKey('Pkginst', notNone=True)
  srv4_file = sqlobject.ForeignKey('Srv4FileStats')
  basename_idx = sqlobject.DatabaseIndex('basename')
  path_idx = sqlobject.DatabaseIndex({'column': 'path', 'length': 255})

  def FullPath(self):
    return os.path.join(self.path, self.basename)

  def __unicode__(self):
    return u"%s %s %s %s %s" % (self.perm_user, self.perm_group, self.perm_mode,
                                self.FullPath(), self.mimetype)
コード例 #20
0
class JSONData(Record):
    """
    Table to hold any form of data in JSON format.

    Todo: extract date from data if available and overwrite value in
        inherited timestamp column. Consider conversion of datatypes.
    """
    # Optional label to describe the area or topic or page the data was
    # submitted on.
    area = so.UnicodeCol(default='', length=31)
    data = so.JSONCol(default=None)
コード例 #21
0
class User(Base):
    """
    Table of app users.
    """
    # A GUID used to uniquely identify this item across systems and on the
    # internet. Does alternateID also enforce unique?
    #guid = so.StringCol(notNull=True, default=UUID, unique=True, alternateID=True)
    # Username defaults to None/Null, but if set it must be unique.
    username = so.UnicodeCol(default=None, unique=True, length=31)
    # The time the user profile was created. Defaults to current time.
    created = so.DateTimeCol(default=so.DateTimeCol.now)
コード例 #22
0
class UwatchPkgVersion(sqlobject.SQLObject):
  
  id_pkg = sqlobject.IntCol(dbName="ID_PKG")
  gar_path = sqlobject.UnicodeCol(length=255, dbName="PKG_GAR_PATH")
  pkgname = sqlobject.UnicodeCol(length=64, dbName="PKG_NAME")
  catalogname = sqlobject.UnicodeCol(length=64, dbName="PKG_CATALOGNAME")
  gar_version = sqlobject.UnicodeCol(length=255, dbName="PKG_GAR_VERSION")
  upstream_version = sqlobject.UnicodeCol(length=255, dbName="PKG_UPSTREAM_VERSION")
  master_sites = sqlobject.UnicodeCol(length=255, dbName="PKG_UPSTREAM_MASTER_SITES")
  distfiles = sqlobject.UnicodeCol(length=255, dbName="PKG_GAR_DISTFILES")
  regex = sqlobject.UnicodeCol(length=255, dbName="PKG_UFILES_REGEXP")

  class sqlmeta(object):
    table = "UWATCH_PKG_VERSION"
    idName = "id_pkg"
コード例 #23
0
class Label(so.SQLObject):
    """
    Model a label.

    Unlike a folder, a label does not fit into a tree hierarchy and its name
    must be unique in order to look it up properly.
    """

    # Descriptive name of the label, which must be unique.
    name = so.UnicodeCol(alternateID=True)

    # Link to pages assigned to the label.
    pages = so.SQLRelatedJoin('Page',
                              intermediateTable='page_label',
                              createRelatedTable=False)
コード例 #24
0
class Domain(so.SQLObject):
    """
    Model a website domain.

    TODO: Add columns for metadata including title, keywords, image and icon.
    """

    class sqlmeta:
        defaultOrder = 'value'

    # Full hostname or domain of the website.
    value = so.UnicodeCol(alternateID=True, validator=URL)

    # The date and time when the record was created. Defaults to the
    # current time.
    datetime_created = so.DateTimeCol(notNull=True, default=so.DateTimeCol.now)

    # Link to Page objects which have paths relative to the Domain name.
    pages = so.SQLMultipleJoin('Page')

    # Get Page objects for the domain as a list. This is less efficient
    # for filtering, but slightly more convenient for development.
    pages_list = so.MultipleJoin('Page')
コード例 #25
0
class Host(sqlobject.SQLObject):
    "Hostname, as returned by socket.getfqdn()"
    fqdn = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
    arch = sqlobject.ForeignKey('Architecture', notNone=True)
コード例 #26
0
class CswConfig(sqlobject.SQLObject):
  option_key = sqlobject.UnicodeCol(length=255, unique=True)
  float_value = sqlobject.FloatCol(default=None)
  int_value = sqlobject.IntCol(default=None)
  str_value = sqlobject.UnicodeCol(default=None, length=250)
コード例 #27
0
class Architecture(sqlobject.SQLObject):
  "One of: 'sparc', 'x86'."
  name = sqlobject.UnicodeCol(length=40, unique=True, notNone=True)

  def __unicode__(self):
    return u"Architecture: %s" % self.name
コード例 #28
0
class CatalogReleaseType(sqlobject.SQLObject):
    "Unstable, testing, stable."
    name = sqlobject.UnicodeCol(length=255, unique=True, notNone=True)
コード例 #29
0
class Pkginst(sqlobject.SQLObject):
  pkgname = sqlobject.UnicodeCol(length=250, unique=True, notNone=True)
  catalogname = sqlobject.UnicodeCol(default=None, length=250)
  pkg_desc = sqlobject.UnicodeCol(default=None, length=250)
  srv4_files = sqlobject.MultipleJoin('Srv4FileStats')
コード例 #30
0
class Srv4FileStats(sqlobject.SQLObject):
  """Represents a srv4 file.

  It focuses on the stats, but it can as well represent just a srv4 file.
  """
  arch = sqlobject.ForeignKey('Architecture', notNone=True)
  basename = sqlobject.UnicodeCol(notNone=True, length=250)
  catalogname = sqlobject.UnicodeCol(notNone=True, length=250)
  filename_arch = sqlobject.ForeignKey('Architecture', notNone=True)
  maintainer = sqlobject.ForeignKey('Maintainer', notNone=False)
  md5_sum = sqlobject.UnicodeCol(notNone=True, unique=True, length=32)
  size = sqlobject.IntCol()
  mtime = sqlobject.DateTimeCol(notNone=False)
  os_rel = sqlobject.ForeignKey('OsRelease', notNone=True)
  osrel_str = sqlobject.UnicodeCol(notNone=True, length=9) # "SunOS5.10"
  pkginst = sqlobject.ForeignKey('Pkginst', notNone=True)
  pkginst_str = sqlobject.UnicodeCol(notNone=True, length=255)
  registered_level_one = sqlobject.BoolCol(notNone=True)
  registered_level_two = sqlobject.BoolCol(notNone=True)
  use_to_generate_catalogs = sqlobject.BoolCol(notNone=True)
  rev = sqlobject.UnicodeCol(notNone=False, length=250)
  stats_version = sqlobject.IntCol(notNone=True)
  version_string = sqlobject.UnicodeCol(notNone=True, length=250)
  bundle = sqlobject.UnicodeCol(length=250)
  in_catalogs = sqlobject.MultipleJoin(
          'Srv4FileInCatalog',
          joinColumn='srv4file_id')
  files = sqlobject.MultipleJoin('CswFile',
          joinColumn='id')
  catalog_idx = sqlobject.DatabaseIndex('catalogname')
  basename_idx = sqlobject.DatabaseIndex('basename')
  pkginst_idx = sqlobject.DatabaseIndex('pkginst')

  def __init__(self, *args, **kwargs):
    super(Srv4FileStats, self).__init__(*args, **kwargs)

  def __unicode__(self):
    return u'%s/%s, %s' % (self.pkginst.pkgname, self.catalogname, self.md5_sum)

  def __str__(self):
    return str(unicode(self))

  def DeleteAllDependentObjects(self):
    """Prepares the object to be deleted.

    Use this function with caution.
    """
    self.DeleteDependentObjectsPopulatedFromPackageItself()
    logger.debug('Removing all dependent objects from %s; it will cause the '
                 'package to be removed from all catalogs.', self)
    self.RemoveCatalogAssignments()
    self.RemoveAllCheckpkgResults()

  def DeleteDependentObjectsPopulatedFromPackageItself(self):
    """Removing all the objects that only depend on the package contents.

    It doesn't touch rows that are created for other reasons, e.g. assignments
    of packages to catalogs.
    """
    logger.debug('%s - Deleting objects that only depend on the package '
                 'contents', self)
    self.RemoveAllCswFiles()
    self.RemoveOverrides()
    self.RemoveDepends()
    self.RemoveIncompatibles()

  def RemoveAllCswFiles(self):
    # Removing existing files, using sqlbuilder to use sql-level
    # mechanisms without interacting with Python.
    # http://www.mail-archive.com/[email protected]/msg00520.html
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          CswFile.sqlmeta.table,
          CswFile.q.srv4_file==self)))

  def RemoveDepends(self):
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          Srv4DependsOn.sqlmeta.table,
          Srv4DependsOn.q.srv4_file==self)))

  def RemoveIncompatibles(self):
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          Srv4IncompatibleWith.sqlmeta.table,
          Srv4IncompatibleWith.q.srv4_file==self)))

  def RemoveCatalogAssignments(self):
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          Srv4FileInCatalog.sqlmeta.table,
          Srv4FileInCatalog.q.srv4file==self)))

  def GetOverridesResult(self):
    return CheckpkgOverride.select(CheckpkgOverride.q.srv4_file==self)

  def GetErrorTagsResult(self, os_rel, arch, catrel):
    assert arch.name != 'all', (
        "Asked for the 'all' architecture, this is not valid "
        "for GetErrorTagsResult().")
    return CheckpkgErrorTag.select(
        sqlobject.AND(
            CheckpkgErrorTag.q.srv4_file==self,
            CheckpkgErrorTag.q.os_rel==os_rel,
            CheckpkgErrorTag.q.arch==arch,
            CheckpkgErrorTag.q.catrel==catrel))

  def RemoveCheckpkgResults(self, os_rel, arch, catrel):
    logger.debug("%s: RemoveCheckpkgResults(%s, %s, %s)",
                  self, os_rel, arch, catrel)
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          CheckpkgErrorTag.sqlmeta.table,
          sqlobject.AND(
            CheckpkgErrorTag.q.srv4_file==self,
            CheckpkgErrorTag.q.os_rel==os_rel,
            CheckpkgErrorTag.q.arch==arch,
            CheckpkgErrorTag.q.catrel==catrel))))

  def RemoveAllCheckpkgResults(self):
    logger.debug("%s: RemoveAllCheckpkgResults()", self)
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          CheckpkgErrorTag.sqlmeta.table,
          CheckpkgErrorTag.q.srv4_file==self)))

  def RemoveOverrides(self):
    logger.debug("%s: RemoveOverrides()", self)
    sqlobject.sqlhub.processConnection.query(
        sqlobject.sqlhub.processConnection.sqlrepr(sqlbuilder.Delete(
          CheckpkgOverride.sqlmeta.table,
          CheckpkgOverride.q.srv4_file==self)))

  def GetUnicodeOrNone(self, s):
    """Tries to decode UTF-8.

    If the object does not decode as UTF-8, it's forced to do so, while
    ignoring any potential errors.

    Returns: a unicode object or a None type.
    """
    if s is None:
      return None
    if type(s) != unicode:
      try:
        s = unicode(s, 'utf-8')
      except UnicodeDecodeError, e:
        s = s.decode("utf-8", "ignore")
        s = s + u" (bad unicode detected)"
    return s