alphaengine 0.1.1__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.
Files changed (34) hide show
  1. {alphaengine-0.1.1 → alphaengine-0.1.2}/CHANGELOG.md +19 -0
  2. {alphaengine-0.1.1 → alphaengine-0.1.2}/PKG-INFO +1 -1
  3. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/__init__.py +3 -1
  4. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/_version.py +1 -1
  5. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/study/__init__.py +4 -4
  6. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/study/report.py +11 -10
  7. {alphaengine-0.1.1 → alphaengine-0.1.2}/.github/workflows/ci.yml +0 -0
  8. {alphaengine-0.1.1 → alphaengine-0.1.2}/.github/workflows/publish.yml +0 -0
  9. {alphaengine-0.1.1 → alphaengine-0.1.2}/.gitignore +0 -0
  10. {alphaengine-0.1.1 → alphaengine-0.1.2}/LICENSE +0 -0
  11. {alphaengine-0.1.1 → alphaengine-0.1.2}/README.md +0 -0
  12. {alphaengine-0.1.1 → alphaengine-0.1.2}/SECURITY.md +0 -0
  13. {alphaengine-0.1.1 → alphaengine-0.1.2}/pyproject.toml +0 -0
  14. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/agent/__init__.py +0 -0
  15. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/agent/driver.py +0 -0
  16. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/client/__init__.py +0 -0
  17. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/client/executor.py +0 -0
  18. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/client/session.py +0 -0
  19. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/__init__.py +0 -0
  20. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/backtest.py +0 -0
  21. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/factors.py +0 -0
  22. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/pairs.py +0 -0
  23. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/performance.py +0 -0
  24. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/risk.py +0 -0
  25. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/technical.py +0 -0
  26. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/core/validation.py +0 -0
  27. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/py.typed +0 -0
  28. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/study/schema.py +0 -0
  29. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/sweep/__init__.py +0 -0
  30. {alphaengine-0.1.1 → alphaengine-0.1.2}/src/alphaengine/sweep/runner.py +0 -0
  31. {alphaengine-0.1.1 → alphaengine-0.1.2}/tests/test_client.py +0 -0
  32. {alphaengine-0.1.1 → alphaengine-0.1.2}/tests/test_goldens.py +0 -0
  33. {alphaengine-0.1.1 → alphaengine-0.1.2}/tests/test_smoke.py +0 -0
  34. {alphaengine-0.1.1 → alphaengine-0.1.2}/tests/test_sweep.py +0 -0
@@ -7,6 +7,25 @@ minor bump.
7
7
 
8
8
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
9
9
 
10
+ ## [0.1.2] - 2026-07-31
11
+
12
+ **No computed value changed.** Identical figures to 0.1.0 and 0.1.1.
13
+
14
+ ### Fixed
15
+
16
+ - `report()` used `try`/`except`/`pass` to read an error body, which ruff's
17
+ SIM105 correctly objects to. It is `contextlib.suppress` now. The intent was
18
+ always total suppression: a server answering with HTML, an empty body or
19
+ nothing at all still has to produce a usable error rather than a second
20
+ exception raised on top of the first.
21
+
22
+ ### Changed
23
+
24
+ - `DEFAULT_BASE_URL` points at the live platform. 0.1.1 shipped with a
25
+ placeholder host, so every `report()` call that did not pass `base_url` or set
26
+ `QUANTOS_API_URL` resolved to a domain that does not answer. Reporting was
27
+ effectively unusable at its default in that release.
28
+
10
29
  ## [0.1.1] - 2026-07-31
11
30
 
12
31
  **No computed value changed.** Every figure this version produces is identical
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alphaengine
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Validated research tooling for investment strategies: deflation, overfitting detection, and honest trial counts.
5
5
  Project-URL: Homepage, https://github.com/quantOSC/alphaengine
6
6
  Project-URL: Documentation, https://github.com/quantOSC/alphaengine#readme
@@ -27,6 +27,8 @@ OFFLINE BY CONSTRUCTION
27
27
  and your data never leaves the machine.
28
28
  """
29
29
 
30
+ from typing import Any
31
+
30
32
  from ._version import __version__
31
33
  from .study import SCHEMA_VERSION, Study, load, save
32
34
  from .sweep import SweepResult, sweep
@@ -49,7 +51,7 @@ __all__ = [
49
51
  ]
50
52
 
51
53
 
52
- def __getattr__(name: str): # PEP 562
54
+ def __getattr__(name: str) -> Any: # PEP 562
53
55
  """`report` and `ReportError` load on first use.
