ci: scripts + format
This commit is contained in:
parent
f2e312f860
commit
8c8e49d75c
9 changed files with 1279 additions and 35 deletions
|
|
@ -7,8 +7,13 @@
|
||||||
"globals": ["vim"]
|
"globals": ["vim"]
|
||||||
},
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"library": ["$VIMRUNTIME/lua", "${3rd}/luv/library", "${3rd}/busted/library"],
|
"library": [
|
||||||
"checkThirdParty": false
|
"$VIMRUNTIME/lua",
|
||||||
|
"${3rd}/luv/library",
|
||||||
|
"${3rd}/busted/library"
|
||||||
|
],
|
||||||
|
"checkThirdParty": false,
|
||||||
|
"ignoreDir": [".direnv"]
|
||||||
},
|
},
|
||||||
"completion": {
|
"completion": {
|
||||||
"callSnippet": "Replace"
|
"callSnippet": "Replace"
|
||||||
|
|
|
||||||
1
.styluaignore
Normal file
1
.styluaignore
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
.direnv/
|
||||||
42
flake.nix
42
flake.nix
|
|
@ -26,10 +26,46 @@
|
||||||
ps.requests
|
ps.requests
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
mkSubmitEnv =
|
||||||
|
pkgs:
|
||||||
|
pkgs.buildFHSEnv {
|
||||||
|
name = "cp-nvim-submit";
|
||||||
|
targetPkgs =
|
||||||
|
pkgs: with pkgs; [
|
||||||
|
uv
|
||||||
|
alsa-lib
|
||||||
|
at-spi2-atk
|
||||||
|
cairo
|
||||||
|
cups
|
||||||
|
dbus
|
||||||
|
fontconfig
|
||||||
|
freetype
|
||||||
|
gdk-pixbuf
|
||||||
|
glib
|
||||||
|
gtk3
|
||||||
|
libdrm
|
||||||
|
libGL
|
||||||
|
libxkbcommon
|
||||||
|
mesa
|
||||||
|
nspr
|
||||||
|
nss
|
||||||
|
pango
|
||||||
|
xorg.libX11
|
||||||
|
xorg.libXcomposite
|
||||||
|
xorg.libXdamage
|
||||||
|
xorg.libXext
|
||||||
|
xorg.libXfixes
|
||||||
|
xorg.libXrandr
|
||||||
|
xorg.libxcb
|
||||||
|
];
|
||||||
|
runScript = "${pkgs.uv}/bin/uv";
|
||||||
|
};
|
||||||
|
|
||||||
mkPlugin =
|
mkPlugin =
|
||||||
pkgs:
|
pkgs:
|
||||||
let
|
let
|
||||||
pythonEnv = mkPythonEnv pkgs;
|
pythonEnv = mkPythonEnv pkgs;
|
||||||
|
submitEnv = mkSubmitEnv pkgs;
|
||||||
in
|
in
|
||||||
pkgs.vimUtils.buildVimPlugin {
|
pkgs.vimUtils.buildVimPlugin {
|
||||||
pname = "cp-nvim";
|
pname = "cp-nvim";
|
||||||
|
|
@ -39,12 +75,15 @@
|
||||||
substituteInPlace lua/cp/utils.lua \
|
substituteInPlace lua/cp/utils.lua \
|
||||||
--replace-fail "local _nix_python = nil" \
|
--replace-fail "local _nix_python = nil" \
|
||||||
"local _nix_python = '${pythonEnv.interpreter}'"
|
"local _nix_python = '${pythonEnv.interpreter}'"
|
||||||
|
substituteInPlace lua/cp/utils.lua \
|
||||||
|
--replace-fail "local _nix_submit_cmd = nil" \
|
||||||
|
"local _nix_submit_cmd = '${submitEnv}/bin/cp-nvim-submit'"
|
||||||
'';
|
'';
|
||||||
nvimSkipModule = [
|
nvimSkipModule = [
|
||||||
"cp.pickers.telescope"
|
"cp.pickers.telescope"
|
||||||
"cp.version"
|
"cp.version"
|
||||||
];
|
];
|
||||||
passthru = { inherit pythonEnv; };
|
passthru = { inherit pythonEnv submitEnv; };
|
||||||
meta.description = "Competitive programming plugin for Neovim";
|
meta.description = "Competitive programming plugin for Neovim";
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|
@ -58,6 +97,7 @@
|
||||||
packages = eachSystem (system: {
|
packages = eachSystem (system: {
|
||||||
default = mkPlugin (pkgsFor system);
|
default = mkPlugin (pkgsFor system);
|
||||||
pythonEnv = mkPythonEnv (pkgsFor system);
|
pythonEnv = mkPythonEnv (pkgsFor system);
|
||||||
|
submitEnv = mkSubmitEnv (pkgsFor system);
|
||||||
});
|
});
|
||||||
|
|
||||||
devShells = eachSystem (system: {
|
devShells = eachSystem (system: {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,12 @@ local function run_scraper(platform, subcommand, args, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
local plugin_path = utils.get_plugin_path()
|
local plugin_path = utils.get_plugin_path()
|
||||||
local cmd = utils.get_python_cmd(platform, plugin_path)
|
local cmd
|
||||||
|
if subcommand == 'submit' then
|
||||||
|
cmd = utils.get_python_submit_cmd(platform, plugin_path)
|
||||||
|
else
|
||||||
|
cmd = utils.get_python_cmd(platform, plugin_path)
|
||||||
|
end
|
||||||
vim.list_extend(cmd, { subcommand })
|
vim.list_extend(cmd, { subcommand })
|
||||||
vim.list_extend(cmd, args)
|
vim.list_extend(cmd, args)
|
||||||
|
|
||||||
|
|
@ -62,6 +67,10 @@ local function run_scraper(platform, subcommand, args, opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if subcommand == 'submit' and utils.is_nix_build() then
|
||||||
|
env.UV_PROJECT_ENVIRONMENT = vim.fn.stdpath('cache') .. '/cp-nvim/submit-env'
|
||||||
|
end
|
||||||
|
|
||||||
if opts and opts.ndjson then
|
if opts and opts.ndjson then
|
||||||
local uv = vim.uv
|
local uv = vim.uv
|
||||||
local stdout = uv.new_pipe(false)
|
local stdout = uv.new_pipe(false)
|
||||||
|
|
@ -131,7 +140,12 @@ local function run_scraper(platform, subcommand, args, opts)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local sysopts = { text = true, timeout = 30000, env = env, cwd = plugin_path }
|
local sysopts = {
|
||||||
|
text = true,
|
||||||
|
timeout = (subcommand == 'submit') and 120000 or 30000,
|
||||||
|
env = env,
|
||||||
|
cwd = plugin_path,
|
||||||
|
}
|
||||||
if opts and opts.stdin then
|
if opts and opts.stdin then
|
||||||
sysopts.stdin = opts.stdin
|
sysopts.stdin = opts.stdin
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ local M = {}
|
||||||
local logger = require('cp.log')
|
local logger = require('cp.log')
|
||||||
|
|
||||||
local _nix_python = nil
|
local _nix_python = nil
|
||||||
|
local _nix_submit_cmd = nil
|
||||||
local _nix_discovered = false
|
local _nix_discovered = false
|
||||||
|
|
||||||
local uname = vim.uv.os_uname()
|
local uname = vim.uv.os_uname()
|
||||||
|
|
@ -111,6 +112,16 @@ function M.get_python_cmd(module, plugin_path)
|
||||||
return { 'uv', 'run', '--directory', plugin_path, '-m', 'scrapers.' .. module }
|
return { 'uv', 'run', '--directory', plugin_path, '-m', 'scrapers.' .. module }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param module string
|
||||||
|
---@param plugin_path string
|
||||||
|
---@return string[]
|
||||||
|
function M.get_python_submit_cmd(module, plugin_path)
|
||||||
|
if _nix_submit_cmd then
|
||||||
|
return { _nix_submit_cmd, 'run', '--directory', plugin_path, '-m', 'scrapers.' .. module }
|
||||||
|
end
|
||||||
|
return M.get_python_cmd(module, plugin_path)
|
||||||
|
end
|
||||||
|
|
||||||
local python_env_setup = false
|
local python_env_setup = false
|
||||||
|
|
||||||
---@return boolean
|
---@return boolean
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backoff>=2.2.1",
|
"backoff>=2.2.1",
|
||||||
"beautifulsoup4>=4.13.5",
|
"beautifulsoup4>=4.13.5",
|
||||||
|
"camoufox[geoip]",
|
||||||
"curl-cffi>=0.13.0",
|
"curl-cffi>=0.13.0",
|
||||||
"httpx>=0.28.1",
|
"httpx>=0.28.1",
|
||||||
"ndjson>=0.3.1",
|
"ndjson>=0.3.1",
|
||||||
|
|
|
||||||
|
|
@ -380,41 +380,34 @@ class AtcoderScraper(BaseScraper):
|
||||||
credentials: dict[str, str],
|
credentials: dict[str, str],
|
||||||
) -> SubmitResult:
|
) -> SubmitResult:
|
||||||
def _submit_sync() -> SubmitResult:
|
def _submit_sync() -> SubmitResult:
|
||||||
|
try:
|
||||||
|
from camoufox.sync_api import Camoufox
|
||||||
|
except ImportError:
|
||||||
|
return SubmitResult(
|
||||||
|
success=False,
|
||||||
|
error="camoufox is required for AtCoder login. Install it: uv add 'camoufox[geoip]'",
|
||||||
|
)
|
||||||
|
|
||||||
from curl_cffi import requests as curl_requests
|
from curl_cffi import requests as curl_requests
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
with Camoufox(headless=True) as browser:
|
||||||
|
page = browser.new_page()
|
||||||
|
page.goto(f"{BASE_URL}/login", wait_until="domcontentloaded")
|
||||||
|
page.wait_for_load_state("networkidle")
|
||||||
|
page.fill('input[name="username"]', credentials.get("username", ""))
|
||||||
|
page.fill('input[name="password"]', credentials.get("password", ""))
|
||||||
|
page.click('#submit')
|
||||||
|
page.wait_for_url(lambda url: "/login" not in url, timeout=30000)
|
||||||
|
cookies = page.context.cookies()
|
||||||
|
|
||||||
session = curl_requests.Session(impersonate="chrome")
|
session = curl_requests.Session(impersonate="chrome")
|
||||||
|
for cookie in cookies:
|
||||||
login_page = session.get(f"{BASE_URL}/login", timeout=TIMEOUT_SECONDS)
|
session.cookies.set(
|
||||||
login_page.raise_for_status()
|
cookie["name"],
|
||||||
soup = BeautifulSoup(login_page.text, "html.parser")
|
cookie["value"],
|
||||||
csrf_input = soup.find("input", {"name": "csrf_token"})
|
domain=cookie.get("domain", ""),
|
||||||
if not csrf_input or not hasattr(csrf_input, "get"):
|
|
||||||
return SubmitResult(
|
|
||||||
success=False, error="Could not find CSRF token on login page"
|
|
||||||
)
|
)
|
||||||
csrf_token = csrf_input.get("value", "") or "" # type: ignore[union-attr]
|
|
||||||
|
|
||||||
login_resp = session.post(
|
|
||||||
f"{BASE_URL}/login",
|
|
||||||
data={
|
|
||||||
"username": credentials.get("username", ""),
|
|
||||||
"password": credentials.get("password", ""),
|
|
||||||
"csrf_token": csrf_token,
|
|
||||||
},
|
|
||||||
timeout=TIMEOUT_SECONDS,
|
|
||||||
allow_redirects=False,
|
|
||||||
)
|
|
||||||
if login_resp.status_code in (301, 302):
|
|
||||||
location = login_resp.headers.get("Location", "")
|
|
||||||
if "/login" in location:
|
|
||||||
return SubmitResult(
|
|
||||||
success=False,
|
|
||||||
error="Login failed: incorrect username or password",
|
|
||||||
)
|
|
||||||
session.get(BASE_URL + location, timeout=TIMEOUT_SECONDS)
|
|
||||||
else:
|
|
||||||
login_resp.raise_for_status()
|
|
||||||
|
|
||||||
submit_page = session.get(
|
submit_page = session.get(
|
||||||
f"{BASE_URL}/contests/{contest_id}/submit",
|
f"{BASE_URL}/contests/{contest_id}/submit",
|
||||||
|
|
|
||||||
11
scripts/ci.sh
Executable file
11
scripts/ci.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
nix develop --command stylua --check .
|
||||||
|
git ls-files '*.lua' | xargs nix develop --command selene --display-style quiet
|
||||||
|
nix develop --command prettier --check .
|
||||||
|
nix develop --command lua-language-server --check . --checklevel=Warning
|
||||||
|
nix develop --command uvx ruff format --check .
|
||||||
|
nix develop --command uvx ruff check .
|
||||||
|
nix develop --command uvx ty check .
|
||||||
|
nix develop --command uv run pytest tests/ -v
|
||||||
Loading…
Add table
Add a link
Reference in a new issue