tokenator 0.1.0__tar.gz → 0.1.2__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {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
|