diracx-db 0.0.1a49__py3-none-any.whl → 0.0.2__py3-none-any.whl
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.
- diracx/db/__main__.py +1 -0
 - diracx/db/sql/auth/db.py +69 -2
 - diracx/db/sql/auth/schema.py +6 -2
 - diracx/db/sql/utils/__init__.py +15 -11
 - diracx/db/sql/utils/base.py +38 -1
 - {diracx_db-0.0.1a49.dist-info → diracx_db-0.0.2.dist-info}/METADATA +4 -1
 - {diracx_db-0.0.1a49.dist-info → diracx_db-0.0.2.dist-info}/RECORD +9 -9
 - {diracx_db-0.0.1a49.dist-info → diracx_db-0.0.2.dist-info}/WHEEL +0 -0
 - {diracx_db-0.0.1a49.dist-info → diracx_db-0.0.2.dist-info}/entry_points.txt +0 -0
 
    
        diracx/db/__main__.py
    CHANGED
    
    
    
        diracx/db/sql/auth/db.py
    CHANGED
    
    | 
         @@ -1,16 +1,21 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            import logging
         
     | 
| 
       3 
4 
     | 
    
         
             
            import secrets
         
     | 
| 
      
 5 
     | 
    
         
            +
            from datetime import UTC, datetime
         
     | 
| 
      
 6 
     | 
    
         
            +
            from itertools import pairwise
         
     | 
| 
       4 
7 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            from  
     | 
| 
      
 8 
     | 
    
         
            +
            from dateutil.rrule import MONTHLY, rrule
         
     | 
| 
      
 9 
     | 
    
         
            +
            from sqlalchemy import insert, select, text, update
         
     | 
| 
       6 
10 
     | 
    
         
             
            from sqlalchemy.exc import IntegrityError, NoResultFound
         
     | 
| 
      
 11 
     | 
    
         
            +
            from sqlalchemy.ext.asyncio import AsyncConnection
         
     | 
| 
       7 
12 
     | 
    
         
             
            from uuid_utils import UUID, uuid7
         
     | 
| 
       8 
13 
     | 
    
         | 
| 
       9 
14 
     | 
    
         
             
            from diracx.core.exceptions import (
         
     | 
| 
       10 
15 
     | 
    
         
             
                AuthorizationError,
         
     | 
| 
       11 
16 
     | 
    
         
             
                TokenNotFoundError,
         
     | 
| 
       12 
17 
     | 
    
         
             
            )
         
     | 
| 
       13 
     | 
    
         
            -
            from diracx.db.sql.utils import BaseSQLDB, hash, substract_date
         
     | 
| 
      
 18 
     | 
    
         
            +
            from diracx.db.sql.utils import BaseSQLDB, hash, substract_date, uuid7_from_datetime
         
     | 
| 
       14 
19 
     | 
    
         | 
| 
       15 
20 
     | 
    
         
             
            from .schema import (
         
     | 
| 
       16 
21 
     | 
    
         
             
                AuthorizationFlows,
         
     | 
| 
         @@ -25,10 +30,72 @@ from .schema import Base as AuthDBBase 
     | 
|
| 
       25 
30 
     | 
    
         
             
            USER_CODE_ALPHABET = "BCDFGHJKLMNPQRSTVWXZ"
         
     | 
| 
       26 
31 
     | 
    
         
             
            MAX_RETRY = 5
         
     | 
| 
       27 
32 
     | 
    
         | 
| 
      
 33 
     | 
    
         
            +
            logger = logging.getLogger(__name__)
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
       28 
35 
     | 
    
         | 
| 
       29 
36 
     | 
    
         
             
            class AuthDB(BaseSQLDB):
         
     | 
| 
       30 
37 
     | 
    
         
             
                metadata = AuthDBBase.metadata
         
     | 
| 
       31 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 40 
     | 
    
         
            +
                async def post_create(cls, conn: AsyncConnection) -> None:
         
     | 
| 
      
 41 
     | 
    
         
            +
                    """Create partitions if it is a MySQL DB and it does not have
         
     | 
| 
      
 42 
     | 
    
         
            +
                    it yet and the table does not have any data yet.
         
     | 
| 
      
 43 
     | 
    
         
            +
                    We do this as a post_create step as sqlalchemy does not support
         
     | 
| 
      
 44 
     | 
    
         
            +
                    partition so well.
         
     | 
| 
      
 45 
     | 
    
         
            +
                    """
         
     | 
| 
      
 46 
     | 
    
         
            +
                    if conn.dialect.name == "mysql":
         
     | 
| 
      
 47 
     | 
    
         
            +
                        check_partition_query = text(
         
     | 
| 
      
 48 
     | 
    
         
            +
                            "SELECT PARTITION_NAME FROM information_schema.partitions "
         
     | 
| 
      
 49 
     | 
    
         
            +
                            "WHERE TABLE_NAME = 'RefreshTokens' AND PARTITION_NAME is not NULL"
         
     | 
| 
      
 50 
     | 
    
         
            +
                        )
         
     | 
| 
      
 51 
     | 
    
         
            +
                        partition_names = (await conn.execute(check_partition_query)).all()
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                        if not partition_names:
         
     | 
| 
      
 54 
     | 
    
         
            +
                            # Create a monthly partition from today until 2 years
         
     | 
| 
      
 55 
     | 
    
         
            +
                            # The partition are named p_<year>_<month>
         
     | 
| 
      
 56 
     | 
    
         
            +
                            start_date = datetime.now(tz=UTC).replace(
         
     | 
| 
      
 57 
     | 
    
         
            +
                                day=1, hour=0, minute=0, second=0, microsecond=0
         
     | 
| 
      
 58 
     | 
    
         
            +
                            )
         
     | 
| 
      
 59 
     | 
    
         
            +
                            end_date = start_date.replace(year=start_date.year + 2)
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                            dates = [
         
     | 
| 
      
 62 
     | 
    
         
            +
                                dt for dt in rrule(MONTHLY, dtstart=start_date, until=end_date)
         
     | 
| 
      
 63 
     | 
    
         
            +
                            ]
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                            partition_list = []
         
     | 
| 
      
 66 
     | 
    
         
            +
                            for name, limit in pairwise(dates):
         
     | 
| 
      
 67 
     | 
    
         
            +
                                partition_list.append(
         
     | 
| 
      
 68 
     | 
    
         
            +
                                    f"PARTITION p_{name.year}_{name.month} "
         
     | 
| 
      
 69 
     | 
    
         
            +
                                    f"VALUES LESS THAN ('{str(uuid7_from_datetime(limit, randomize=False)).replace('-', '')}')"
         
     | 
| 
      
 70 
     | 
    
         
            +
                                )
         
     | 
| 
      
 71 
     | 
    
         
            +
                            partition_list.append("PARTITION p_future VALUES LESS THAN (MAXVALUE)")
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                            alter_query = text(
         
     | 
| 
      
 74 
     | 
    
         
            +
                                f"ALTER TABLE RefreshTokens PARTITION BY RANGE COLUMNS (JTI) ({','.join(partition_list)})"
         
     | 
| 
      
 75 
     | 
    
         
            +
                            )
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                            check_table_empty_query = text("SELECT * FROM RefreshTokens LIMIT 1")
         
     | 
| 
      
 78 
     | 
    
         
            +
                            refresh_table_content = (
         
     | 
| 
      
 79 
     | 
    
         
            +
                                await conn.execute(check_table_empty_query)
         
     | 
| 
      
 80 
     | 
    
         
            +
                            ).all()
         
     | 
| 
      
 81 
     | 
    
         
            +
                            if refresh_table_content:
         
     | 
| 
      
 82 
     | 
    
         
            +
                                logger.warning(
         
     | 
| 
      
 83 
     | 
    
         
            +
                                    "RefreshTokens table not empty. Run the following query yourself"
         
     | 
| 
      
 84 
     | 
    
         
            +
                                )
         
     | 
| 
      
 85 
     | 
    
         
            +
                                logger.warning(alter_query)
         
     | 
| 
      
 86 
     | 
    
         
            +
                                return
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                            await conn.execute(alter_query)
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                            partition_names = (
         
     | 
| 
      
 91 
     | 
    
         
            +
                                await conn.execute(
         
     | 
| 
      
 92 
     | 
    
         
            +
                                    check_partition_query, {"table_name": "RefreshTokens"}
         
     | 
| 
      
 93 
     | 
    
         
            +
                                )
         
     | 
| 
      
 94 
     | 
    
         
            +
                            ).all()
         
     | 
| 
      
 95 
     | 
    
         
            +
                            assert partition_names, (
         
     | 
| 
      
 96 
     | 
    
         
            +
                                f"There should be partitions now {partition_names}"
         
     | 
| 
      
 97 
     | 
    
         
            +
                            )
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
       32 
99 
     | 
    
         
             
                async def device_flow_validate_user_code(
         
     | 
| 
       33 
100 
     | 
    
         
             
                    self, user_code: str, max_validity: int
         
     | 
| 
       34 
101 
     | 
    
         
             
                ) -> str:
         
     | 
    
        diracx/db/sql/auth/schema.py
    CHANGED
    
    | 
         @@ -10,7 +10,12 @@ from sqlalchemy import ( 
     | 
|
| 
       10 
10 
     | 
    
         
             
            )
         
     | 
| 
       11 
11 
     | 
    
         
             
            from sqlalchemy.orm import declarative_base
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
            from diracx.db.sql.utils import  
     | 
| 
      
 13 
     | 
    
         
            +
            from diracx.db.sql.utils import (
         
     | 
| 
      
 14 
     | 
    
         
            +
                Column,
         
     | 
| 
      
 15 
     | 
    
         
            +
                DateNowColumn,
         
     | 
| 
      
 16 
     | 
    
         
            +
                EnumColumn,
         
     | 
| 
      
 17 
     | 
    
         
            +
                NullColumn,
         
     | 
| 
      
 18 
     | 
    
         
            +
            )
         
     | 
| 
       14 
19 
     | 
    
         | 
| 
       15 
20 
     | 
    
         
             
            USER_CODE_LENGTH = 8
         
     | 
| 
       16 
21 
     | 
    
         | 
| 
         @@ -92,7 +97,6 @@ class RefreshTokens(Base): 
     | 
|
| 
       92 
97 
     | 
    
         
             
                status = EnumColumn(
         
     | 
| 
       93 
98 
     | 
    
         
             
                    "Status", RefreshTokenStatus, server_default=RefreshTokenStatus.CREATED.name
         
     | 
| 
       94 
99 
     | 
    
         
             
                )
         
     | 
| 
       95 
     | 
    
         
            -
                creation_time = DateNowColumn("CreationTime", index=True)
         
     | 
| 
       96 
100 
     | 
    
         
             
                scope = Column("Scope", String(1024))
         
     | 
| 
       97 
101 
     | 
    
         | 
| 
       98 
102 
     | 
    
         
             
                # User attributes bound to the refresh token
         
     | 
    
        diracx/db/sql/utils/__init__.py
    CHANGED
    
    | 
         @@ -1,16 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
                BaseSQLDB,
         
     | 
| 
       5 
     | 
    
         
            -
                SQLDBUnavailableError,
         
     | 
| 
       6 
     | 
    
         
            -
                _get_columns,
         
     | 
| 
       7 
     | 
    
         
            -
                apply_search_filters,
         
     | 
| 
       8 
     | 
    
         
            -
                apply_sort_constraints,
         
     | 
| 
       9 
     | 
    
         
            -
            )
         
     | 
