Skip to content

Commit

Permalink
Use Hatch instead of Tox
Browse files Browse the repository at this point in the history
- Removes the old setup.[py,cfg] in favour of a modern pyproject.toml
- Remove Tox in favour of Hatch
- Add tests!
  • Loading branch information
juledwar committed Jul 22, 2024
1 parent 986181a commit 7478f57
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 142 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8, 3.9]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
Expand All @@ -22,9 +22,9 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
pip install hatch
- name: Run Tox
- name: Run tests
run: |
tox
hatch run ci
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.tox/
.hatch/
.stestr/
db_testtools.egg-info/
__pycache__/
*.pyc
dbtesttools/_version.py
dist/
19 changes: 12 additions & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
{
"python.pythonPath": "${workspaceFolder}/.tox/py3/bin/python3",
"python.formatting.provider": "black",
"python.formatting.blackArgs": [
"[python]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"black-formatter.args": [
"--line-length",
"79"
],
"python.linting.flake8Enabled": true,
"python.linting.enabled": true,
"python.testing.pytestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.testing.unittestEnabled": true,
"files.watcherExclude": {
"**/.coverage/**": true,
"**/.eggs": true,
"**/.stestr/**": true,
"**/.testrepository/**": true,
"**/.tox/**": true
"${workspaceFolder}/build/**": true,
"**/.hatch/**": true
},
"git.allowForcePush": true,
"editor.wordWrapColumn": 79,
"vim.textwidth": 79,
"githubPullRequests.defaultMergeMethod": "rebase"
}

6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
CHANGES
=======

2024.07.21
----------
* Use Hatch to test and build the project
* Replace Black with Ruff for formatting and checking
* Allow overriding of the PG server IP address

2023.01.27
----------

Expand Down
15 changes: 6 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ after each test completes.
Requirements
------------

Python 3.7 and beyond should work.
Python 3.8 and beyond should work.

Quickstart
----------
Expand Down Expand Up @@ -76,7 +76,8 @@ dropped and re-instated on every test.

The PostgresContainerFixture starts its own Postgres instance in a local
Docker container. Therefore you must have Docker installed before using
this fixture.
this fixture. The Postgres image used by default is 16.3-alpine, but this
fixture is known to work all the way back to v11.

If you are already running inside Docker you will need to start the
container with `--network-"host"` so that 127.0.0.1 routes to the started
Expand All @@ -90,16 +91,12 @@ PG containers. You will need to do up to two extra things:
can set the DBTESTTOOLS_PG_IP_ADDR environment variable.


Help needed!
------------
This fixture suite is currently not tested itself and would benefit from
anyone willing to contribute some unit tests. However, it has been in
use daily on a large project at Cisco for a few years now, and is very
stable.
This code has been in use daily on a large project at Cisco for a few years
now, and is very stable.


Copyright
---------

