Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

invenio-db

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

invenio-db - npm Package Compare versions

Comparing version
1.3.1
to
2.0.0
+15
invenio_db/proxies.py
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2022 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
"""Helper proxy to the state object."""
from flask import current_app
from werkzeug.local import LocalProxy
current_db = LocalProxy(lambda: current_app.extensions["sqlalchemy"])
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2023 Graz University of Technology.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
"""Test database integration layer."""
from importlib_metadata import EntryPoint
from werkzeug.utils import import_string
class MockEntryPoint(EntryPoint):
"""Mocking of entrypoint."""
def load(self):
"""Mock load entry point."""
if self.name == "importfail":
raise ImportError()
else:
return import_string(self.name)
def _mock_entry_points(name):
def fn(group):
data = {
"invenio_db.models": [
MockEntryPoint(name="demo.child", value="demo.child", group="test"),
MockEntryPoint(name="demo.parent", value="demo.parent", group="test"),
],
"invenio_db.models_a": [
MockEntryPoint(
name="demo.versioned_a", value="demo.versioned_a", group="test"
),
],
"invenio_db.models_b": [
MockEntryPoint(
name="demo.versioned_b", value="demo.versioned_b", group="test"
),
],
}
if group:
return data.get(group, [])
if name:
return {name: data.get(name)}
return data
return fn
+13
-53

@@ -5,3 +5,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2020-2024 CERN.
# Copyright (C) 2022 Graz University of Technology.
# Copyright (C) 2022-2024 Graz University of Technology.
#

@@ -15,63 +15,23 @@ # Invenio is free software; you can redistribute it and/or modify it

