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:
Bu5hm4nn
2026-04-01 13:58:49 +02:00
parent 6bcf78e5df
commit dbd6e103c0
7 changed files with 28 additions and 52 deletions

View File

@@ -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:

View File

@@ -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});
}})(); }})();
""" """)
)

View File

@@ -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\">

View File

@@ -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

View File

@@ -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"
) )

View File

@@ -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

View File

@@ -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: