diff --git a/swh/lister/bitbucket/models.py b/swh/lister/bitbucket/models.py --- a/swh/lister/bitbucket/models.py +++ b/swh/lister/bitbucket/models.py @@ -1,13 +1,13 @@ -# Copyright (C) 2017 the Software Heritage developers +# Copyright (C) 2017-2018 the Software Heritage developers # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from sqlalchemy import Column, String -from swh.lister.core.models import ModelBase +from swh.lister.core.models import IndexingModelBase -class BitBucketModel(ModelBase): +class BitBucketModel(IndexingModelBase): """a BitBucket repository""" __tablename__ = 'bitbucket_repos' diff --git a/swh/lister/core/models.py b/swh/lister/core/models.py --- a/swh/lister/core/models.py +++ b/swh/lister/core/models.py @@ -24,10 +24,6 @@ uid = AbstractAttribute('Column(, primary_key=True)') - # The value used for sorting, segmenting, or api query paging, - # because uids aren't always sequential. - indexable = AbstractAttribute('Column(, index=True)') - name = Column(String, index=True) full_name = Column(String, index=True) html_url = Column(String) @@ -40,14 +36,12 @@ task_id = Column(Integer) origin_id = Column(Integer) - def __init__(self, uid=None, indexable=None, name=None, full_name=None, + def __init__(self, uid=None, name=None, full_name=None, html_url=None, origin_url=None, origin_type=None, description=None, task_id=None, origin_id=None): self.uid = uid self.last_seen = datetime.now() - if indexable is not None: - self.indexable = indexable if name is not None: self.name = name if full_name is not None: @@ -65,3 +59,24 @@ self.task_id = task_id if origin_id is not None: self.origin_id = origin_id + + +class IndexingModelBase(ModelBase, metaclass=ABCSQLMeta): + __abstract__ = True + __tablename__ = AbstractAttribute + + # The value used for sorting, segmenting, or api query paging, + # because uids aren't always sequential. + indexable = AbstractAttribute('Column(, index=True)') + + def __init__(self, uid=None, name=None, full_name=None, + html_url=None, origin_url=None, origin_type=None, + description=None, task_id=None, origin_id=None, + indexable=None): + super().__init__( + uid=uid, name=name, full_name=full_name, html_url=html_url, + origin_url=origin_url, origin_type=origin_type, + description=description, task_id=task_id, origin_id=origin_id) + + if indexable is not None: + self.indexable = indexable diff --git a/swh/lister/core/tests/test_model.py b/swh/lister/core/tests/test_model.py --- a/swh/lister/core/tests/test_model.py +++ b/swh/lister/core/tests/test_model.py @@ -7,7 +7,7 @@ from nose.tools import istest from sqlalchemy import Column, Integer -from swh.lister.core.models import ModelBase +from swh.lister.core.models import ModelBase, IndexingModelBase class BadSubclass1(ModelBase): @@ -30,6 +30,27 @@ indexable = Column(Integer, index=True) +class IndexingBadSubclass(IndexingModelBase): + __abstract__ = True + pass + + +class IndexingBadSubclass2(IndexingModelBase): + __abstract__ = True + __tablename__ = 'foo' + + +class IndexingBadSubclass3(IndexingBadSubclass2): + __abstract__ = True + pass + + +class IndexingGoodSubclass(IndexingModelBase): + uid = Column(Integer, primary_key=True) + indexable = Column(Integer, index=True) + __tablename__ = 'bar' + + class TestModel(unittest.TestCase): @istest def test_model_instancing(self): @@ -46,8 +67,28 @@ BadSubclass3() self.assertIsInstance(GoodSubclass(), GoodSubclass) - gsc = GoodSubclass(uid='uid', indexable='indexable') + gsc = GoodSubclass(uid='uid') self.assertEqual(gsc.__tablename__, 'foo') self.assertEqual(gsc.uid, 'uid') + + @istest + def test_indexing_model_instancing(self): + with self.assertRaises(TypeError): + IndexingModelBase() + + with self.assertRaises(TypeError): + IndexingBadSubclass() + + with self.assertRaises(TypeError): + IndexingBadSubclass2() + + with self.assertRaises(TypeError): + IndexingBadSubclass3() + + self.assertIsInstance(IndexingGoodSubclass(), IndexingGoodSubclass) + gsc = IndexingGoodSubclass(uid='uid', indexable='indexable') + + self.assertEqual(gsc.__tablename__, 'bar') + self.assertEqual(gsc.uid, 'uid') self.assertEqual(gsc.indexable, 'indexable') diff --git a/swh/lister/github/models.py b/swh/lister/github/models.py --- a/swh/lister/github/models.py +++ b/swh/lister/github/models.py @@ -1,13 +1,13 @@ -# Copyright (C) 2017 the Software Heritage developers +# Copyright (C) 2017-2018 the Software Heritage developers # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from sqlalchemy import Column, Boolean, Integer -from swh.lister.core.models import ModelBase +from swh.lister.core.models import IndexingModelBase -class GitHubModel(ModelBase): +class GitHubModel(IndexingModelBase): """a GitHub repository""" __tablename__ = 'github_repos' diff --git a/swh/lister/gitlab/lister.py b/swh/lister/gitlab/lister.py --- a/swh/lister/gitlab/lister.py +++ b/swh/lister/gitlab/lister.py @@ -70,7 +70,6 @@ return { 'instance': self.instance, 'uid': repo['id'], - 'indexable': repo['id'], 'name': repo['name'], 'full_name': repo['path_with_namespace'], 'html_url': repo['web_url'], diff --git a/swh/lister/gitlab/models.py b/swh/lister/gitlab/models.py --- a/swh/lister/gitlab/models.py +++ b/swh/lister/gitlab/models.py @@ -16,13 +16,12 @@ id = Column(Integer, primary_key=True) uid = Column(Integer, index=True) instance = Column(String, index=True) - indexable = Column(Integer, index=True) def __init__(self, uid=None, indexable=None, name=None, full_name=None, html_url=None, origin_url=None, origin_type=None, description=None, task_id=None, origin_id=None, instance=None): - super().__init__(uid=uid, indexable=indexable, name=name, + super().__init__(uid=uid, name=name, full_name=full_name, html_url=html_url, origin_url=origin_url, origin_type=origin_type, description=description, task_id=task_id,