db-testtools is copyright (c) 2021-2023 Cisco Systems, Inc. and its affiliates
db-testtools is copyright (c) 2021-2024 Cisco Systems, Inc. and its affiliates
All rights reserved.
17 changes: 7 additions & 10 deletions RELEASING.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ To release a new version of db-testtools:
1. Tag the current revision with the required release number, e.g.
`git tag 2021.09.29`
2. Build the package:
`tox -e build-python-package`
3. This will generate a new ChangeLog file. It needs to be committed as
a new revision.
4. After committing, move the tag: `git tag -f 2021.09.29`
5. Build the package again because PBR.
6. Upload the package to testpyi first to make sure it is ok:
`tox -e testpypi dist/*2021.9.29*`
7. If that looks ok, upload to the real pypi:
`tox -e pypi dist/*2021.9.29*`
8. Push the new tag to Github:
`hatch build`
3. Upload the package to testpyi first to make sure it is ok:
`hatch run testpypi dist/*2021.9.29*`
4. If that looks ok, upload to the real pypi:
`hatch run pypi dist/*2021.9.29*`
5. Push the new tag to Github:
`git push origin 2021.09.29`
6. Make a Github release
24 changes: 13 additions & 11 deletions dbtesttools/engines/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
LC_CTYPE = 'en_US.utf8';
CREATE USER testing WITH ENCRYPTED PASSWORD 'testing';
GRANT ALL PRIVILEGES ON DATABASE testing TO testing;
GRANT ALL ON SCHEMA public TO testing;
ALTER DATABASE testing OWNER TO testing;
"""

NEXT_ID = count(1)
Expand Down Expand Up @@ -53,10 +55,10 @@ def __init__(
# Using the larger non-alpine image causes sort-order errors
# because of locale collation differences.
# image='postgres:11.4',
image='postgres:11.11-alpine',
name='testdb',
image="postgres:16.3-alpine",
name="testdb",
init_sql=None,
pg_data='/tmp/pgdata', # noqa: S108
pg_data="/tmp/pgdata", # noqa: S108
isolation=None,
future=False,
ip_address=None,
Expand All @@ -71,7 +73,7 @@ def __init__(
self.isolation = isolation
self.future = future
self.ip_address = ip_address or os.getenv(
'DBTESTTOOLS_PG_IP_ADDR', '127.0.0.1'
"DBTESTTOOLS_PG_IP_ADDR", "127.0.0.1"
)

def connect(self):
Expand All @@ -95,7 +97,7 @@ def setUp(self):
self.wait_for_pg_start()
self.set_up_test_database()
self.engine = sa.create_engine(
'postgresql://testing:testing@{ip}:{port}/testing'.format(
"postgresql://testing:testing@{ip}:{port}/testing".format(
ip=self.ip_address, port=self.local_port
),
isolation_level=self.isolation,
Expand All @@ -111,18 +113,18 @@ def pull_image(self):
self.client.images.pull(self.image)

def start_container(self):
env = dict(POSTGRES_PASSWORD='postgres', PGDATA=self.pg_data) # noqa: S106
ports = {'5432': self.local_port}
env = dict(POSTGRES_PASSWORD="postgres", PGDATA=self.pg_data) # noqa: S106
ports = {"5432": self.local_port}
print("Starting Postgres container ...", file=sys.stderr)
# Uniq-ify the name as threaded tests will create multiple containers.
name = '{}-{}.{}'.format(self.name, os.getpid(), next(NEXT_ID))
name = "{}-{}.{}".format(self.name, os.getpid(), next(NEXT_ID))
self.container = self.client.containers.run(
self.image,
detach=True,
auto_remove=True,
environment=env,
name=name,
network_mode='bridge',
network_mode="bridge",
ports=ports,
remove=True,
)
Expand All @@ -133,7 +135,7 @@ def find_free_port(self):
# real free port. We close the socket after determnining which port
# that was.
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
s.bind(('localhost', 0))
s.bind(("localhost", 0))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.local_port = s.getsockname()[1]
print("Using port {}".format(self.local_port), file=sys.stderr)
Expand All @@ -148,7 +150,7 @@ def set_up_test_database(self):
)
c.autocommit = True
cur = c.cursor()
for stmt in self.init_sql.split(';'):
for stmt in self.init_sql.split(";"):
if stmt.strip():
cur.execute(stmt)
cur.close()
Expand Down
15 changes: 5 additions & 10 deletions dbtesttools/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def __init__(
ModelBase,
models_module, # NOSONAR
patch_query_property=False,
engine_fixture_name='SqliteMemoryFixture',
engine_fixture_name="SqliteMemoryFixture",
sessionmaker_class=None,
engine_fixture_kwargs=None,
future=False,
Expand All @@ -83,7 +83,7 @@ def __init__(
self.sessionmaker_class = sessionmaker_class
self.engine_fixture_kwargs = engine_fixture_kwargs or {}
self.future = future
self.engine_fixture_kwargs['future'] = self.future
self.engine_fixture_kwargs["future"] = self.future

def make(self, dep_resources):
print("Creating new database resource...", file=sys.stderr)
Expand All @@ -101,22 +101,21 @@ def has_savepoint(self):

def clean(self, resource):
print("Cleaning up database resource...", file=sys.stderr)
self.drop_tables(self.engine)
self.db.cleanUp()

def pick_engine_fixture(self):
env_name = os.environ.get('TEST_ENGINE_FIXTURE', None)
env_name = os.environ.get("TEST_ENGINE_FIXTURE", None)
if env_name is not None:
self.engine_fixture_name = env_name
import dbtesttools.engines

for _, module, _ in pkgutil.iter_modules(dbtesttools.engines.__path__):
mod = importlib.import_module(f'dbtesttools.engines.{module}')
mod = importlib.import_module(f"dbtesttools.engines.{module}")

for name, obj in mod.__dict__.items():
if name == self.engine_fixture_name:
return obj(**self.engine_fixture_kwargs)
raise AttributeError(f'{self.engine_fixture_name} not found')
raise AttributeError(f"{self.engine_fixture_name} not found")

def initialize_engine(self):
self.db = self.pick_engine_fixture()
Expand Down Expand Up @@ -177,10 +176,6 @@ def create_tables(self, engine):
metadata = self.ModelBase.metadata
metadata.create_all(bind=engine)

def drop_tables(self, engine):
metadata = self.ModelBase.metadata
metadata.drop_all(bind=engine)

def rollback_transaction(self, txn):
"""Roll back an in-progress transaction.
Expand Down
13 changes: 13 additions & 0 deletions dbtesttools/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import os

import testresources
from testscenarios import generate_scenarios


def load_tests(loader, tests, pattern):
this_dir = os.path.dirname(__file__)
mytests = loader.discover(start_dir=this_dir, pattern=pattern)
result = testresources.OptimisingTestSuite()
result.addTests(generate_scenarios(mytests))
result.addTests(generate_scenarios(tests))
return result
11 changes: 11 additions & 0 deletions dbtesttools/tests/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import sqlalchemy as sa
from sqlalchemy.orm import declarative_base

ModelBase = declarative_base()


class TestModel(ModelBase):
__tablename__ = "test_model"
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
value = sa.Column(sa.Integer)
Loading

0 comments on commit 7478f57

Please sign in to comment.