hdx-python-database 1.2.8__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.config/pre-commit-config.yaml +9 -10
  2. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.config/ruff.toml +7 -5
  3. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/CONTRIBUTING.md +2 -3
  4. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/PKG-INFO +1 -1
  5. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/documentation/main.md +13 -0
  6. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/pyproject.toml +4 -12
  7. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/requirements.txt +17 -17
  8. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/__init__.py +8 -5
  9. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/_version.py +2 -2
  10. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/views.py +33 -3
  11. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/dbtestdate.py +8 -6
  12. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/test_database.py +11 -1
  13. hdx_python_database-1.2.8/.config/black.toml +0 -2
  14. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.config/coveragerc +0 -0
  15. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.config/pytest.ini +0 -0
  16. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.github/workflows/publish.yaml +0 -0
  17. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.github/workflows/run-python-tests.yaml +0 -0
  18. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/.gitignore +0 -0
  19. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/LICENSE +0 -0
  20. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/README.md +0 -0
  21. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/documentation/.readthedocs.yaml +0 -0
  22. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/documentation/pydoc-markdown.yaml +0 -0
  23. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/dburi.py +0 -0
  24. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/no_timezone.py +0 -0
  25. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/postgresql.py +0 -0
  26. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/utils.py +0 -0
  27. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/src/hdx/database/with_timezone.py +0 -0
  28. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/fixtures/test.db +0 -0
  29. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/__init__.py +0 -0
  30. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/conftest.py +0 -0
  31. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/test_dburi.py +0 -0
  32. {hdx_python_database-1.2.8 → hdx_python_database-1.3.0}/tests/hdx/database/test_postgresql.py +0 -0
@@ -2,23 +2,22 @@ default_language_version:
2
2
  python: python3.11
3
3
  repos:
4
4
  - repo: https://github.com/pre-commit/pre-commit-hooks
5
- rev: v4.4.0
5
+ rev: v4.5.0
6
6
  hooks:
7
7
  - id: trailing-whitespace
8
8
  - id: end-of-file-fixer
9
9
  - id: check-ast
10
- - repo: https://github.com/psf/black
11
- rev: 23.3.0
12
- hooks:
13
- - id: black
14
- args: [--config, .config/black.toml]
15
- - repo: https://github.com/charliermarsh/ruff-pre-commit
16
- rev: v0.0.267
10
+ - repo: https://github.com/astral-sh/ruff-pre-commit
11
+ rev: v0.1.14
17
12
  hooks:
13
+ # Run the linter.
18
14
  - id: ruff
19
- args: [--config, .config/ruff.toml, --fix, --exit-non-zero-on-fix]
15
+ args: [--config, .config/ruff.toml, --fix]
16
+ # Run the formatter.
17
+ - id: ruff-format
18
+ args: [--config, .config/ruff.toml]
20
19
  - repo: https://github.com/jazzband/pip-tools
21
- rev: 6.13.0
20
+ rev: 7.3.0
22
21
  hooks:
23
22
  - id: pip-compile
24
23
  name: pip-compile requirements.txt
@@ -1,14 +1,16 @@
1
1
  line-length = 79
2
2
  exclude = ["_version.py"]
3
- ignore = [
4
- "E501" # Line too long
5
- ]
6
- # List of rules: https://beta.ruff.rs/docs/rules/
3
+
4
+ [lint]
5
+ # List of rules: https://docs.astral.sh/ruff/rules/
7
6
  select = [
8
7
  "E", # pycodestyle - default
9
8
  "F", # pyflakes - default
10
9
  "I" # isort
11
10
  ]
11
+ ignore = [
12
+ "E501" # Line too long
13
+ ]
12
14
 
13
- [isort]
15
+ [lint.isort]
14
16
  known-local-folder = ["hdx"]
@@ -21,14 +21,13 @@ you make a git commit:
21
21
  pre-commit install
22
22
 
23
23
  The configuration file for this project is in a
24
- non-start location. Thus, you will need to edit your
24
+ non-standard location. Thus, you will need to edit your
25
25
  `.git/hooks/pre-commit` file to reflect this. Change
26
26
  the line that begins with `ARGS` to:
27
27
 
28
28
  ARGS=(hook-impl --config=.config/pre-commit-config.yaml --hook-type=pre-commit)
29
29
 
30
30
  With pre-commit, all code is formatted according to
