Repository: absent1706/sqlalchemy-mixins

Issue:
sqlalchemy.exc.ArgumentError: Class 'MyClass' already has a primary mapper defined. 
I have a project with SQLAlchemy 1.4 and sqlalchemy-mixins 1.5.3.
I have upgraded SQLAlchemy to 2.0 and made the code work and passes the tests. Then, I tried to upgrade sqlalchemy-mixins to 2.0.3 but I get the error of the title.

```
File "/lib/MyClass.py", line 12, in <module>
    class MyClass(MyBaseClass):
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_api.py", line 195, in __init__
    _as_declarative(reg, cls, dict_)
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_base.py", line 247, in _as_declarative
    return _MapperConfig.setup_mapping(registry, cls, dict_, None, {})
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_base.py", line 328, in setup_mapping
    return _ClassScanMapperConfig(
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_base.py", line 520, in __init__
    super().__init__(registry, cls_, mapper_kw)
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_base.py", line 344, in __init__
    instrumentation.register_class(
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/instrumentation.py", line 684, in register_class
    manager._update_state(
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/instrumentation.py", line 209, in _update_state
    registry._add_manager(self)
  File "/venv38/lib/python3.8/site-packages/sqlalchemy/orm/decl_api.py", line 1380, in _add_manager
    raise exc.ArgumentError(
sqlalchemy.exc.ArgumentError: Class '<class 'lib.MyClass'>' already has a primary mapper defined. 
```

MyBaseClass is defined as:

```python
class MyBaseClass(AnotherBaseClass):
    __abstract__ = True

    #SOME CODE

class AnotherBaseClass(Base, AllFeaturesMixin):
    __abstract__ = True

    #SOME OTHER CODE
```

Any idea of what may be happening or how to troubleshoot this?


Comments:

Patch:
diff --git a/sqlalchemy_mixins/inspection.py b/sqlalchemy_mixins/inspection.py
index 41d1ea6..bd2584e 100644
--- a/sqlalchemy_mixins/inspection.py
+++ b/sqlalchemy_mixins/inspection.py
@@ -5,12 +5,7 @@ from sqlalchemy.orm import RelationshipProperty, DeclarativeBase
 from .utils import classproperty
 
 
-class Base(DeclarativeBase):
-    __abstract__ = True
-
-
-class InspectionMixin(Base):
-    __abstract__ = True
+class InspectionMixin:
 
     @classproperty
     def columns(cls):
diff --git a/sqlalchemy_mixins/inspection.pyi b/sqlalchemy_mixins/inspection.pyi
index ebc9da1..09582d8 100644
--- a/sqlalchemy_mixins/inspection.pyi
+++ b/sqlalchemy_mixins/inspection.pyi
@@ -1,18 +1,16 @@
 from typing import List, Protocol, Dict
 
 from sqlalchemy.ext.hybrid import hybrid_method
-from sqlalchemy.orm import Mapper, DeclarativeBase
+from sqlalchemy.orm import Mapper
 from sqlalchemy.orm.interfaces import MapperProperty
 
 from sqlalchemy_mixins.utils import classproperty
 
-class Base(DeclarativeBase):
-    __abstract__ = True
 
 class MappingProtocol(Protocol):
     __mapper__: Mapper
 
-class InspectionMixin(Base):
+class InspectionMixin:
 
     @classproperty
     def columns(cls) -> List[str]: ...


Test patch:
diff --git a/sqlalchemy_mixins/tests/test_activerecord.py b/sqlalchemy_mixins/tests/test_activerecord.py
index 901ac73..8284b2a 100644
--- a/sqlalchemy_mixins/tests/test_activerecord.py
+++ b/sqlalchemy_mixins/tests/test_activerecord.py
@@ -3,13 +3,16 @@ import unittest
 import sqlalchemy as sa
 from sqlalchemy import create_engine
 from sqlalchemy.ext.hybrid import hybrid_property
-from sqlalchemy.orm import Query, Session, DeclarativeBase
+from sqlalchemy.orm import Query, Session, DeclarativeBase, declarative_base
 
 from sqlalchemy_mixins import ActiveRecordMixin
 from sqlalchemy_mixins.activerecord import ModelNotFoundError
 
 class Base(DeclarativeBase):
     __abstract__ = True
+
+AlternativeBase = declarative_base()
+
 engine = create_engine('sqlite:///:memory:', echo=False)
 sess = Session(engine)
 # sess = scoped_session(sessionmaker(bind=engine))
@@ -20,6 +23,9 @@ class BaseModel(Base, ActiveRecordMixin):
     pass
 
 
+class BaseModelAlternative(AlternativeBase, ActiveRecordMixin):
+    __abstract__ = True
+
 class User(BaseModel):
     __tablename__ = 'user'
     __repr_attrs__ = ['name']
@@ -29,6 +35,13 @@ class User(BaseModel):
     posts_viewonly = sa.orm.relationship('Post', viewonly=True)
 
 
+class UserAlternative(BaseModelAlternative):
+    __tablename__ = 'user_alt'
+    __repr_attrs__ = ['name']
+    id = sa.Column(sa.Integer, primary_key=True)
+    name = sa.Column(sa.String)
+
+
 class Post(BaseModel):
     __tablename__ = 'post'
     id = sa.Column(sa.Integer, primary_key=True)
@@ -204,5 +217,21 @@ class TestActiveRecord(unittest.TestCase):
             _ = User.find_or_fail(123456789)
 
 
+class TestActiveRecordAlternative(unittest.TestCase):
+    def setUp(self):
+        sess.rollback()
+
+        BaseModelAlternative.set_session(None)
+        AlternativeBase.metadata.drop_all(engine)
+        AlternativeBase.metadata.create_all(engine)
+
+        BaseModelAlternative.set_session(sess)
+
+    def test_create(self):
+        u1 = UserAlternative.create(name='Bill u1')
+        self.assertEqual(u1, sess.query(UserAlternative).first())
+
+
+
 if __name__ == '__main__': # pragma: no cover
     unittest.main()