54
56
 
55
57
  Everything else in this package is offline by construction and imports
@@ -12,4 +12,4 @@ While the leading digit is 0, the MINOR position carries that rule: 0.1 -> 0.2
12
12
  is what a changed figure costs. The API may still move underneath it.
13
13
  """
14
14
 
15
- __version__ = "0.1.1"
15
+ __version__ = "0.1.2"
@@ -27,14 +27,14 @@ WHAT IS NOT IN IT
27
27
  whoever owns them.
28
28
  """
29
29
 
30
+ from typing import Any
31
+
30
32
  from .schema import SCHEMA_VERSION, Study, load, save
31
33
 
32
- __all__ = [
33
- "report",
34
- "ReportError","Study", "save", "load", "SCHEMA_VERSION"]
34
+ __all__ = ["report", "ReportError", "Study", "save", "load", "SCHEMA_VERSION"]
35
35
 
36
36
 
37
- def __getattr__(name: str): # PEP 562
37
+ def __getattr__(name: str) -> Any: # PEP 562
38
38
  """`report` and `ReportError` load on first use.
39
39
 
40
40
  Eager import would pull urllib into `import alphaengine`, which the offline
@@ -29,6 +29,7 @@ user of the offline half, who did not ask for this.
29
29
 
30
30
  from __future__ import annotations
31
31
 
32
+ import contextlib
32
33
  import json
33
34
  import os
34
35
  from typing import TYPE_CHECKING, Any
@@ -38,7 +39,7 @@ if TYPE_CHECKING: # pragma: no cover - typing only
38
39
 
39
40
  __all__ = ["report", "ReportError"]
40
41
 
41
- DEFAULT_BASE_URL = "https://api.quantos.dev"
42
+ DEFAULT_BASE_URL = "https://alpha-backend-production-51df.up.railway.app"
42
43
  _ENV_KEY = "QUANTOS_API_KEY"
43
44
  _ENV_URL = "QUANTOS_API_URL"
44
45
  _PATH = "/api/me/runs/ingest"
@@ -140,8 +141,7 @@ def report(
140
141
  key = api_key or os.environ.get(_ENV_KEY, "")
141
142
  if not key.strip():
142
143
  raise ReportError(
143
- f"No API key. Pass api_key=..., or set {_ENV_KEY}. "
144
- "Create one in the portal under Settings."
144
+ f"No API key. Pass api_key=..., or set {_ENV_KEY}. Create one in the portal under Settings."
145
145
  )
146
146
 
147
147
  root = (base_url or os.environ.get(_ENV_URL) or DEFAULT_BASE_URL).rstrip("/")
@@ -160,13 +160,16 @@ def report(
160
160
 
161
161
  try:
162
162
  with urllib.request.urlopen(req, timeout=timeout) as resp:
163
- return json.loads(resp.read().decode("utf-8"))
163
+ recorded: dict[str, Any] = json.loads(resp.read().decode("utf-8"))
164
+ return recorded
164
165
  except urllib.error.HTTPError as e:
166
+ # The body is best-effort context for the message. A server that
167
+ # answers with HTML, an empty body, or nothing at all still has to
168
+ # produce a usable error rather than a second exception on top of the
169
+ # first, which is why the failure to read it is suppressed entirely.
165
170
  detail = ""
166
- try:
171
+ with contextlib.suppress(Exception):
167
172
  detail = json.loads(e.read().decode("utf-8")).get("detail", "")
168
- except Exception: # noqa: BLE001 - the body is best-effort context
169
- pass
170
173
  if e.code in (401, 403):
171
174
  raise ReportError(
172
175
  f"The key was rejected ({e.code}). It may be revoked, or from a different "
@@ -174,6 +177,4 @@ def report(
174
177
  ) from e
175
178
  raise ReportError(f"The server refused the study ({e.code}). {detail}".strip()) from e
176
179
  except urllib.error.URLError as e:
177
- raise ReportError(
178
- f"Could not reach {root}: {e.reason}. Your study is still on your disk."
179
- ) from e
180
+ raise ReportError(f"Could not reach {root}: {e.reason}. Your study is still on your disk.") from e
File without changes
File without changes
File without changes
File without changes
File without changes