31
- [black]("https://github.com/psf/black") and
32
31
  [ruff]("https://github.com/charliermarsh/ruff") guidelines.
33
32
 
34
33
  To check if your changes pass pre-commit without committing, run:
@@ -41,7 +40,7 @@ To run the tests and view coverage, execute:
41
40
 
42
41
  pytest -c .config/pytest.ini --cov hdx --cov-config .config/coveragerc
43
42
 
44
- Follow the example set out already in ``api.rst`` as you write the documentation.
43
+ Follow the example set out already in ``documentation/main.md`` as you write the documentation.
45
44
 
46
45
  ## Packages
47
46
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hdx-python-database
3
- Version: 1.2.8
3
+ Version: 1.3.0
4
4
  Summary: HDX Python database utilities
5
5
  Project-URL: Homepage, https://github.com/OCHA-DAP/hdx-python-database
6
6
  Author-email: Michael Rans <rans@email.com>
@@ -134,6 +134,19 @@ org_type_view = view(
134
134
  metadata=Base.metadata,
135
135
  selectable=select(*DBOrgType.__table__.columns),
136
136
  )
137
+
138
+ class DBTestDate(Base):
139
+ test_date: Mapped[datetime] = mapped_column(primary_key=True)
140
+
141
+ date_view_params = {
142
+ "name": "date_view",
143
+ "metadata": Base.metadata,
144
+ "selectable": select(*DBTestDate.__table__.columns),
145
+ }
146
+
147
+ date_view = build_view(date_view_params)
148
+
149
+ date_view = build_views([date_view_params])[0]
137
150
  ```
138
151
 
139
152
  ## PostgreSQL specific
@@ -86,22 +86,14 @@ test = """
86
86
  """
87
87
 
88
88
  [[tool.hatch.envs.test.matrix]]
89
- python = ["3.11"]
89
+ python = ["3.12"]
90
90
 
91
91
  [tool.hatch.envs.lint]
92
92
  detached = true
93
- dependencies = [
94
- "black",
95
- "ruff",
96
- ]
93
+ dependencies = ["ruff"]
97
94
 
98
95
  [tool.hatch.envs.lint.scripts]
99
96
  style = [
100
- "ruff --config .config/ruff.toml {args:.}",
101
- "black --config .config/black.toml --check --diff {args:.}",
102
- ]
103
- # Not used for anything at the moment
104
- fmt = [
105
- "black --config .config/black.toml {args:.}",
106
- "ruff --config .config/ruff.toml --fix {args:.}",
97
+ "ruff check --config .config/ruff.toml --diff {args:.}",
98
+ "ruff format --config .config/ruff.toml --diff {args:.}",
107
99
  ]
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # pip-compile --all-extras --output-file=requirements.txt --resolver=backtracking pyproject.toml
6
6
  #
7
- bcrypt==4.0.1
7
+ bcrypt==4.1.2
8
8
  # via paramiko
9
9
  cffi==1.16.0
10
10
  # via
@@ -12,17 +12,17 @@ cffi==1.16.0
12
12
  # pynacl
13
13
  cfgv==3.4.0
14
14
  # via pre-commit
15
- coverage[toml]==7.3.2
15
+ coverage[toml]==7.4.1
16
16
  # via pytest-cov
17
- cryptography==41.0.4
17
+ cryptography==42.0.2
18
18
  # via paramiko
19
- distlib==0.3.7
19
+ distlib==0.3.8
20
20
  # via virtualenv
21
- filelock==3.12.4
21
+ filelock==3.13.1
22
22
  # via virtualenv
23
- greenlet==3.0.0
23
+ greenlet==3.0.3
24
24
  # via sqlalchemy
25
- identify==2.5.30
25
+ identify==2.5.34
26
26
  # via pre-commit
27
27
  iniconfig==2.0.0
28
28
  # via pytest
@@ -30,23 +30,23 @@ nodeenv==1.8.0
30
30
  # via pre-commit
31
31
  packaging==23.2
32
32
  # via pytest
33
- paramiko==3.3.1
33
+ paramiko==3.4.0
34
34
  # via sshtunnel
35
- platformdirs==3.11.0
35
+ platformdirs==4.2.0
36
36
  # via virtualenv
37
- pluggy==1.3.0
37
+ pluggy==1.4.0
38
38
  # via pytest
39
- pre-commit==3.4.0
39
+ pre-commit==3.6.1
40
40
  # via hdx-python-database (pyproject.toml)
41
- psycopg[binary]==3.1.12
41
+ psycopg[binary]==3.1.18
42
42
  # via hdx-python-database (pyproject.toml)
43
- psycopg-binary==3.1.12
43
+ psycopg-binary==3.1.18
44
44
  # via psycopg
45
45
  pycparser==2.21
46
46
  # via cffi
47
47
  pynacl==1.5.0
48
48
  # via paramiko
49
- pytest==7.4.2
49
+ pytest==8.0.0
50
50
  # via
51
51
  # hdx-python-database (pyproject.toml)
52
52
  # pytest-cov
@@ -54,15 +54,15 @@ pytest-cov==4.1.0
54
54
  # via hdx-python-database (pyproject.toml)
55
55
  pyyaml==6.0.1
56
56
  # via pre-commit
57
- sqlalchemy==2.0.21
57
+ sqlalchemy==2.0.27
58
58
  # via hdx-python-database (pyproject.toml)
59
59
  sshtunnel==0.4.0
60
60
  # via hdx-python-database (pyproject.toml)
61
- typing-extensions==4.8.0
61
+ typing-extensions==4.9.0
62
62
  # via
63
63
  # psycopg
64
64
  # sqlalchemy
65
- virtualenv==20.24.5
65
+ virtualenv==20.25.0
66
66
  # via pre-commit
67
67
 
68
68
  # The following packages are considered to be unsafe in a requirements file:
@@ -23,7 +23,7 @@ class Database:
23
23
  reflected classes. db_has_tz which defaults to False indicates whether
24
24
  database datetime columns have timezones. If not, conversion occurs between
25
25
  Python datetimes with timezones to timezoneless database columns (but not
26
- when using reflection).
26
+ when using reflection). If table_base is supplied, db_has_tz is ignored.
27
27
 
28
28
  Args:
29
29
  database (Optional[str]): Database name
@@ -34,6 +34,7 @@ class Database:
34
34
  dialect (str): Database dialect. Defaults to "postgresql".
35
35
  driver (Optional[str]): Database driver. Defaults to None (psycopg if postgresql or None)
36
36
  db_has_tz (bool): True if db datetime columns have timezone. Defaults to False.
37
+ table_base (Optional[Type[DeclarativeBase]]): Override table base. Defaults to None.
37
38
  reflect (bool): Whether to reflect existing tables. Defaults to False.
38
39
  **kwargs: See below
39
40
  ssh_host (str): SSH host (the server to connect to)
@@ -55,6 +56,7 @@ class Database:
55
56
  dialect: str = "postgresql",
56
57
  driver: Optional[str] = None,
57
58
  db_has_tz: bool = False,
59
+ table_base: Optional[Type[DeclarativeBase]] = None,
58
60
  reflect: bool = False,
59
61
  **kwargs: Any,
60
62
  ) -> None:
@@ -98,10 +100,11 @@ class Database:
98
100
  )
99
101
  if dialect == "postgresql":
100
102
  wait_for_postgresql(db_uri)
101
- if db_has_tz:
102
- table_base = TZBase
103
- else:
104
- table_base = NoTZBase
103
+ if not table_base:
104
+ if db_has_tz:
105
+ table_base = TZBase
106
+ else:
107
+ table_base = NoTZBase
105
108
  self.session = self.get_session(
106
109
  db_uri, table_base=table_base, reflect=reflect
107
110
  )
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.2.8'
16
- __version_tuple__ = version_tuple = (1, 2, 8)
15
+ __version__ = version = '1.3.0'
16
+ __version_tuple__ = version_tuple = (1, 3, 0)
@@ -4,8 +4,10 @@ Create a DB View.
4
4
  Copied from:
5
5
  https://github.com/sqlalchemy/sqlalchemy/wiki/Views#sqlalchemy-14-20-version
6
6
  """
7
+ from typing import Dict, List
8
+
7
9
  import sqlalchemy as sa
8
- from sqlalchemy import MetaData, Select, TableClause
10
+ from sqlalchemy import MetaData, Selectable, TableClause
9
11
  from sqlalchemy.ext import compiler
10
12
  from sqlalchemy.schema import DDLElement
11
13
  from sqlalchemy.sql import table
@@ -43,13 +45,13 @@ def view_doesnt_exist(ddl, target, connection, **kw):
43
45
  return not view_exists(ddl, target, connection, **kw)
44
46
 
45
47
 
46
- def view(name: str, metadata: MetaData, selectable: Select) -> TableClause:
48
+ def view(name: str, metadata: MetaData, selectable: Selectable) -> TableClause:
47
49
  """Create SQLAlchemy view
48
50
 
49
51
  Args:
50
52
  name (str): View name
51
53
  metadata (MetaData): Base metadata
52
- selectable (Select): SQLAlchemy select statement
54
+ selectable (Selectable): SQLAlchemy select statement
53
55
 
54
56
  Returns:
55
57
  TableClause: SQLAlchemy View
@@ -71,3 +73,31 @@ def view(name: str, metadata: MetaData, selectable: Select) -> TableClause:
71
73
  DropView(name).execute_if(callable_=view_exists),
72
74
  )
73
75
  return t
76
+
77
+
78
+ def build_view(view_params: Dict) -> TableClause:
79
+ """Create SQLAlchemy view from dictionary with keys: name, metadata and
80
+ selectable
81
+
82
+ Args:
83
+ view_params (Dict): Dictionary with keys name, metadata, selectable
84
+
85
+ Returns:
86
+ TableClause: SQLAlchemy View
87
+ """
88
+ return view(**view_params)
89
+
90
+
91
+ def build_views(view_params_list: List[Dict]) -> List[TableClause]:
92
+ """Create SQLAlchemy views from a list of dictionaries with keys: name,
93
+ metadata and selectable
94
+
95
+ Args:
96
+ view_params_list (List[Dict]): List of dictionaries with view parameters
97
+ Returns:
98
+ List[TableClause]: SQLAlchemy Views
99
+ """
100
+ results = []
101
+ for view_params in view_params_list:
102
+ results.append(build_view(view_params))
103
+ return results
@@ -6,7 +6,7 @@ from sqlalchemy import select
6
6
  from sqlalchemy.orm import Mapped, mapped_column
7
7
 
8
8
  from hdx.database.no_timezone import Base
9
- from hdx.database.views import view
9
+ from hdx.database.views import build_views
10
10
 
11
11
 
12
12
  class DBTestDate(Base):
@@ -25,8 +25,10 @@ class DBTestDate(Base):
25
25
  return f"<Test date={str(self.test_date)}>"
26
26
 
27
27
 
28
- date_view = view(
29
- name="date_view",
30
- metadata=Base.metadata,
31
- selectable=select(*DBTestDate.__table__.columns),
32
- )
28
+ date_view_params = {
29
+ "name": "date_view",
30
+ "metadata": Base.metadata,
31
+ "selectable": select(*DBTestDate.__table__.columns),
32
+ }
33
+
34
+ date_view = build_views([date_view_params])[0]
@@ -10,7 +10,7 @@ import pytest
10
10
  from sqlalchemy import select
11
11
  from sshtunnel import SSHTunnelForwarder
12
12
 
13
- from .dbtestdate import DBTestDate
13
+ from .dbtestdate import DBTestDate, date_view
14
14
  from hdx.database import Database
15
15
  from hdx.database.no_timezone import Base as NoTZBase
16
16
  from hdx.database.with_timezone import Base as TZBase
@@ -94,6 +94,8 @@ class TestDatabase:
94
94
  dbsession.commit()
95
95
  dbtestdate = dbsession.execute(select(DBTestDate)).scalar_one()
96
96
  assert dbtestdate.test_date == now
97
+ dbtestdate = dbsession.execute(select(date_view)).scalar_one()
98
+ assert dbtestdate == now
97
99
 
98
100
  def test_get_reflect_session(self, database_to_reflect):
99
101
  with Database(
@@ -138,3 +140,11 @@ class TestDatabase:
138
140
  == "postgresql+psycopg://myuser@0.0.0.0:12345/mydatabase"
139
141
  )
140
142
  assert TestDatabase.table_base == TZBase
143
+ with Database(
144
+ ssh_host="mysshhost", ssh_port=25, table_base=TZBase, **params
145
+ ) as dbsession:
146
+ assert (
147
+ str(dbsession.bind.engine.url)
148
+ == "postgresql+psycopg://myuser@0.0.0.0:12345/mydatabase"
149
+ )
150
+ assert TestDatabase.table_base == TZBase
@@ -1,2 +0,0 @@
1
- [tool.black]
2
- line-length = 79