tokenator 0.1.0__tar.gz → 0.1.2__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.
- {tokenator-0.1.0 → tokenator-0.1.2}/PKG-INFO +1 -1
- {tokenator-0.1.0 → tokenator-0.1.2}/pyproject.toml +1 -1
- tokenator-0.1.2/src/tokenator/migrations.py +38 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/schemas.py +7 -1
- tokenator-0.1.2/src/tokenator/utils.py +49 -0
- tokenator-0.1.0/src/tokenator/migrations.py +0 -40
- tokenator-0.1.0/src/tokenator/utils.py +0 -35
- {tokenator-0.1.0 → tokenator-0.1.2}/LICENSE +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/README.md +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/__init__.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/base_wrapper.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/client_anthropic.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/client_openai.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/create_migrations.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/migrations/env.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/migrations/script.py.mako +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/models.py +0 -0
- {tokenator-0.1.0 → tokenator-0.1.2}/src/tokenator/usage.py +0 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
"""Automatic database migrations manager."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
import logging
|
5
|
+
from pathlib import Path
|
6
|
+
from alembic import command
|
7
|
+
from alembic.config import Config
|
8
|
+
from alembic.runtime.migration import MigrationContext
|
9
|
+
from sqlalchemy import create_engine
|
10
|
+
|
11
|
+
from .utils import get_default_db_path
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
def check_and_run_migrations():
|
16
|
+
"""Check and run any pending database migrations."""
|
17
|
+
try:
|
18
|
+
db_path = get_default_db_path()
|
19
|
+
engine = create_engine(f"sqlite:///{db_path}")
|
20
|
+
|
21
|
+
# Create migrations table if it doesn't exist
|
22
|
+
with engine.connect() as conn:
|
23
|
+
context = MigrationContext.configure(conn)
|
24
|
+
current_rev = context.get_current_revision()
|
25
|
+
|
26
|
+
if current_rev is None:
|
27
|
+
# Run migrations
|
28
|
+
config = Config()
|
29
|
+
migrations_dir = os.path.join(os.path.dirname(__file__), "migrations")
|
30
|
+
config.set_main_option("script_location", migrations_dir)
|
31
|
+
config.set_main_option("sqlalchemy.url", f"sqlite:///{db_path}")
|
32
|
+
|
33
|
+
command.upgrade(config, "head")
|
34
|
+
logger.info("Database migrations completed successfully")
|
35
|
+
except Exception as e:
|
36
|
+
logger.error(f"Failed to run migrations: {e}")
|
37
|
+
# Don't raise the exception - allow the application to continue
|
38
|
+
# The user can manually initialize the DB later if needed
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
import uuid
|
4
4
|
from datetime import datetime
|
5
|
+
import os
|
5
6
|
|
6
7
|
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Float, Index
|
7
8
|
from sqlalchemy.orm import sessionmaker, scoped_session, declarative_base
|
@@ -12,7 +13,12 @@ Base = declarative_base()
|
|
12
13
|
|
13
14
|
def get_engine(db_path: str = None):
|
14
15
|
"""Create SQLAlchemy engine with the given database path."""
|
15
|
-
|
16
|
+
if db_path is None:
|
17
|
+
try:
|
18
|
+
import google.colab # type: ignore
|
19
|
+
db_path = '/content/tokenator.db'
|
20
|
+
except ImportError:
|
21
|
+
db_path = get_default_db_path()
|
16
22
|
return create_engine(f"sqlite:///{db_path}", echo=False)
|
17
23
|
|
18
24
|
def get_session(db_path: str = None):
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"""Shared utility functions for tokenator."""
|
2
|
+
|
3
|
+
import os
|
4
|
+
import platform
|
5
|
+
import logging
|
6
|
+
from pathlib import Path
|
7
|
+
from typing import Optional
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
def is_colab() -> bool:
|
12
|
+
"""Check if running in Google Colab."""
|
13
|
+
try:
|
14
|
+
import google.colab # type: ignore
|
15
|
+
return True
|
16
|
+
except ImportError:
|
17
|
+
return False
|
18
|
+
|
19
|
+
def get_default_db_path() -> str:
|
20
|
+
"""Get the platform-specific default database path."""
|
21
|
+
system = platform.system().lower()
|
22
|
+
|
23
|
+
try:
|
24
|
+
if is_colab():
|
25
|
+
# We're in Colab - use current directory
|
26
|
+
db_path = os.path.join(os.getcwd(), "tokenator_usage.db")
|
27
|
+
elif system == "linux" or system == "darwin":
|
28
|
+
# Follow XDG Base Directory Specification
|
29
|
+
xdg_data_home = os.environ.get("XDG_DATA_HOME", "")
|
30
|
+
if not xdg_data_home:
|
31
|
+
xdg_data_home = os.path.join(str(Path.home()), ".local", "share")
|
32
|
+
db_path = os.path.join(xdg_data_home, "tokenator", "usage.db")
|
33
|
+
elif system == "windows":
|
34
|
+
# Use %LOCALAPPDATA% on Windows
|
35
|
+
local_app_data = os.environ.get("LOCALAPPDATA", "")
|
36
|
+
if not local_app_data:
|
37
|
+
local_app_data = os.path.join(str(Path.home()), "AppData", "Local")
|
38
|
+
db_path = os.path.join(local_app_data, "tokenator", "usage.db")
|
39
|
+
else:
|
40
|
+
db_path = os.path.join(str(Path.home()), ".tokenator", "usage.db")
|
41
|
+
|
42
|
+
# Create directory if it doesn't exist
|
43
|
+
os.makedirs(os.path.dirname(db_path), exist_ok=True)
|
44
|
+
return db_path
|
45
|
+
except (OSError, IOError) as e:
|
46
|
+
# Fallback to current directory if we can't create the default path
|
47
|
+
fallback_path = os.path.join(os.getcwd(), "tokenator_usage.db")
|
48
|
+
logger.warning(f"Could not create default db path, falling back to {fallback_path}. Error: {e}")
|
49
|
+
return fallback_path
|
@@ -1,40 +0,0 @@
|
|
1
|
-
"""Automatic database migrations manager."""
|
2
|
-
|
3
|
-
import os
|
4
|
-
from pathlib import Path
|
5
|
-
from alembic import command
|
6
|
-
from alembic.config import Config
|
7
|
-
from alembic.runtime.migration import MigrationContext
|
8
|
-
from alembic.script import ScriptDirectory
|
9
|
-
from sqlalchemy import create_engine
|
10
|
-
|
11
|
-
from .utils import get_default_db_path
|
12
|
-
|
13
|
-
def get_alembic_config():
|
14
|
-
"""Get Alembic config pointing to the package's migrations."""
|
15
|
-
package_dir = Path(__file__).parent
|
16
|
-
migrations_dir = package_dir / "migrations"
|
17
|
-
|
18
|
-
alembic_cfg = Config()
|
19
|
-
alembic_cfg.set_main_option("script_location", str(migrations_dir))
|
20
|
-
alembic_cfg.set_main_option("sqlalchemy.url", f"sqlite:///{get_default_db_path()}")
|
21
|
-
|
22
|
-
return alembic_cfg
|
23
|
-
|
24
|
-
def check_and_run_migrations():
|
25
|
-
"""Check if migrations are needed and run them automatically."""
|
26
|
-
engine = create_engine(f"sqlite:///{get_default_db_path()}")
|
27
|
-
|
28
|
-
# Create migrations table if it doesn't exist
|
29
|
-
with engine.connect() as conn:
|
30
|
-
context = MigrationContext.configure(conn)
|
31
|
-
current_rev = context.get_current_revision()
|
32
|
-
|
33
|
-
# Get latest available revision
|
34
|
-
config = get_alembic_config()
|
35
|
-
script = ScriptDirectory.from_config(config)
|
36
|
-
head_rev = script.get_current_head()
|
37
|
-
|
38
|
-
# Run migrations if needed
|
39
|
-
if current_rev != head_rev:
|
40
|
-
command.upgrade(config, "head")
|
@@ -1,35 +0,0 @@
|
|
1
|
-
"""Shared utility functions for tokenator."""
|
2
|
-
|
3
|
-
import os
|
4
|
-
import platform
|
5
|
-
from pathlib import Path
|
6
|
-
from typing import Optional
|
7
|
-
|
8
|
-
def get_default_db_path() -> str:
|
9
|
-
"""Get the platform-specific default database path.
|
10
|
-
|
11
|
-
Returns:
|
12
|
-
str: Path to the SQLite database file
|
13
|
-
|
14
|
-
The path follows platform conventions:
|
15
|
-
- Linux/macOS: ~/.local/share/tokenator/usage.db (XDG spec)
|
16
|
-
- Windows: %LOCALAPPDATA%\\tokenator\\usage.db
|
17
|
-
- Others: ~/.tokenator/usage.db
|
18
|
-
"""
|
19
|
-
system = platform.system().lower()
|
20
|
-
|
21
|
-
if system == "linux" or system == "darwin":
|
22
|
-
# Follow XDG Base Directory Specification
|
23
|
-
xdg_data_home = os.environ.get("XDG_DATA_HOME", "")
|
24
|
-
if not xdg_data_home:
|
25
|
-
xdg_data_home = os.path.join(str(Path.home()), ".local", "share")
|
26
|
-
return os.path.join(xdg_data_home, "tokenator", "usage.db")
|
27
|
-
elif system == "windows":
|
28
|
-
# Use %LOCALAPPDATA% on Windows
|
29
|
-
local_app_data = os.environ.get("LOCALAPPDATA", "")
|
30
|
-
if not local_app_data:
|
31
|
-
local_app_data = os.path.join(str(Path.home()), "AppData", "Local")
|
32
|
-
return os.path.join(local_app_data, "tokenator", "usage.db")
|
33
|
-
else:
|
34
|
-
# Fallback for other systems
|
35
|
-
return os.path.join(str(Path.home()), ".tokenator", "usage.db")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|