| 
       10 
     | 
    
         
            -
            from .functions import hash, substract_date, utcnow
         
     | 
| 
       11 
     | 
    
         
            -
            from .types import Column, DateNowColumn, EnumBackedBool, EnumColumn, NullColumn
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
            __all__ = (
         
     | 
| 
      
 3 
     | 
    
         
            +
            __all__ = [
         
     | 
| 
       14 
4 
     | 
    
         
             
                "_get_columns",
         
     | 
| 
       15 
5 
     | 
    
         
             
                "utcnow",
         
     | 
| 
       16 
6 
     | 
    
         
             
                "Column",
         
     | 
| 
         @@ -24,4 +14,18 @@ __all__ = ( 
     | 
|
| 
       24 
14 
     | 
    
         
             
                "substract_date",
         
     | 
| 
       25 
15 
     | 
    
         
             
                "hash",
         
     | 
| 
       26 
16 
     | 
    
         
             
                "SQLDBUnavailableError",
         
     | 
| 
      
 17 
     | 
    
         
            +
                "uuid7_from_datetime",
         
     | 
| 
      
 18 
     | 
    
         
            +
                "uuid7_to_datetime",
         
     | 
| 
      
 19 
     | 
    
         
            +
            ]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            from .base import (
         
     | 
| 
      
 22 
     | 
    
         
            +
                BaseSQLDB,
         
     | 
| 
      
 23 
     | 
    
         
            +
                SQLDBUnavailableError,
         
     | 
| 
      
 24 
     | 
    
         
            +
                _get_columns,
         
     | 
| 
      
 25 
     | 
    
         
            +
                apply_search_filters,
         
     | 
| 
      
 26 
     | 
    
         
            +
                apply_sort_constraints,
         
     | 
| 
      
 27 
     | 
    
         
            +
                uuid7_from_datetime,
         
     | 
| 
      
 28 
     | 
    
         
            +
                uuid7_to_datetime,
         
     | 
| 
       27 
29 
     | 
    
         
             
            )
         
     | 
| 
      
 30 
     | 
    
         
            +
            from .functions import hash, substract_date, utcnow
         
     | 
| 
      
 31 
     | 
    
         
            +
            from .types import Column, DateNowColumn, EnumBackedBool, EnumColumn, NullColumn
         
     | 
    
        diracx/db/sql/utils/base.py
    CHANGED
    
    | 
         @@ -7,13 +7,15 @@ import re 
     | 
|
| 
       7 
7 
     | 
    
         
             
            from abc import ABCMeta
         
     | 
| 
       8 
8 
     | 
    
         
             
            from collections.abc import AsyncIterator
         
     | 
| 
       9 
9 
     | 
    
         
             
            from contextvars import ContextVar
         
     | 
| 
       10 
     | 
    
         
            -
            from datetime import datetime
         
     | 
| 
      
 10 
     | 
    
         
            +
            from datetime import datetime, timezone
         
     | 
| 
       11 
11 
     | 
    
         
             
            from typing import Any, Self, cast
         
     | 
| 
      
 12 
     | 
    
         
            +
            from uuid import UUID as StdUUID  # noqa: N811
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
            from pydantic import TypeAdapter
         
     | 
| 
       14 
15 
     | 
    
         
             
            from sqlalchemy import DateTime, MetaData, func, select
         
     | 
| 
       15 
16 
     | 
    
         
             
            from sqlalchemy.exc import OperationalError
         
     | 
| 
       16 
17 
     | 
    
         
             
            from sqlalchemy.ext.asyncio import AsyncConnection, AsyncEngine, create_async_engine
         
     | 
| 
      
 18 
     | 
    
         
            +
            from uuid_utils import UUID, uuid7
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
20 
     | 
    
         
             
            from diracx.core.exceptions import InvalidQueryError
         
     | 
| 
       19 
21 
     | 
    
         
             
            from diracx.core.extensions import select_from_extension
         
     | 
| 
         @@ -153,6 +155,11 @@ class BaseSQLDB(metaclass=ABCMeta): 
     | 
|
| 
       153 
155 
     | 
    
         
             
                                raise
         
     | 
| 
       154 
156 
     | 
    
         
             
                    return db_urls
         
     | 
| 
       155 
157 
     | 
    
         | 
| 
      
 158 
     | 
    
         
            +
                @classmethod
         
     | 
| 
      
 159 
     | 
    
         
            +
                async def post_create(cls, conn: AsyncConnection) -> None:
         
     | 
| 
      
 160 
     | 
    
         
            +
                    """Execute actions after the schema has been created."""
         
     | 
| 
      
 161 
     | 
    
         
            +
                    return
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
       156 
163 
     | 
    
         
             
                @classmethod
         
     | 
| 
       157 
164 
     | 
    
         
             
                def transaction(cls) -> Self:
         
     | 
| 
       158 
165 
     | 
    
         
             
                    raise NotImplementedError("This should never be called")
         
     | 
| 
         @@ -416,3 +423,33 @@ def apply_sort_constraints(column_mapping, stmt, sorts): 
     | 
|
| 
       416 
423 
     | 
    
         
             
                if sort_columns:
         
     | 
| 
       417 
424 
     | 
    
         
             
                    stmt = stmt.order_by(*sort_columns)
         
     | 
| 
       418 
425 
     | 
    
         
             
                return stmt
         
     | 
| 
      
 426 
     | 
    
         
            +
             
     | 
| 
      
 427 
     | 
    
         
            +
             
     | 
| 
      
 428 
     | 
    
         
            +
            def uuid7_to_datetime(uuid: UUID | StdUUID | str) -> datetime:
         
     | 
| 
      
 429 
     | 
    
         
            +
                """Convert a UUIDv7 to a datetime."""
         
     | 
| 
      
 430 
     | 
    
         
            +
                if isinstance(uuid, StdUUID):
         
     | 
| 
      
 431 
     | 
    
         
            +
                    # Convert stdlib UUID to uuid_utils.UUID
         
     | 
| 
      
 432 
     | 
    
         
            +
                    uuid = UUID(str(uuid))
         
     | 
| 
      
 433 
     | 
    
         
            +
                elif not isinstance(uuid, UUID):
         
     | 
| 
      
 434 
     | 
    
         
            +
                    # Convert string or other types to uuid_utils.UUID
         
     | 
| 
      
 435 
     | 
    
         
            +
                    uuid = UUID(uuid)
         
     | 
| 
      
 436 
     | 
    
         
            +
                if uuid.version != 7:
         
     | 
| 
      
 437 
     | 
    
         
            +
                    raise ValueError(f"UUID {uuid} is not a UUIDv7")
         
     | 
| 
      
 438 
     | 
    
         
            +
                return datetime.fromtimestamp(uuid.timestamp / 1000.0, tz=timezone.utc)
         
     | 
| 
      
 439 
     | 
    
         
            +
             
     | 
| 
      
 440 
     | 
    
         
            +
             
     | 
| 
      
 441 
     | 
    
         
            +
            def uuid7_from_datetime(dt: datetime, *, randomize: bool = True) -> UUID:
         
     | 
| 
      
 442 
     | 
    
         
            +
                """Generate a UUIDv7 corresponding to the given datetime.
         
     | 
| 
      
 443 
     | 
    
         
            +
             
     | 
| 
      
 444 
     | 
    
         
            +
                If randomize is True, the standard uuid7 function is used resulting in the
         
     | 
| 
      
 445 
     | 
    
         
            +
                lowest 62-bits being random. If randomize is False, the UUIDv7 will be the
         
     | 
| 
      
 446 
     | 
    
         
            +
                lowest possible UUIDv7 for the given datetime.
         
     | 
| 
      
 447 
     | 
    
         
            +
                """
         
     | 
| 
      
 448 
     | 
    
         
            +
                timestamp = dt.timestamp()
         
     | 
| 
      
 449 
     | 
    
         
            +
                if randomize:
         
     | 
| 
      
 450 
     | 
    
         
            +
                    uuid = uuid7(int(timestamp), int((timestamp % 1) * 1e9))
         
     | 
| 
      
 451 
     | 
    
         
            +
                else:
         
     | 
| 
      
 452 
     | 
    
         
            +
                    time_high = int(timestamp * 1000) >> 16
         
     | 
| 
      
 453 
     | 
    
         
            +
                    time_low = int(timestamp * 1000) & 0xFFFF
         
     | 
| 
      
 454 
     | 
    
         
            +
                    uuid = UUID.from_fields((time_high, time_low, 0x7000, 0x80, 0, 0))
         
     | 
| 
      
 455 
     | 
    
         
            +
                return uuid
         
     | 
| 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            Metadata-Version: 2.4
         
     | 
| 
       2 
2 
     | 
    
         
             
            Name: diracx-db
         
     | 
| 
       3 
     | 
    
         
            -
            Version: 0.0. 
     | 
| 
      
 3 
     | 
    
         
            +
            Version: 0.0.2
         
     | 
| 
       4 
4 
     | 
    
         
             
            Summary: TODO
         
     | 
| 
       5 
5 
     | 
    
         
             
            License: GPL-3.0-only
         
     | 
| 
       6 
6 
     | 
    
         
             
            Classifier: Intended Audience :: Science/Research
         
     | 
| 
         @@ -12,8 +12,11 @@ Requires-Python: >=3.11 
     | 
|
| 
       12 
12 
     | 
    
         
             
            Requires-Dist: diracx-core
         
     | 
| 
       13 
13 
     | 
    
         
             
            Requires-Dist: opensearch-py[async]
         
     | 
| 
       14 
14 
     | 
    
         
             
            Requires-Dist: pydantic>=2.10
         
     | 
| 
      
 15 
     | 
    
         
            +
            Requires-Dist: python-dateutil
         
     | 
| 
       15 
16 
     | 
    
         
             
            Requires-Dist: sqlalchemy[aiomysql,aiosqlite]>=2
         
     | 
| 
       16 
17 
     | 
    
         
             
            Requires-Dist: uuid-utils
         
     | 
| 
       17 
18 
     | 
    
         
             
            Provides-Extra: testing
         
     | 
| 
       18 
19 
     | 
    
         
             
            Requires-Dist: diracx-testing; extra == 'testing'
         
     | 
| 
       19 
20 
     | 
    
         
             
            Requires-Dist: freezegun; extra == 'testing'
         
     | 
| 
      
 21 
     | 
    
         
            +
            Provides-Extra: types
         
     | 
| 
      
 22 
     | 
    
         
            +
            Requires-Dist: types-python-dateutil; extra == 'types'
         
     | 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            diracx/db/__init__.py,sha256=2oeUeVwZq53bo_ZOflEYZsBn7tcR5Tzb2AIu0TAWELM,109
         
     | 
| 
       2 
     | 
    
         
            -
            diracx/db/__main__.py,sha256= 
     | 
| 
      
 2 
     | 
    
         
            +
            diracx/db/__main__.py,sha256=6YlmpiU1cLLHjKLy1DfdEOQUyvSla-MbJsJ7aQwAOVs,1757
         
     | 
| 
       3 
3 
     | 
    
         
             
            diracx/db/exceptions.py,sha256=1nn-SZLG-nQwkxbvHjZqXhE5ouzWj1f3qhSda2B4ZEg,83
         
     | 
| 
       4 
4 
     | 
    
         
             
            diracx/db/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
       5 
5 
     | 
    
         
             
            diracx/db/os/__init__.py,sha256=IZr6z6SefrRvuC8sTC4RmB3_wwOyEt1GzpDuwSMH8O4,112
         
     | 
| 
         @@ -7,8 +7,8 @@ diracx/db/os/job_parameters.py,sha256=3w_CeA2z-cY5pWwXkGu-Fod27FobbUXuwVKK-jN037 
     | 
|
| 
       7 
7 
     | 
    
         
             
            diracx/db/os/utils.py,sha256=V4T-taos64SFNcorfIr7mq5l5y88K6TzyCj1YqWk8VI,11562
         
     | 
| 
       8 
8 
     | 
    
         
             
            diracx/db/sql/__init__.py,sha256=JYu0b0IVhoXy3lX2m2r2dmAjsRS7IbECBUMEDvX0Te4,391
         
     | 
| 
       9 
9 
     | 
    
         
             
            diracx/db/sql/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
       10 
     | 
    
         
            -
            diracx/db/sql/auth/db.py,sha256= 
     | 
| 
       11 
     | 
    
         
            -
            diracx/db/sql/auth/schema.py,sha256= 
     | 
| 
      
 10 
     | 
    
         
            +
            diracx/db/sql/auth/db.py,sha256=sGXKFLy1iCdrkg1952_F-c7nRSIx4F1JuDloIV6AXN8,11814
         
     | 
| 
      
 11 
     | 
    
         
            +
            diracx/db/sql/auth/schema.py,sha256=9fUV7taDPnoAcoiwRAmQraOmF2Ytoizjs2TFvN7zsVs,3132
         
     | 
| 
       12 
12 
     | 
    
         
             
            diracx/db/sql/dummy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
       13 
13 
     | 
    
         
             
            diracx/db/sql/dummy/db.py,sha256=MKSUSJI1BlRgK08tjCfkCkOz02asvJAeBw60pAdiGV8,1212
         
     | 
| 
       14 
14 
     | 
    
         
             
            diracx/db/sql/dummy/schema.py,sha256=9zI53pKlzc6qBezsyjkatOQrNZdGCjwgjQ8Iz_pyAXs,789
         
     | 
| 
         @@ -27,11 +27,11 @@ diracx/db/sql/sandbox_metadata/schema.py,sha256=V5gV2PHwzTbBz_th9ribLfE7Lqk8YGem 
     | 
|
| 
       27 
27 
     | 
    
         
             
            diracx/db/sql/task_queue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         
     | 
| 
       28 
28 
     | 
    
         
             
            diracx/db/sql/task_queue/db.py,sha256=2qul1D2tX2uCI92N591WK5xWHakG0pNibzDwKQ7W-I8,6246
         
     | 
| 
       29 
29 
     | 
    
         
             
            diracx/db/sql/task_queue/schema.py,sha256=5efAgvNYRkLlaJ2NzRInRfmVa3tyIzQu2l0oRPy4Kzw,3258
         
     | 
| 
       30 
     | 
    
         
            -
            diracx/db/sql/utils/__init__.py,sha256= 
     | 
| 
       31 
     | 
    
         
            -
            diracx/db/sql/utils/base.py,sha256= 
     | 
| 
      
 30 
     | 
    
         
            +
            diracx/db/sql/utils/__init__.py,sha256=k1DI4Idlqv36pXn2BhQysb947Peio9DnYaePslkTpUQ,685
         
     | 
| 
      
 31 
     | 
    
         
            +
            diracx/db/sql/utils/base.py,sha256=cXwAzWtYtEkukjHSBGaGNtXSozHfXHpZ9p9eXdQTpDY,17065
         
     | 
| 
       32 
32 
     | 
    
         
             
            diracx/db/sql/utils/functions.py,sha256=_E4tc9Gti6LuSh7QEyoqPJSvCuByVqvRenOXCzxsulE,4014
         
     | 
| 
       33 
33 
     | 
    
         
             
            diracx/db/sql/utils/types.py,sha256=KNZWJfpvHTjfIPg6Nn7zY-rS0q3ybnirHcTcLAYSYbE,5118
         
     | 
| 
       34 
     | 
    
         
            -
            diracx_db-0.0. 
     | 
| 
       35 
     | 
    
         
            -
            diracx_db-0.0. 
     | 
| 
       36 
     | 
    
         
            -
            diracx_db-0.0. 
     | 
| 
       37 
     | 
    
         
            -
            diracx_db-0.0. 
     | 
| 
      
 34 
     | 
    
         
            +
            diracx_db-0.0.2.dist-info/METADATA,sha256=n8QuMXRrA6-iLKw14y29Jj2WxBzQZ2plW5qMngBnEqs,780
         
     | 
| 
      
 35 
     | 
    
         
            +
            diracx_db-0.0.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
         
     | 
| 
      
 36 
     | 
    
         
            +
            diracx_db-0.0.2.dist-info/entry_points.txt,sha256=UPqhLvb9gui0kOyWeI_edtefcrHToZmQt1p76vIwujo,317
         
     | 
| 
      
 37 
     | 
    
         
            +
            diracx_db-0.0.2.dist-info/RECORD,,
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     |