push:
branches: master
branches:
- master
pull_request:
branches: master
branches:
- master
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '0 3 * * 6'
- cron: "0 3 * * 6"
workflow_dispatch:
inputs:
reason:
description: 'Reason'
description: "Reason"
required: false
default: 'Manual trigger'
default: "Manual trigger"
jobs:
Tests:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
python-version: [3.9, 3.12]
db-service: [postgresql11, postgresql14, mysql8, sqlite]
uses: inveniosoftware/workflows/.github/workflows/tests-python.yml@master
with:
extras: "tests,postgresql"
search-service: '[""]'
include:
- db-service: postgresql11
EXTRAS: "tests,postgresql"
- db-service: postgresql14
EXTRAS: "tests,postgresql"
- db-service: mysql8
EXTRAS: "tests,mysql"
- db-service: sqlite
EXTRAS: "tests"
env:
DB: ${{ matrix.db-service }}
EXTRAS: ${{ matrix.EXTRAS }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: setup.cfg
- name: Pre-install
uses: ./.github/actions/pre-install
if: ${{ hashFiles('.github/actions/pre-install/action.yml') != '' }}
- name: Install dependencies
run: |
pip install ".[$EXTRAS]"
pip freeze
docker version
- name: Run tests
run: ./run-tests.sh
..
This file is part of Invenio.
Copyright (C) 2015-2024 CERN.
Copyright (C) 2024 Graz University of Technology.

@@ -11,2 +12,19 @@ Invenio is free software; you can redistribute it and/or modify it

Version v2.0.0 (released 2024-11-19)
- uow: possible solution for the rollback problem
- fix: select of BinaryExpressions
- setup: increase flask-sqlalchemy
- ci: change to reusable workflows
- setup: increase min sqlalchemy dependency
- cli: password is per default hided
- refactor: move MockEntryPoint to independent file
- setup: remove upper pins
- fix: remove warning and black problems
- fix: WeakKeyDictionary
- change: add proxy file
- change: remove click 3 compatibility
- fix: tests LocalProxy
- setup: increase flask-sqlalchemy version
Version v1.3.1 (released 2024-11-14)

@@ -13,0 +31,0 @@

Metadata-Version: 2.1
Name: invenio-db
Version: 1.3.1
Version: 2.0.0
Summary: Database management for Invenio.

@@ -39,2 +39,3 @@ Home-page: https://github.com/inveniosoftware/invenio-db

Copyright (C) 2015-2024 CERN.
Copyright (C) 2024 Graz University of Technology.

@@ -47,2 +48,19 @@ Invenio is free software; you can redistribute it and/or modify it

Version v2.0.0 (released 2024-11-19)
- uow: possible solution for the rollback problem
- fix: select of BinaryExpressions
- setup: increase flask-sqlalchemy
- ci: change to reusable workflows
- setup: increase min sqlalchemy dependency
- cli: password is per default hided
- refactor: move MockEntryPoint to independent file
- setup: remove upper pins
- fix: remove warning and black problems
- fix: WeakKeyDictionary
- change: add proxy file
- change: remove click 3 compatibility
- fix: tests LocalProxy
- setup: increase flask-sqlalchemy version
Version v1.3.1 (released 2024-11-14)

@@ -49,0 +67,0 @@

@@ -1,8 +0,8 @@

alembic<1.11.0,>=1.10.0
Flask-Alembic>=2.0.1
Flask-SQLAlchemy<3.0.0,>=2.1
alembic>=1.10.0
Flask-Alembic>=3.0.0
Flask-SQLAlchemy>=3.0
invenio-base>=1.2.10
SQLAlchemy-Continuum>=1.3.12
SQLAlchemy-Utils<0.39,>=0.33.1
SQLAlchemy[asyncio]<1.5.0,>=1.2.18
SQLAlchemy-Utils>=0.33.1
SQLAlchemy[asyncio]>=2.0.0

@@ -16,3 +16,4 @@ [mysql]

[tests]
pytest-black>=0.3.0
six>=1.0.0
pytest-black-ng>=0.4.0
cryptography>=2.1.4

@@ -19,0 +20,0 @@ pytest-invenio>=1.4.5

@@ -37,2 +37,3 @@ .dockerignore

invenio_db/ext.py
invenio_db/proxies.py
invenio_db/shared.py

@@ -53,2 +54,3 @@ invenio_db/uow.py

tests/conftest.py
tests/mocks.py
tests/test_db.py

@@ -55,0 +57,0 @@ tests/test_uow.py

@@ -5,2 +5,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2015-2024 CERN.
# Copyright (C) 2024 Graz University of Technology.
#

@@ -95,3 +96,3 @@ # Invenio is free software; you can redistribute it and/or modify it

__version__ = "1.3.1"
__version__ = "2.0.0"

@@ -98,0 +99,0 @@ __all__ = (

@@ -26,5 +26,5 @@ # -*- coding: utf-8 -*-

"transaction",
sa.Column("issued_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.BigInteger(), nullable=False),
sa.Column("remote_addr", sa.String(length=50), nullable=True),
sa.Column("issued_at", sa.DateTime(), nullable=True),
)

@@ -31,0 +31,0 @@ op.create_primary_key("pk_transaction", "transaction", ["id"])

@@ -5,2 +5,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2015-2018 CERN.
# Copyright (C) 2024 Graz University of Technology.
#

@@ -12,20 +13,10 @@ # Invenio is free software; you can redistribute it and/or modify it

import sys
import click
from click import _termui_impl
from flask import current_app
from flask.cli import with_appcontext
from sqlalchemy_utils.functions import create_database, database_exists, drop_database
from werkzeug.local import LocalProxy
from .proxies import current_db
from .utils import create_alembic_version_table, drop_alembic_version_table
_db = LocalProxy(lambda: current_app.extensions["sqlalchemy"].db)
# Fix Python 3 compatibility issue in click
if sys.version_info > (3,):
_termui_impl.long = int # pragma: no cover
def abort_if_false(ctx, param, value):

@@ -39,7 +30,3 @@ """Abort command is value is False."""

"""Render the URL for CLI output."""
try:
return url.render_as_string(hide_password=True)
except AttributeError:
# SQLAlchemy <1.4
return url.__to_string__(hide_password=True)
return url.render_as_string(hide_password=True)

@@ -61,7 +48,7 @@

click.secho("Creating all tables!", fg="yellow", bold=True)
with click.progressbar(_db.metadata.sorted_tables) as bar:
with click.progressbar(current_db.metadata.sorted_tables) as bar:
for table in bar:
if verbose:
click.echo(" Creating table {0}".format(table))
table.create(bind=_db.engine, checkfirst=True)
table.create(bind=current_db.engine, checkfirst=True)
create_alembic_version_table()

@@ -84,7 +71,7 @@ click.secho("Created all tables!", fg="green")

click.secho("Dropping all tables!", fg="red", bold=True)
with click.progressbar(reversed(_db.metadata.sorted_tables)) as bar:
with click.progressbar(reversed(current_db.metadata.sorted_tables)) as bar:
for table in bar:
if verbose:
click.echo(" Dropping table {0}".format(table))
table.drop(bind=_db.engine, checkfirst=True)
table.drop(bind=current_db.engine, checkfirst=True)
drop_alembic_version_table()

@@ -98,5 +85,5 @@ click.secho("Dropped all tables!", fg="green")

"""Create database."""
displayed_database = render_url(_db.engine.url)
displayed_database = render_url(current_db.engine.url)
click.secho(f"Creating database {displayed_database}", fg="green")
database_url = str(_db.engine.url)
database_url = current_db.engine.url.render_as_string(hide_password=False)
if not database_exists(database_url):

@@ -117,10 +104,11 @@ create_database(database_url)

"""Drop database."""
displayed_database = render_url(_db.engine.url)
displayed_database = render_url(current_db.engine.url)
click.secho(f"Destroying database {displayed_database}", fg="red", bold=True)
if _db.engine.name == "sqlite":
plain_url = current_db.engine.url.render_as_string(hide_password=False)
if current_db.engine.name == "sqlite":
try:
drop_database(_db.engine.url)
except FileNotFoundError as e:
drop_database(plain_url)
except FileNotFoundError:
click.secho("Sqlite database has not been initialised", fg="red", bold=True)
else:
drop_database(_db.engine.url)
drop_database(plain_url)

@@ -39,15 +39,13 @@ # -*- coding: utf-8 -*-

script_location = str(importlib_resources.files("invenio_db") / "alembic")
def pathify(base_entry):
return str(
importlib_resources.files(base_entry.module)
/ os.path.join(base_entry.attr)
)
entry_points = importlib_metadata.entry_points(group="invenio_db.alembic")
version_locations = [
(
base_entry.name,
str(
importlib_resources.files(base_entry.module)
/ os.path.join(base_entry.attr)
),
)
for base_entry in importlib_metadata.entry_points(
group="invenio_db.alembic"
)
(base_entry.name, pathify(base_entry)) for base_entry in entry_points
]
script_location = str(importlib_resources.files("invenio_db") / "alembic")
app.config.setdefault(

@@ -54,0 +52,0 @@ "ALEMBIC",

# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 CERN.
# Copyright (C) 2024 Graz University of Technology.
#

@@ -170,2 +171,3 @@ # Invenio is free software; you can redistribute it and/or modify it

"""Entering the context."""
self.session.begin_nested()
return self

@@ -172,0 +174,0 @@

@@ -5,2 +5,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2017-2018 CERN.
# Copyright (C) 2022 Graz University of Technology.
#

@@ -15,10 +16,8 @@ # Invenio is free software; you can redistribute it and/or modify it

from sqlalchemy import inspect
from werkzeug.local import LocalProxy
from .shared import db
from .proxies import current_db
from .shared import db as _db
_db = LocalProxy(lambda: current_app.extensions["sqlalchemy"].db)
def rebuild_encrypted_properties(old_key, model, properties):
def rebuild_encrypted_properties(old_key, model, properties, db=_db):
"""Rebuild model's EncryptedType properties when the SECRET_KEY is changed.

@@ -78,7 +77,7 @@

"""Drop alembic_version table."""
if has_table(_db.engine, "alembic_version"):
alembic_version = _db.Table(
"alembic_version", _db.metadata, autoload_with=_db.engine
if has_table(current_db.engine, "alembic_version"):
alembic_version = current_db.Table(
"alembic_version", current_db.metadata, autoload_with=current_db.engine
)
alembic_version.drop(bind=_db.engine)
alembic_version.drop(bind=current_db.engine)

@@ -85,0 +84,0 @@

Metadata-Version: 2.1
Name: invenio-db
Version: 1.3.1
Version: 2.0.0
Summary: Database management for Invenio.

@@ -39,2 +39,3 @@ Home-page: https://github.com/inveniosoftware/invenio-db

Copyright (C) 2015-2024 CERN.
Copyright (C) 2024 Graz University of Technology.

@@ -47,2 +48,19 @@ Invenio is free software; you can redistribute it and/or modify it

Version v2.0.0 (released 2024-11-19)
- uow: possible solution for the rollback problem
- fix: select of BinaryExpressions
- setup: increase flask-sqlalchemy
- ci: change to reusable workflows
- setup: increase min sqlalchemy dependency
- cli: password is per default hided
- refactor: move MockEntryPoint to independent file
- setup: remove upper pins
- fix: remove warning and black problems
- fix: WeakKeyDictionary
- change: add proxy file
- change: remove click 3 compatibility
- fix: tests LocalProxy
- setup: increase flask-sqlalchemy version
Version v1.3.1 (released 2024-11-14)

@@ -49,0 +67,0 @@

@@ -21,13 +21,14 @@ [metadata]

install_requires =
alembic>=1.10.0,<1.11.0
Flask-Alembic>=2.0.1
Flask-SQLAlchemy>=2.1,<3.0.0
alembic>=1.10.0
Flask-Alembic>=3.0.0
Flask-SQLAlchemy>=3.0
invenio-base>=1.2.10
SQLAlchemy-Continuum>=1.3.12
SQLAlchemy-Utils>=0.33.1,<0.39
SQLAlchemy[asyncio]>=1.2.18,<1.5.0
SQLAlchemy-Utils>=0.33.1
SQLAlchemy[asyncio]>=2.0.0
[options.extras_require]
tests =
pytest-black>=0.3.0
six>=1.0.0
pytest-black-ng>=0.4.0
cryptography>=2.1.4

@@ -60,3 +61,3 @@ pytest-invenio>=1.4.5

[pydocstyle]
add_ignore = D401
add_ignore = D401, D202

@@ -63,0 +64,0 @@ [isort]

@@ -20,4 +20,4 @@ # -*- coding: utf-8 -*-

@pytest.fixture()
def db():
@pytest.fixture(name="db")
def fixture_db():
"""Database fixture with session sharing."""

@@ -24,0 +24,0 @@ import invenio_db

@@ -6,2 +6,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2022 RERO.
# Copyright (C) 2024 Graz University of Technology.
#

@@ -18,3 +19,3 @@ # Invenio is free software; you can redistribute it and/or modify it

from flask import Flask
from importlib_metadata import EntryPoint
from mocks import _mock_entry_points
from sqlalchemy import inspect

@@ -24,47 +25,9 @@ from sqlalchemy.exc import IntegrityError

from sqlalchemy_utils.functions import create_database, drop_database
from werkzeug.utils import import_string
from invenio_db import InvenioDB, shared
from invenio_db import InvenioDB
from invenio_db.cli import db as db_cmd
from invenio_db.shared import NAMING_CONVENTION, MetaData, SQLAlchemy
from invenio_db.utils import drop_alembic_version_table, has_table
class MockEntryPoint(EntryPoint):
"""Mocking of entrypoint."""
def load(self):
"""Mock load entry point."""
if self.name == "importfail":
raise ImportError()
else:
return import_string(self.name)
def _mock_entry_points(name):
def fn(group):
data = {
"invenio_db.models": [
MockEntryPoint(name="demo.child", value="demo.child", group="test"),
MockEntryPoint(name="demo.parent", value="demo.parent", group="test"),
],
"invenio_db.models_a": [
MockEntryPoint(
name="demo.versioned_a", value="demo.versioned_a", group="test"
),
],
"invenio_db.models_b": [
MockEntryPoint(
name="demo.versioned_b", value="demo.versioned_b", group="test"
),
],
}
if group:
return data.get(group, [])
if name:
return {name: data.get(name)}
return data
return fn
def test_init(db, app):

@@ -105,4 +68,4 @@ """Test extension initialization."""

with app.app_context():
Demo2.query.delete()
Demo.query.delete()
db.session.query(Demo2).delete()
db.session.query(Demo).delete()
db.session.commit()

@@ -127,5 +90,4 @@

"""Test naming convention."""
from sqlalchemy_continuum import remove_versioning
ext = InvenioDB(app, entry_point_group=False, db=db)
InvenioDB(app, entry_point_group=False, db=db)
cfg = dict(

@@ -166,4 +128,4 @@ DB_VERSIONING=True,

source_db = shared.SQLAlchemy(
metadata=shared.MetaData(
source_db = SQLAlchemy(
metadata=MetaData(
naming_convention={

@@ -206,5 +168,3 @@ "ix": "source_ix_%(table_name)s_%(column_0_label)s",

target_db = shared.SQLAlchemy(
metadata=shared.MetaData(naming_convention=shared.NAMING_CONVENTION)
)
target_db = SQLAlchemy(metadata=MetaData(naming_convention=NAMING_CONVENTION))
target_app = Flask("target_app")

@@ -230,3 +190,3 @@ target_app.config.update(**cfg)

cns.name
for model in source_models
for model in target_models
for cns in list(model.__table__.constraints)

@@ -313,2 +273,5 @@ + list(model.__table__.indexes)

result = runner.invoke(db_cmd, ["init"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["destroy", "--yes-i-know"])

@@ -323,2 +286,17 @@ assert result.exit_code == 0

result = runner.invoke(db_cmd, ["destroy", "--yes-i-know"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["init"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["create", "-v"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["create", "-v"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["drop", "-v", "--yes-i-know"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["drop"])

@@ -334,6 +312,9 @@ assert result.exit_code == 1

result = runner.invoke(db_cmd, ["drop", "--yes-i-know", "create"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["destroy", "--yes-i-know"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["destroy"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["init"])
assert result.exit_code == 0

@@ -346,7 +327,20 @@ result = runner.invoke(db_cmd, ["destroy", "--yes-i-know"])

result = runner.invoke(db_cmd, ["destroy", "--yes-i-know"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["init"])
assert result.exit_code == 0
result = runner.invoke(db_cmd, ["drop", "-v", "--yes-i-know"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["create", "-v"])
assert result.exit_code == 1
result = runner.invoke(db_cmd, ["drop", "-v", "--yes-i-know"])
assert result.exit_code == 0
def test_local_proxy(app, db):
"""Test local proxy filter."""
from werkzeug.local import LocalProxy
InvenioDB(app, db=db)

@@ -356,3 +350,3 @@

query = db.select(
[
*[
db.literal("hello") != db.bindparam("a"),

@@ -364,8 +358,10 @@ db.literal(0) <= db.bindparam("x"),

)
result = db.engine.execute(
result = db.session.execute(
query,
a=LocalProxy(lambda: "world"),
x=LocalProxy(lambda: 1),
y=LocalProxy(lambda: "2"),
z=LocalProxy(lambda: None),
{
"a": "world",
"x": 1,
"y": "2",
"z": None,
},
).fetchone()

@@ -389,2 +385,3 @@ assert result == (True, True, True, True)

raise pytest.skip("Upgrades are not supported on SQLite.")
db.drop_all()

@@ -398,2 +395,3 @@ runner = app.test_cli_runner()

assert ext.alembic.migration_context._has_version_table()
# Note that compare_metadata does not detect additional sequences

@@ -404,2 +402,3 @@ # and constraints.

assert not ext.alembic.compare_metadata()
ext.alembic.upgrade()

@@ -424,4 +423,4 @@ assert has_table(db.engine, "transaction")

finally:
drop_database(str(db.engine.url))
drop_database(str(db.engine.url.render_as_string(hide_password=False)))
remove_versioning(manager=ext.versioning_manager)
create_database(str(db.engine.url))
create_database(str(db.engine.url.render_as_string(hide_password=False)))

@@ -5,2 +5,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2017-2018 CERN.
# Copyright (C) 2023 Graz University of Technology.
#

@@ -15,3 +16,3 @@ # Invenio is free software; you can redistribute it and/or modify it

from sqlalchemy_continuum import remove_versioning
from sqlalchemy_utils.types import EncryptedType
from sqlalchemy_utils.types import StringEncryptedType

@@ -38,3 +39,4 @@ from invenio_db import InvenioDB

et = db.Column(
EncryptedType(type_in=db.Unicode, key=_secret_key), nullable=False
StringEncryptedType(length=255, type_in=db.Unicode, key=_secret_key),
nullable=False,
)

@@ -56,3 +58,3 @@

with pytest.raises(AttributeError):
rebuild_encrypted_properties(old_secret_key, Demo, ["nonexistent"])
rebuild_encrypted_properties(old_secret_key, Demo, ["nonexistent"], db)
assert app.secret_key == new_secret_key

@@ -63,3 +65,3 @@

db.session.query(Demo).all()
rebuild_encrypted_properties(old_secret_key, Demo, ["et"])
rebuild_encrypted_properties(old_secret_key, Demo, ["et"], db)
d1_after = db.session.query(Demo).first()

@@ -66,0 +68,0 @@ assert d1_after.et == "something"

@@ -6,2 +6,3 @@ # -*- coding: utf-8 -*-

# Copyright (C) 2022 RERO.
# Copyright (C) 2024 Graz University of Technology.
#

@@ -16,4 +17,4 @@ # Invenio is free software; you can redistribute it and/or modify it

import pytest
from mocks import _mock_entry_points
from sqlalchemy_continuum import VersioningManager, remove_versioning
from test_db import _mock_entry_points

@@ -37,2 +38,4 @@ from invenio_db import InvenioDB

# this class has to be defined here, because the the db has to be the db
# from the fixture. using it "from invenio_db import db" is not working
class EarlyClass(db.Model):

@@ -51,3 +54,2 @@ __versioned__ = {}

before = len(db.metadata.tables)
ec = EarlyClass()

@@ -54,0 +56,0 @@ ec.pk = 1