fix: pin black to 26.3.1 across all environments
- Pin black version in requirements-dev.txt (was >=24.0.0) - Update pre-commit to use black 26.3.1 with Python 3.12 - Add language_version: python3.12 to pre-commit black hook - Reformat files with new black version for consistency
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
repos:
|
repos:
|
||||||
# Ruff - fast Python linter
|
# Ruff - fast Python linter
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.11.2
|
rev: v0.15.8
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: [--fix, --exit-non-zero-on-fix]
|
args: [--fix, --exit-non-zero-on-fix]
|
||||||
@@ -11,10 +11,11 @@ repos:
|
|||||||
|
|
||||||
# Black - Python formatter
|
# Black - Python formatter
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 25.1.0
|
rev: 26.3.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
files: ^(app|tests|scripts)/
|
files: ^(app|tests|scripts)/
|
||||||
|
language_version: python3.12
|
||||||
|
|
||||||
# Type checking with mypy (optional, slower)
|
# Type checking with mypy (optional, slower)
|
||||||
# Uncomment to enable:
|
# Uncomment to enable:
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ def _ensure_lightweight_charts_assets() -> None:
|
|||||||
global _CHARTS_SCRIPT_ADDED
|
global _CHARTS_SCRIPT_ADDED
|
||||||
if _CHARTS_SCRIPT_ADDED:
|
if _CHARTS_SCRIPT_ADDED:
|
||||||
return
|
return
|
||||||
ui.add_head_html(
|
ui.add_head_html("""
|
||||||
"""
|
|
||||||
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
|
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
_CHARTS_SCRIPT_ADDED = True
|
_CHARTS_SCRIPT_ADDED = True
|
||||||
|
|
||||||
|
|
||||||
@@ -48,8 +46,7 @@ class CandlestickChart:
|
|||||||
self._initialize_chart()
|
self._initialize_chart()
|
||||||
|
|
||||||
def _initialize_chart(self) -> None:
|
def _initialize_chart(self) -> None:
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const root = document.getElementById({json.dumps(self.chart_id)});
|
const root = document.getElementById({json.dumps(self.chart_id)});
|
||||||
if (!root || typeof LightweightCharts === 'undefined') return;
|
if (!root || typeof LightweightCharts === 'undefined') return;
|
||||||
@@ -94,57 +91,48 @@ class CandlestickChart:
|
|||||||
indicators: {{}},
|
indicators: {{}},
|
||||||
}};
|
}};
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def set_candles(self, candles: list[dict[str, Any]]) -> None:
|
def set_candles(self, candles: list[dict[str, Any]]) -> None:
|
||||||
payload = json.dumps(candles)
|
payload = json.dumps(candles)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.candleSeries.setData({payload});
|
ref.candleSeries.setData({payload});
|
||||||
ref.chart.timeScale().fitContent();
|
ref.chart.timeScale().fitContent();
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def update_price(self, candle: dict[str, Any]) -> None:
|
def update_price(self, candle: dict[str, Any]) -> None:
|
||||||
payload = json.dumps(candle)
|
payload = json.dumps(candle)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.candleSeries.update({payload});
|
ref.candleSeries.update({payload});
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def set_volume(self, volume_points: list[dict[str, Any]]) -> None:
|
def set_volume(self, volume_points: list[dict[str, Any]]) -> None:
|
||||||
payload = json.dumps(volume_points)
|
payload = json.dumps(volume_points)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.volumeSeries.setData({payload});
|
ref.volumeSeries.setData({payload});
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def update_volume(self, volume_point: dict[str, Any]) -> None:
|
def update_volume(self, volume_point: dict[str, Any]) -> None:
|
||||||
payload = json.dumps(volume_point)
|
payload = json.dumps(volume_point)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
ref.volumeSeries.update({payload});
|
ref.volumeSeries.update({payload});
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def set_indicator(
|
def set_indicator(
|
||||||
self,
|
self,
|
||||||
@@ -156,8 +144,7 @@ class CandlestickChart:
|
|||||||
) -> None:
|
) -> None:
|
||||||
key = json.dumps(name)
|
key = json.dumps(name)
|
||||||
payload = json.dumps(points)
|
payload = json.dumps(points)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
if (!ref) return;
|
if (!ref) return;
|
||||||
@@ -171,19 +158,16 @@ class CandlestickChart:
|
|||||||
}}
|
}}
|
||||||
ref.indicators[{key}].setData({payload});
|
ref.indicators[{key}].setData({payload});
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|
||||||
def update_indicator(self, name: str, point: dict[str, Any]) -> None:
|
def update_indicator(self, name: str, point: dict[str, Any]) -> None:
|
||||||
key = json.dumps(name)
|
key = json.dumps(name)
|
||||||
payload = json.dumps(point)
|
payload = json.dumps(point)
|
||||||
ui.run_javascript(
|
ui.run_javascript(f"""
|
||||||
f"""
|
|
||||||
(function() {{
|
(function() {{
|
||||||
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
const ref = window.vaultDashCharts?.[{json.dumps(self.chart_id)}];
|
||||||
const series = ref?.indicators?.[{key}];
|
const series = ref?.indicators?.[{key}];
|
||||||
if (!series) return;
|
if (!series) return;
|
||||||
series.update({payload});
|
series.update({payload});
|
||||||
}})();
|
}})();
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
|
|||||||
@@ -117,8 +117,7 @@ class StrategyComparisonPanel:
|
|||||||
scenario_class = (
|
scenario_class = (
|
||||||
"text-emerald-600 dark:text-emerald-400" if scenario >= 0 else "text-rose-600 dark:text-rose-400"
|
"text-emerald-600 dark:text-emerald-400" if scenario >= 0 else "text-rose-600 dark:text-rose-400"
|
||||||
)
|
)
|
||||||
rows.append(
|
rows.append(f"""
|
||||||
f"""
|
|
||||||
<tr class=\"border-b border-slate-200 dark:border-slate-800\">
|
<tr class=\"border-b border-slate-200 dark:border-slate-800\">
|
||||||
<td class=\"px-4 py-3 font-medium text-slate-900 dark:text-slate-100\">{name}</td>
|
<td class=\"px-4 py-3 font-medium text-slate-900 dark:text-slate-100\">{name}</td>
|
||||||
<td class=\"px-4 py-3 text-slate-600 dark:text-slate-300\">${cost:,.2f}</td>
|
<td class=\"px-4 py-3 text-slate-600 dark:text-slate-300\">${cost:,.2f}</td>
|
||||||
@@ -126,8 +125,7 @@ class StrategyComparisonPanel:
|
|||||||
<td class=\"px-4 py-3 text-slate-600 dark:text-slate-300\">{self._format_cap(strategy)}</td>
|
<td class=\"px-4 py-3 text-slate-600 dark:text-slate-300\">{self._format_cap(strategy)}</td>
|
||||||
<td class=\"px-4 py-3 font-semibold {scenario_class}\">${scenario:,.2f}</td>
|
<td class=\"px-4 py-3 font-semibold {scenario_class}\">${scenario:,.2f}</td>
|
||||||
</tr>
|
</tr>
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
return f"""
|
return f"""
|
||||||
<div class=\"overflow-x-auto\">
|
<div class=\"overflow-x-auto\">
|
||||||
<table class=\"min-w-full rounded-xl overflow-hidden\">
|
<table class=\"min-w-full rounded-xl overflow-hidden\">
|
||||||
|
|||||||
@@ -137,8 +137,7 @@ async def options_page() -> None:
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
"""
|
"""
|
||||||
+ "".join(
|
+ "".join(f"""
|
||||||
f"""
|
|
||||||
<tr class='border-b border-slate-200 dark:border-slate-800'>
|
<tr class='border-b border-slate-200 dark:border-slate-800'>
|
||||||
<td class='px-4 py-3 font-medium text-slate-900 dark:text-slate-100'>{row['symbol']}</td>
|
<td class='px-4 py-3 font-medium text-slate-900 dark:text-slate-100'>{row['symbol']}</td>
|
||||||
<td class='px-4 py-3 text-slate-600 dark:text-slate-300'>{row['type'].upper()}</td>
|
<td class='px-4 py-3 text-slate-600 dark:text-slate-300'>{row['type'].upper()}</td>
|
||||||
@@ -149,9 +148,7 @@ async def options_page() -> None:
|
|||||||
<td class='px-4 py-3 text-slate-600 dark:text-slate-300'>Δ {float(row.get('delta', 0.0)):+.3f} · Γ {float(row.get('gamma', 0.0)):.3f} · Θ {float(row.get('theta', 0.0)):+.3f} · V {float(row.get('vega', 0.0)):.3f}</td>
|
<td class='px-4 py-3 text-slate-600 dark:text-slate-300'>Δ {float(row.get('delta', 0.0)):+.3f} · Γ {float(row.get('gamma', 0.0)):.3f} · Θ {float(row.get('theta', 0.0)):+.3f} · V {float(row.get('vega', 0.0)):.3f}</td>
|
||||||
<td class='px-4 py-3 text-sky-600 dark:text-sky-300'>Use quick-add buttons below</td>
|
<td class='px-4 py-3 text-sky-600 dark:text-sky-300'>Use quick-add buttons below</td>
|
||||||
</tr>
|
</tr>
|
||||||
"""
|
""" for row in rows)
|
||||||
for row in rows
|
|
||||||
)
|
|
||||||
+ (
|
+ (
|
||||||
""
|
""
|
||||||
if rows
|
if rows
|
||||||
|
|||||||
@@ -124,13 +124,11 @@ def welcome_page(request: Request):
|
|||||||
if turnstile.uses_test_keys
|
if turnstile.uses_test_keys
|
||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
ui.html(
|
ui.html(f"""<form method="post" action="/workspaces/bootstrap" class="flex items-center gap-4">
|
||||||
f"""<form method="post" action="/workspaces/bootstrap" class="flex items-center gap-4">
|
|
||||||
{hidden_token}
|
{hidden_token}
|
||||||
<div class="cf-turnstile" data-sitekey="{turnstile.site_key}"></div>
|
<div class="cf-turnstile" data-sitekey="{turnstile.site_key}"></div>
|
||||||
<button type="submit" class="rounded-lg bg-slate-900 px-5 py-3 text-sm font-semibold text-white no-underline dark:bg-slate-100 dark:text-slate-900">Get started</button>
|
<button type="submit" class="rounded-lg bg-slate-900 px-5 py-3 text-sm font-semibold text-white no-underline dark:bg-slate-100 dark:text-slate-900">Get started</button>
|
||||||
</form>"""
|
</form>""")
|
||||||
)
|
|
||||||
ui.label("You can always create a fresh workspace later if a link is lost.").classes(
|
ui.label("You can always create a fresh workspace later if a link is lost.").classes(
|
||||||
"text-sm text-slate-500 dark:text-slate-400"
|
"text-sm text-slate-500 dark:text-slate-400"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
pytest>=8.0.0
|
pytest>=8.0.0
|
||||||
pytest-asyncio>=0.23.0
|
pytest-asyncio>=0.23.0
|
||||||
black>=24.0.0
|
black==26.3.1
|
||||||
ruff>=0.2.0
|
ruff>=0.2.0
|
||||||
mypy>=1.8.0
|
mypy>=1.8.0
|
||||||
types-requests>=2.31.0
|
types-requests>=2.31.0
|
||||||
|
|||||||
@@ -26,16 +26,14 @@ def test_overview_shows_ltv_history_and_exports_csv() -> None:
|
|||||||
expect(page.locator("text=90 Day").first).to_be_visible(timeout=15000)
|
expect(page.locator("text=90 Day").first).to_be_visible(timeout=15000)
|
||||||
expect(page.get_by_role("button", name="Export CSV")).to_be_visible(timeout=15000)
|
expect(page.get_by_role("button", name="Export CSV")).to_be_visible(timeout=15000)
|
||||||
|
|
||||||
series_names = page.evaluate(
|
series_names = page.evaluate("""
|
||||||
"""
|
|
||||||
async () => {
|
async () => {
|
||||||
const importMap = JSON.parse(document.querySelector('script[type="importmap"]').textContent).imports;
|
const importMap = JSON.parse(document.querySelector('script[type="importmap"]').textContent).imports;
|
||||||
const mod = await import(importMap['nicegui-echart']);
|
const mod = await import(importMap['nicegui-echart']);
|
||||||
const chart = mod.echarts.getInstanceByDom(document.querySelector('.nicegui-echart'));
|
const chart = mod.echarts.getInstanceByDom(document.querySelector('.nicegui-echart'));
|
||||||
return chart ? chart.getOption().series.map(series => series.name) : [];
|
return chart ? chart.getOption().series.map(series => series.name) : [];
|
||||||
}
|
}
|
||||||
"""
|
""")
|
||||||
)
|
|
||||||
assert series_names == ["LTV", "Margin threshold"]
|
assert series_names == ["LTV", "Margin threshold"]
|
||||||
|
|
||||||
with page.expect_download() as download_info:
|
with page.expect_download() as download_info:
|
||||||
|
|||||||
Reference in New Issue
Block a user