lumera 0.9.5__tar.gz → 0.9.7__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.
- {lumera-0.9.5 → lumera-0.9.7}/PKG-INFO +1 -1
- {lumera-0.9.5 → lumera-0.9.7}/lumera/__init__.py +5 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/_utils.py +38 -1
- lumera-0.9.7/lumera/files.py +97 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera.egg-info/PKG-INFO +1 -1
- {lumera-0.9.5 → lumera-0.9.7}/lumera.egg-info/SOURCES.txt +1 -0
- {lumera-0.9.5 → lumera-0.9.7}/pyproject.toml +1 -1
- {lumera-0.9.5 → lumera-0.9.7}/lumera/automations.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/exceptions.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/google.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/integrations/__init__.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/integrations/google.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/llm.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/locks.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/pb.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/sdk.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/storage.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera/webhooks.py +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera.egg-info/dependency_links.txt +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera.egg-info/requires.txt +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/lumera.egg-info/top_level.txt +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/setup.cfg +0 -0
- {lumera-0.9.5 → lumera-0.9.7}/tests/test_sdk.py +0 -0
|
@@ -31,6 +31,9 @@ from .exceptions import (
|
|
|
31
31
|
ValidationError,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
+
# Import file types for Pydantic automation inputs
|
|
35
|
+
from .files import LumeraFile, LumeraFiles
|
|
36
|
+
|
|
34
37
|
# Import key SDK helpers to expose them at the package root.
|
|
35
38
|
from .sdk import (
|
|
36
39
|
CollectionField,
|
|
@@ -87,6 +90,8 @@ __all__ = [
|
|
|
87
90
|
# Type definitions
|
|
88
91
|
"CollectionField",
|
|
89
92
|
"HookReplayResult",
|
|
93
|
+
"LumeraFile",
|
|
94
|
+
"LumeraFiles",
|
|
90
95
|
# Exceptions
|
|
91
96
|
"LumeraAPIError",
|
|
92
97
|
"RecordNotUniqueError",
|
|
@@ -19,6 +19,8 @@ from dotenv import load_dotenv
|
|
|
19
19
|
TOKEN_ENV = "LUMERA_TOKEN"
|
|
20
20
|
BASE_URL_ENV = "LUMERA_BASE_URL"
|
|
21
21
|
ENV_PATH = "/root/.env"
|
|
22
|
+
LOCAL_CREDS_PATH = ".lumera/credentials.json"
|
|
23
|
+
GLOBAL_CREDS_PATH = os.path.join(os.path.expanduser("~"), ".config", "lumera", "credentials.json")
|
|
22
24
|
|
|
23
25
|
load_dotenv(override=False)
|
|
24
26
|
load_dotenv(ENV_PATH, override=False)
|
|
@@ -56,12 +58,47 @@ def _get_session() -> requests.Session:
|
|
|
56
58
|
return _http_session
|
|
57
59
|
|
|
58
60
|
|
|
61
|
+
def _read_token_from_creds_file(path: str) -> str | None:
|
|
62
|
+
"""Read token from a credentials.json file."""
|
|
63
|
+
try:
|
|
64
|
+
if os.path.exists(path):
|
|
65
|
+
with open(path, "r") as f:
|
|
66
|
+
creds = json.load(f)
|
|
67
|
+
return creds.get("token")
|
|
68
|
+
except (json.JSONDecodeError, IOError):
|
|
69
|
+
pass
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
|
|
59
73
|
def get_lumera_token() -> str:
|
|
74
|
+
"""Get Lumera API token from environment or credentials files.
|
|
75
|
+
|
|
76
|
+
Priority:
|
|
77
|
+
1. LUMERA_TOKEN environment variable
|
|
78
|
+
2. .lumera/credentials.json (project-local, from CLI login --local)
|
|
79
|
+
3. ~/.config/lumera/credentials.json (global, from CLI login)
|
|
80
|
+
4. /root/.env (legacy, for automations in sandbox)
|
|
81
|
+
"""
|
|
82
|
+
# 1. Check environment variable (highest priority)
|
|
60
83
|
token = os.getenv(TOKEN_ENV)
|
|
61
84
|
if token:
|
|
62
85
|
return token
|
|
86
|
+
|
|
87
|
+
# 2. Check project-local credentials
|
|
88
|
+
token = _read_token_from_creds_file(LOCAL_CREDS_PATH)
|
|
89
|
+
if token:
|
|
90
|
+
return token
|
|
91
|
+
|
|
92
|
+
# 3. Check global credentials
|
|
93
|
+
token = _read_token_from_creds_file(GLOBAL_CREDS_PATH)
|
|
94
|
+
if token:
|
|
95
|
+
return token
|
|
96
|
+
|
|
97
|
+
# 4. /root/.env is already loaded via dotenv at module load time
|
|
98
|
+
# so if we get here, no token was found anywhere
|
|
63
99
|
raise RuntimeError(
|
|
64
|
-
f"{TOKEN_ENV}
|
|
100
|
+
f"{TOKEN_ENV} not found. Checked: environment, {LOCAL_CREDS_PATH}, {GLOBAL_CREDS_PATH}, {ENV_PATH}. "
|
|
101
|
+
f"Run `lumera login` to authenticate."
|
|
65
102
|
)
|
|
66
103
|
|
|
67
104
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File input types for Lumera automations.
|
|
3
|
+
|
|
4
|
+
These types are used with Pydantic models to define file inputs for automations.
|
|
5
|
+
They generate the correct JSON schema format that the frontend recognizes for
|
|
6
|
+
file picker UI.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
from lumera import LumeraFile, LumeraFiles
|
|
11
|
+
|
|
12
|
+
class ProcessInputs(BaseModel):
|
|
13
|
+
report: LumeraFile = Field(..., description="Excel report to process")
|
|
14
|
+
attachments: LumeraFiles = Field(default=[], description="Additional files")
|
|
15
|
+
|
|
16
|
+
def main(inputs: ProcessInputs):
|
|
17
|
+
# inputs.report is a string path like "/tmp/lumera-files/report.xlsx"
|
|
18
|
+
with open(inputs.report) as f:
|
|
19
|
+
...
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from typing import Annotated, Any
|
|
23
|
+
|
|
24
|
+
# Check if Pydantic is available
|
|
25
|
+
try:
|
|
26
|
+
from pydantic import GetJsonSchemaHandler
|
|
27
|
+
from pydantic.json_schema import JsonSchemaValue
|
|
28
|
+
from pydantic_core import CoreSchema
|
|
29
|
+
|
|
30
|
+
_HAS_PYDANTIC = True
|
|
31
|
+
except ImportError:
|
|
32
|
+
_HAS_PYDANTIC = False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if _HAS_PYDANTIC:
|
|
36
|
+
|
|
37
|
+
class _LumeraFileSchema:
|
|
38
|
+
"""
|
|
39
|
+
Pydantic JSON schema handler for single file inputs.
|
|
40
|
+
|
|
41
|
+
Generates: {"type": "string", "format": "file"}
|
|
42
|
+
|
|
43
|
+
The frontend recognizes this schema and renders a file picker.
|
|
44
|
+
At runtime, the value is a string path to the downloaded file.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def __get_pydantic_json_schema__(
|
|
49
|
+
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
|
|
50
|
+
) -> JsonSchemaValue:
|
|
51
|
+
return {"type": "string", "format": "file"}
|
|
52
|
+
|
|
53
|
+
class _LumeraFilesSchema:
|
|
54
|
+
"""
|
|
55
|
+
Pydantic JSON schema handler for multiple file inputs.
|
|
56
|
+
|
|
57
|
+
Generates: {"type": "array", "items": {"type": "string", "format": "file"}}
|
|
58
|
+
|
|
59
|
+
The frontend recognizes this schema and renders a multi-file picker.
|
|
60
|
+
At runtime, the value is a list of string paths to downloaded files.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def __get_pydantic_json_schema__(
|
|
65
|
+
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
|
|
66
|
+
) -> JsonSchemaValue:
|
|
67
|
+
return {"type": "array", "items": {"type": "string", "format": "file"}}
|
|
68
|
+
|
|
69
|
+
# Public types using Annotated to attach schema handlers
|
|
70
|
+
LumeraFile: Any = Annotated[str, _LumeraFileSchema()]
|
|
71
|
+
"""
|
|
72
|
+
Type for single file input in Pydantic models.
|
|
73
|
+
|
|
74
|
+
At runtime, this is a string containing the local file path.
|
|
75
|
+
In JSON schema, generates {"type": "string", "format": "file"}.
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
class Inputs(BaseModel):
|
|
79
|
+
document: LumeraFile = Field(..., description="PDF to process")
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
LumeraFiles: Any = Annotated[list[str], _LumeraFilesSchema()]
|
|
83
|
+
"""
|
|
84
|
+
Type for multiple file inputs in Pydantic models.
|
|
85
|
+
|
|
86
|
+
At runtime, this is a list of strings containing local file paths.
|
|
87
|
+
In JSON schema, generates {"type": "array", "items": {"type": "string", "format": "file"}}.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
class Inputs(BaseModel):
|
|
91
|
+
documents: LumeraFiles = Field(default=[], description="PDFs to merge")
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
else:
|
|
95
|
+
# Fallback when Pydantic is not installed - types are just aliases
|
|
96
|
+
LumeraFile: Any = str
|
|
97
|
+
LumeraFiles: Any = list
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|