compair-core 0.3.8__tar.gz → 0.3.10__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.

Potentially problematic release.


This version of compair-core might be problematic. Click here for more details.

Files changed (44) hide show
  1. {compair_core-0.3.8 → compair_core-0.3.10}/PKG-INFO +2 -1
  2. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/api.py +14 -7
  3. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/__init__.py +27 -35
  4. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/utils.py +1 -1
  5. compair_core-0.3.10/compair_core/compair_email/templates_core.py +32 -0
  6. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/app.py +1 -1
  7. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/settings.py +1 -1
  8. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core.egg-info/PKG-INFO +2 -1
  9. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core.egg-info/requires.txt +1 -0
  10. {compair_core-0.3.8 → compair_core-0.3.10}/pyproject.toml +2 -1
  11. compair_core-0.3.8/compair_core/compair_email/templates_core.py +0 -13
  12. {compair_core-0.3.8 → compair_core-0.3.10}/LICENSE +0 -0
  13. {compair_core-0.3.8 → compair_core-0.3.10}/README.md +0 -0
  14. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/__init__.py +0 -0
  15. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/celery_app.py +0 -0
  16. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/default_groups.py +0 -0
  17. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/embeddings.py +0 -0
  18. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/feedback.py +0 -0
  19. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/logger.py +0 -0
  20. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/main.py +0 -0
  21. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/models.py +0 -0
  22. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/schema.py +0 -0
  23. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair/tasks.py +0 -0
  24. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair_email/__init__.py +0 -0
  25. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair_email/email.py +0 -0
  26. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair_email/email_core.py +0 -0
  27. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/compair_email/templates.py +0 -0
  28. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/__init__.py +0 -0
  29. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/deps.py +0 -0
  30. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/local_model/__init__.py +0 -0
  31. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/local_model/app.py +0 -0
  32. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/__init__.py +0 -0
  33. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/console_mailer.py +0 -0
  34. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/contracts.py +0 -0
  35. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/local_storage.py +0 -0
  36. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/noop_analytics.py +0 -0
  37. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/noop_billing.py +0 -0
  38. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/providers/noop_ocr.py +0 -0
  39. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/routers/__init__.py +0 -0
  40. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core/server/routers/capabilities.py +0 -0
  41. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core.egg-info/SOURCES.txt +0 -0
  42. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core.egg-info/dependency_links.txt +0 -0
  43. {compair_core-0.3.8 → compair_core-0.3.10}/compair_core.egg-info/top_level.txt +0 -0
  44. {compair_core-0.3.8 → compair_core-0.3.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compair-core
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Open-source foundation of the Compair collaboration platform.
5
5
  Author: RocketResearch, Inc.
6
6
  License: MIT
@@ -23,6 +23,7 @@ Requires-Dist: redis>=5.0
23
23
  Requires-Dist: psutil>=5.9
24
24
  Requires-Dist: python-Levenshtein>=0.23
25
25
  Requires-Dist: redmail>=0.6
26
+ Requires-Dist: python-multipart>=0.0.20
26
27
  Provides-Extra: dev
27
28
  Requires-Dist: build>=1.0; extra == "dev"
28
29
  Requires-Dist: twine>=5.0; extra == "dev"
@@ -36,10 +36,13 @@ from .compair_email.templates import (
36
36
  )
37
37
  from .compair.tasks import process_document_task as process_document_celery, send_feature_announcement_task, send_deactivate_request_email, send_help_request_email
38
38
 
39
- import redis
39
+ try:
40
+ import redis # type: ignore
41
+ except ImportError: # pragma: no cover - optional dependency
42
+ redis = None
40
43
 
41
44
  redis_url = os.environ.get("REDIS_URL")
42
- redis_client = redis.Redis.from_url(redis_url)
45
+ redis_client = redis.Redis.from_url(redis_url) if (redis and redis_url) else None
43
46
  #from compair.main import process_document
44
47
 
45
48
  router = APIRouter()
@@ -80,6 +83,7 @@ HAS_ACTIVITY = hasattr(models, "Activity")
80
83
  HAS_REFERRALS = hasattr(models.User, "referral_code")
81
84
  HAS_BILLING = hasattr(models.User, "stripe_customer_id")
82
85
  HAS_TRIALS = hasattr(models.User, "trial_expiration_date")
86
+ HAS_REDIS = redis_client is not None
83
87
 
84
88
 
85
89
  def require_feature(flag: bool, feature: str) -> None:
@@ -3228,11 +3232,12 @@ def generate_download_token(
3228
3232
  else:
3229
3233
  raise HTTPException(status_code=403, detail="Not authorized to download this file.")
3230
3234
 
3235
+ if not HAS_REDIS:
3236
+ raise HTTPException(status_code=501, detail="Secure download links require Redis, which is unavailable in the core edition.")
3237
+
3231
3238
  token = secrets.token_urlsafe(32)
3232
3239
  key = f"download_token:{token}"
3233
3240
  redis_client.setex(key, 300, document_id)
3234
- print('Setting redis kv')
3235
- print(key, document_id)
3236
3241
  return {"download_url": f"/documents/download/{token}"}
3237
3242
 
3238
3243
 
@@ -3241,10 +3246,12 @@ def download_document_with_token(
3241
3246
  token: str,
3242
3247
  storage: StorageProvider = Depends(get_storage),
3243
3248
  ):
3249
+ if not HAS_REDIS:
3250
+ raise HTTPException(status_code=501, detail="Secure download links require Redis, which is unavailable in the core edition.")
3251
+
3244
3252
  key = f"download_token:{token}"
3245
- print(f'Retrieving redis kv with key {key}')
3246
- document_id = redis_client.get(key).decode('utf-8') if redis_client.get(key) else None
3247
- print(f'Value {document_id}')
3253
+ value = redis_client.get(key) if redis_client else None
3254
+ document_id = value.decode('utf-8') if value else None
3248
3255
  if not document_id:
3249
3256
  raise HTTPException(status_code=403, detail="Invalid or expired token")
3250
3257
  redis_client.delete(key)
@@ -1,25 +1,20 @@
1
1
  from __future__ import annotations
2
2
 
3
- import importlib
4
- import logging
5
3
  import os
6
- import sys
7
-
8
4
  from sqlalchemy import Engine, create_engine
9
5
  from sqlalchemy.orm import sessionmaker
10
6
 
11
- from ..compair import embeddings, feedback, logger, main, models, tasks, utils
12
- from ..compair.default_groups import initialize_default_groups
7
+ from . import embeddings, feedback, logger, main, models, tasks, utils
8
+ from .default_groups import initialize_default_groups
13
9
 
14
10
  edition = os.getenv("COMPAIR_EDITION", "core").lower()
15
11
 
16
- _cloud_available = False
12
+ initialize_database_override = None
13
+
17
14
  if edition == "cloud":
18
15
  try: # Import cloud overrides if the private package is installed
19
- from ..compair_cloud import (
16
+ from compair_cloud import ( # type: ignore
20
17
  bootstrap as cloud_bootstrap,
21
- celery_app as cloud_celery_app,
22
- default_groups as cloud_default_groups,
23
18
  embeddings as cloud_embeddings,
24
19
  feedback as cloud_feedback,
25
20
  logger as cloud_logger,
@@ -27,27 +22,18 @@ if edition == "cloud":
27
22
  models as cloud_models,
28
23
  tasks as cloud_tasks,
29
24
  utils as cloud_utils,
30
- ) # type: ignore
25
+ )
31
26
 
32
- _cloud_available = True
27
+ embeddings = cloud_embeddings
28
+ feedback = cloud_feedback
29
+ logger = cloud_logger
30
+ main = cloud_main
31
+ models = cloud_models
32
+ tasks = cloud_tasks
33
+ utils = cloud_utils
34
+ initialize_database_override = getattr(cloud_bootstrap, "initialize_database", None)
33
35
  except ImportError:
34
- _cloud_available = False
35
-
36
- if _cloud_available:
37
- from ..compair_cloud.default_groups import initialize_default_groups # type: ignore
38
- embeddings = cloud_embeddings
39
- feedback = cloud_feedback
40
- logger = cloud_logger
41
- main = cloud_main
42
- models = cloud_models
43
- tasks = cloud_tasks
44
- utils = cloud_utils
45
- initialize_database_override = getattr(cloud_bootstrap, "initialize_database", None)
46
- else:
47
- from . import embeddings, feedback, logger, main, models, tasks, utils
48
- from .default_groups import initialize_default_groups
49
- initialize_database_override = None
50
-
36
+ pass
51
37
 
52
38
 
53
39
  def _handle_engine() -> Engine:
@@ -74,15 +60,21 @@ def _handle_engine() -> Engine:
74
60
  return create_engine(f"sqlite:///{sqlite_path}", connect_args={"check_same_thread": False})
75
61
 
76
62
 
77
- engine = _handle_engine()
78
-
79
-
80
63
  def initialize_database() -> None:
81
64
  models.Base.metadata.create_all(engine)
82
65
  if initialize_database_override:
83
66
  initialize_database_override(engine)
84
67
 
85
68
 
86
- __all__ = ["embeddings", "feedback", "main", "models", "utils"]
87
- sys.modules.setdefault(__name__ + ".server", importlib.import_module("server"))
88
- sys.modules.setdefault(__name__ + ".compair_email", importlib.import_module("compair_email"))
69
+ def _initialize_defaults() -> None:
70
+ with Session() as session:
71
+ initialize_default_groups(session)
72
+
73
+
74
+ engine = _handle_engine()
75
+ Session = sessionmaker(engine)
76
+ embedder = embeddings.Embedder()
77
+ reviewer = feedback.Reviewer()
78
+ _initialize_defaults()
79
+
80
+ __all__ = ["embeddings", "feedback", "main", "models", "utils", "Session"]
@@ -5,7 +5,7 @@ from datetime import datetime, timedelta, timezone
5
5
 
6
6
  from sqlalchemy.orm import Session
7
7
 
8
- from compair.models import Activity
8
+ from .models import Activity
9
9
 
10
10
 
11
11
  def chunk_text(text: str) -> list[str]:
@@ -0,0 +1,32 @@
1
+ """Minimal email templates for the core edition."""
2
+
3
+ ACCOUNT_VERIFY_TEMPLATE = """
4
+ <p>Hi {{user_name}},</p>
5
+ <p>Please verify your Compair account by clicking the link below:</p>
6
+ <p><a href="{{verify_link}}">Verify my account</a></p>
7
+ <p>Thanks!</p>
8
+ """.strip()
9
+
10
+ PASSWORD_RESET_TEMPLATE = """
11
+ <p>We received a request to reset your password.</p>
12
+ <p>Your password reset code is: <strong>{{reset_code}}</strong></p>
13
+ """.strip()
14
+
15
+ GROUP_INVITATION_TEMPLATE = """
16
+ <p>{{inviter_name}} invited you to join the group {{group_name}}.</p>
17
+ <p><a href="{{invitation_link}}">Accept invitation</a></p>
18
+ """.strip()
19
+
20
+ GROUP_JOIN_TEMPLATE = """
21
+ <p>{{user_name}} has joined your group.</p>
22
+ """.strip()
23
+
24
+ INDIVIDUAL_INVITATION_TEMPLATE = """
25
+ <p>{{inviter_name}} invited you to Compair.</p>
26
+ <p><a href="{{referral_link}}">Join now</a></p>
27
+ """.strip()
28
+
29
+ REFERRAL_CREDIT_TEMPLATE = """
30
+ <p>Hi {{user_name}},</p>
31
+ <p>Great news! You now have {{referral_credits}} referral credits.</p>
32
+ """.strip()
@@ -28,7 +28,7 @@ def create_app(settings: Settings | None = None) -> FastAPI:
28
28
 
29
29
  app = FastAPI(title="Compair API", version=resolved_settings.version)
30
30
 
31
- from api import router as legacy_router
31
+ from ..api import router as legacy_router
32
32
 
33
33
  app.include_router(legacy_router)
34
34
  app.include_router(capabilities_router)
@@ -18,7 +18,7 @@ class Settings(BaseSettings):
18
18
  premium_models: bool = False
19
19
 
20
20
  # Core/local storage defaults
21
- local_upload_dir: str = "/data/uploads"
21
+ local_upload_dir: str = "~/.compair-core/data/uploads"
22
22
  local_upload_base_url: str = "/uploads"
23
23
 
24
24
  # Cloud storage (R2/S3-compatible)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: compair-core
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Open-source foundation of the Compair collaboration platform.
5
5
  Author: RocketResearch, Inc.
6
6
  License: MIT
@@ -23,6 +23,7 @@ Requires-Dist: redis>=5.0
23
23
  Requires-Dist: psutil>=5.9
24
24
  Requires-Dist: python-Levenshtein>=0.23
25
25
  Requires-Dist: redmail>=0.6
26
+ Requires-Dist: python-multipart>=0.0.20
26
27
  Provides-Extra: dev
27
28
  Requires-Dist: build>=1.0; extra == "dev"
28
29
  Requires-Dist: twine>=5.0; extra == "dev"
@@ -11,6 +11,7 @@ redis>=5.0
11
11
  psutil>=5.9
12
12
  python-Levenshtein>=0.23
13
13
  redmail>=0.6
14
+ python-multipart>=0.0.20
14
15
 
15
16
  [dev]
16
17
  build>=1.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "compair-core"
7
- version = "0.3.8"
7
+ version = "0.3.10"
8
8
  description = "Open-source foundation of the Compair collaboration platform."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -26,6 +26,7 @@ dependencies = [
26
26
  "psutil>=5.9",
27
27
  "python-Levenshtein>=0.23",
28
28
  "redmail>=0.6",
29
+ "python-multipart>=0.0.20",
29
30
  ]
30
31
 
31
32
  [project.optional-dependencies]
@@ -1,13 +0,0 @@
1
- """Minimal email templates for the core edition."""
2
-
3
- ACCOUNT_VERIFY_TEMPLATE = """
4
- <p>Hi {{user_name}},</p>
5
- <p>Please verify your Compair account by clicking the link below:</p>
6
- <p><a href="{{verify_link}}">Verify my account</a></p>
7
- <p>Thanks!</p>
8
- """.strip()
9
-
10
- PASSWORD_RESET_TEMPLATE = """
11
- <p>We received a request to reset your password.</p>
12
- <p>Your password reset code is: <strong>{{reset_code}}</strong></p>
13
- """.strip()
File without changes
File without changes
File without changes