From 56034567d01d93875f1cf1e084f8c7ebd9670508 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Nov 2025 15:48:35 +0000 Subject: [PATCH 1/3] Initial plan From 1d5424e1ab27e155885afacd5e358f03c07b6ed1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Nov 2025 15:52:27 +0000 Subject: [PATCH 2/3] Add create_table parameter to prevent automatic table creation Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- README.md | 21 +++++++++++ sqlalchemy_adapter/adapter.py | 4 +- tests/test_adapter.py | 69 +++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aac721..1764d0a 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,27 @@ adapter = sqlalchemy_adapter.Adapter('sqlite:///test.db', table_name=custom_tabl e = casbin.Enforcer('path/to/model.conf', adapter) ``` +## Prevent Automatic Table Creation + +By default, the adapter automatically creates the necessary database tables during initialization. If you want to use the adapter only as an intermediary without automatically creating tables, you can set the `create_table` parameter to `False`: + +```python +import sqlalchemy_adapter +import casbin + +# Create adapter without automatically creating tables +adapter = sqlalchemy_adapter.Adapter('sqlite:///test.db', create_table=False) + +e = casbin.Enforcer('path/to/model.conf', adapter) +``` + +This is useful when: +- Tables are already created by your database migration system +- You want to manage table creation separately +- You are using the adapter as an intermediary between SQLAlchemy and your system + +**Note:** When `create_table=False`, you are responsible for ensuring the required tables exist in the database before using the adapter. + ### Getting Help diff --git a/sqlalchemy_adapter/adapter.py b/sqlalchemy_adapter/adapter.py index 81957cf..163fc36 100644 --- a/sqlalchemy_adapter/adapter.py +++ b/sqlalchemy_adapter/adapter.py @@ -80,6 +80,7 @@ def __init__( db_class=None, table_name="casbin_rule", filtered=False, + create_table=True, ): if isinstance(engine, str): self._engine = create_engine(engine) @@ -107,7 +108,8 @@ def __init__( self._db_class = db_class self.session_local = sessionmaker(bind=self._engine) - metadata.create_all(self._engine) + if create_table: + metadata.create_all(self._engine) self._filtered = filtered @contextmanager diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 8e22883..8665a4e 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -409,3 +409,72 @@ def test_update_filtered_policies(self): e.update_filtered_policies([["bob", "data2", "read"]], 0, "bob") self.assertTrue(e.enforce("bob", "data2", "read")) + + def test_create_table_false(self): + """Test that tables are not created when create_table=False""" + from sqlalchemy import inspect + + engine = create_engine("sqlite://") + + # Create adapter with create_table=False + adapter = Adapter(engine, create_table=False) + + # Verify that the table was NOT created + inspector = inspect(engine) + tables = inspector.get_table_names() + self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") + + def test_create_table_true_default(self): + """Test that tables are created by default (backward compatibility)""" + from sqlalchemy import inspect + + engine = create_engine("sqlite://") + + # Create adapter without specifying create_table (should default to True) + adapter = Adapter(engine) + + # Verify that the table WAS created + inspector = inspect(engine) + tables = inspector.get_table_names() + self.assertIn("casbin_rule", tables, "Table should be created by default") + + def test_create_table_custom_table_name(self): + """Test that custom table name is not created when create_table=False""" + from sqlalchemy import inspect + + engine = create_engine("sqlite://") + table_name = "my_custom_table" + + # Create adapter with custom table name and create_table=False + adapter = Adapter(engine, table_name=table_name, create_table=False) + + # Verify that the table was NOT created + inspector = inspect(engine) + tables = inspector.get_table_names() + self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") + + def test_create_table_custom_db_class(self): + """Test that custom db_class table is not created when create_table=False""" + from sqlalchemy import inspect + + class CustomRule(Base): + __tablename__ = "custom_rule_table" + + id = Column(Integer, primary_key=True) + ptype = Column(String(255)) + v0 = Column(String(255)) + v1 = Column(String(255)) + v2 = Column(String(255)) + v3 = Column(String(255)) + v4 = Column(String(255)) + v5 = Column(String(255)) + + engine = create_engine("sqlite://") + + # Create adapter with custom db_class and create_table=False + adapter = Adapter(engine, db_class=CustomRule, create_table=False) + + # Verify that the table was NOT created + inspector = inspect(engine) + tables = inspector.get_table_names() + self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") From 1fe354bc28b983781b1a82f07da61e765ed08e61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 16 Nov 2025 15:56:23 +0000 Subject: [PATCH 3/3] Apply Black formatting to test file Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com> --- tests/test_adapter.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 8665a4e..ee51cb7 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -413,26 +413,28 @@ def test_update_filtered_policies(self): def test_create_table_false(self): """Test that tables are not created when create_table=False""" from sqlalchemy import inspect - + engine = create_engine("sqlite://") - + # Create adapter with create_table=False adapter = Adapter(engine, create_table=False) - + # Verify that the table was NOT created inspector = inspect(engine) tables = inspector.get_table_names() - self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") + self.assertEqual( + len(tables), 0, "No tables should be created when create_table=False" + ) def test_create_table_true_default(self): """Test that tables are created by default (backward compatibility)""" from sqlalchemy import inspect - + engine = create_engine("sqlite://") - + # Create adapter without specifying create_table (should default to True) adapter = Adapter(engine) - + # Verify that the table WAS created inspector = inspect(engine) tables = inspector.get_table_names() @@ -441,22 +443,24 @@ def test_create_table_true_default(self): def test_create_table_custom_table_name(self): """Test that custom table name is not created when create_table=False""" from sqlalchemy import inspect - + engine = create_engine("sqlite://") table_name = "my_custom_table" - + # Create adapter with custom table name and create_table=False adapter = Adapter(engine, table_name=table_name, create_table=False) - + # Verify that the table was NOT created inspector = inspect(engine) tables = inspector.get_table_names() - self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") + self.assertEqual( + len(tables), 0, "No tables should be created when create_table=False" + ) def test_create_table_custom_db_class(self): """Test that custom db_class table is not created when create_table=False""" from sqlalchemy import inspect - + class CustomRule(Base): __tablename__ = "custom_rule_table" @@ -470,11 +474,13 @@ class CustomRule(Base): v5 = Column(String(255)) engine = create_engine("sqlite://") - + # Create adapter with custom db_class and create_table=False adapter = Adapter(engine, db_class=CustomRule, create_table=False) - + # Verify that the table was NOT created inspector = inspect(engine) tables = inspector.get_table_names() - self.assertEqual(len(tables), 0, "No tables should be created when create_table=False") + self.assertEqual( + len(tables), 0, "No tables should be created when create_table=False" + )