arcade-core 4.2.0__tar.gz → 4.2.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.
- {arcade_core-4.2.0 → arcade_core-4.2.2}/PKG-INFO +3 -1
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/toolkit.py +31 -13
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/identity.py +11 -13
- {arcade_core-4.2.0 → arcade_core-4.2.2}/pyproject.toml +3 -1
- {arcade_core-4.2.0 → arcade_core-4.2.2}/.gitignore +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/README.md +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/__init__.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/annotations.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/auth.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/auth_tokens.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/catalog.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/config.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/config_model.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/constants.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/context.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/converters/__init__.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/converters/anthropic.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/converters/openai.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/converters/utils.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/discovery.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/errors.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/executor.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/network/__init__.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/network/org_transport.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/output.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/parse.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/py.typed +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/schema.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/__init__.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/__main__.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/constants.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/usage_service.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/usage/utils.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/utils.py +0 -0
- {arcade_core-4.2.0 → arcade_core-4.2.2}/arcade_core/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: arcade-core
|
|
3
|
-
Version: 4.2.
|
|
3
|
+
Version: 4.2.2
|
|
4
4
|
Summary: Arcade Core - Core library for Arcade platform
|
|
5
5
|
Author-email: Arcade <dev@arcade.dev>
|
|
6
6
|
License: MIT
|
|
@@ -16,6 +16,8 @@ Requires-Python: >=3.10
|
|
|
16
16
|
Requires-Dist: httpx>=0.27.0
|
|
17
17
|
Requires-Dist: loguru>=0.7.0
|
|
18
18
|
Requires-Dist: packaging>=24.1
|
|
19
|
+
Requires-Dist: portalocker>=2.10.0
|
|
20
|
+
Requires-Dist: posthog<7.0.0,>=6.7.6
|
|
19
21
|
Requires-Dist: pydantic>=2.7.0
|
|
20
22
|
Requires-Dist: pyjwt>=2.8.0
|
|
21
23
|
Requires-Dist: pyyaml>=6.0
|
|
@@ -299,32 +299,50 @@ class Toolkit(BaseModel):
|
|
|
299
299
|
# Skipping this file is necessary because tools are discovered via AST parsing, but those tools
|
|
300
300
|
# aren't in the module's namespace yet since the file is still executing.
|
|
301
301
|
current_file = None
|
|
302
|
+
current_module_name = None
|
|
302
303
|
main_module = sys.modules.get("__main__")
|
|
303
|
-
if main_module
|
|
304
|
-
|
|
305
|
-
|
|
304
|
+
if main_module:
|
|
305
|
+
if hasattr(main_module, "__file__") and main_module.__file__:
|
|
306
|
+
with contextlib.suppress(Exception):
|
|
307
|
+
current_file = Path(main_module.__file__).resolve()
|
|
308
|
+
# Get module name from __spec__ if available (used when paths don't match,
|
|
309
|
+
# e.g., script runs from bundle but package is in site-packages)
|
|
310
|
+
main_spec = getattr(main_module, "__spec__", None)
|
|
311
|
+
if main_spec and main_spec.name:
|
|
312
|
+
current_module_name = main_spec.name
|
|
306
313
|
|
|
307
314
|
tools: dict[str, list[str]] = {}
|
|
308
315
|
|
|
309
316
|
for module_path in modules:
|
|
310
|
-
#
|
|
317
|
+
# Build import path first (needed for module name comparison in skip logic)
|
|
318
|
+
relative_path = module_path.relative_to(package_dir)
|
|
319
|
+
relative_parts = relative_path.with_suffix("").parts
|
|
320
|
+
import_path = ".".join(relative_parts)
|
|
321
|
+
if relative_parts and relative_parts[0] == package_name:
|
|
322
|
+
full_import_path = import_path
|
|
323
|
+
else:
|
|
324
|
+
full_import_path = f"{package_name}.{import_path}" if import_path else package_name
|
|
325
|
+
|
|
326
|
+
# Skip logic: check by file path OR by module name
|
|
327
|
+
# This handles cases where the script is run from a different location than
|
|
328
|
+
# where the package is installed (e.g., deployment scenarios)
|
|
329
|
+
should_skip = False
|
|
311
330
|
if current_file:
|
|
312
331
|
try:
|
|
313
332
|
module_path_resolved = module_path.resolve()
|
|
314
333
|
if module_path_resolved == current_file:
|
|
315
|
-
|
|
334
|
+
should_skip = True
|
|
316
335
|
except Exception: # noqa: S110
|
|
317
336
|
pass
|
|
318
337
|
|
|
319
|
-
|
|
338
|
+
# Secondary check: compare module names when paths don't match
|
|
339
|
+
if not should_skip and current_module_name and full_import_path == current_module_name:
|
|
340
|
+
should_skip = True
|
|
341
|
+
|
|
342
|
+
if should_skip:
|
|
343
|
+
continue
|
|
344
|
+
|
|
320
345
|
cls.validate_file(module_path)
|
|
321
|
-
# Build import path and avoid duplicating the package prefix if it already exists
|
|
322
|
-
relative_parts = relative_path.with_suffix("").parts
|
|
323
|
-
import_path = ".".join(relative_parts)
|
|
324
|
-
if relative_parts and relative_parts[0] == package_name:
|
|
325
|
-
full_import_path = import_path
|
|
326
|
-
else:
|
|
327
|
-
full_import_path = f"{package_name}.{import_path}" if import_path else package_name
|
|
328
346
|
tools[full_import_path] = get_tools_from_file(str(module_path))
|
|
329
347
|
|
|
330
348
|
if not tools:
|
|
@@ -6,7 +6,6 @@ supporting pre-login anonymous tracking, post-login identity stitching,
|
|
|
6
6
|
and logout identity rotation.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
import fcntl
|
|
10
9
|
import json
|
|
11
10
|
import os
|
|
12
11
|
import tempfile
|
|
@@ -14,6 +13,7 @@ import uuid
|
|
|
14
13
|
from typing import Any
|
|
15
14
|
|
|
16
15
|
import httpx
|
|
16
|
+
import portalocker
|
|
17
17
|
import yaml
|
|
18
18
|
|
|
19
19
|
from arcade_core.constants import ARCADE_CONFIG_PATH, CREDENTIALS_FILE_PATH
|
|
@@ -46,18 +46,16 @@ class UsageIdentity:
|
|
|
46
46
|
if os.path.exists(self.usage_file_path):
|
|
47
47
|
try:
|
|
48
48
|
with open(self.usage_file_path) as f:
|
|
49
|
-
#
|
|
50
|
-
|
|
51
|
-
fcntl.flock(f.fileno(), fcntl.LOCK_SH)
|
|
49
|
+
# Lock file for reading (shared lock)
|
|
50
|
+
portalocker.lock(f, portalocker.LOCK_SH)
|
|
52
51
|
try:
|
|
53
52
|
data = json.load(f)
|
|
54
53
|
if isinstance(data, dict) and KEY_ANON_ID in data:
|
|
55
54
|
self._data = data
|
|
56
55
|
return self._data
|
|
57
56
|
finally:
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
|
|
57
|
+
# Unlock file
|
|
58
|
+
portalocker.unlock(f)
|
|
61
59
|
except Exception: # noqa: S110
|
|
62
60
|
pass
|
|
63
61
|
|
|
@@ -80,18 +78,18 @@ class UsageIdentity:
|
|
|
80
78
|
|
|
81
79
|
try:
|
|
82
80
|
with os.fdopen(temp_fd, "w") as f:
|
|
83
|
-
#
|
|
84
|
-
|
|
85
|
-
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
|
|
81
|
+
# Lock file for writing (exclusive lock)
|
|
82
|
+
portalocker.lock(f, portalocker.LOCK_EX)
|
|
86
83
|
try:
|
|
87
84
|
json.dump(data, f, indent=2)
|
|
88
85
|
f.flush()
|
|
89
86
|
os.fsync(f.fileno()) # ensure data is written to disk
|
|
90
87
|
finally:
|
|
91
|
-
|
|
92
|
-
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
|
|
88
|
+
portalocker.unlock(f)
|
|
93
89
|
|
|
94
|
-
os.
|
|
90
|
+
# Use os.replace() for cross-platform atomic file replacement
|
|
91
|
+
# os.replace() is atomic on both Unix and Windows (Python 3.3+)
|
|
92
|
+
os.replace(temp_path, self.usage_file_path)
|
|
95
93
|
except Exception:
|
|
96
94
|
# clean up
|
|
97
95
|
import contextlib
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "arcade-core"
|
|
3
|
-
version = "4.2.
|
|
3
|
+
version = "4.2.2"
|
|
4
4
|
description = "Arcade Core - Core library for Arcade platform"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -24,9 +24,11 @@ dependencies = [
|
|
|
24
24
|
"toml>=0.10.2",
|
|
25
25
|
"httpx>=0.27.0",
|
|
26
26
|
"packaging>=24.1",
|
|
27
|
+
"portalocker>=2.10.0",
|
|
27
28
|
"types-python-dateutil==2.9.0.20241003",
|
|
28
29
|
"types-pytz==2024.2.0.20241003",
|
|
29
30
|
"types-toml==0.10.8.20240310",
|
|
31
|
+
"posthog>=6.7.6,<7.0.0",
|
|
30
32
|
]
|
|
31
33
|
|
|
32
34
|
[project.optional-dependencies]
|
|
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
|
|
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
|