diff --git a/.env.example b/.env.example index 5f8e07890..f6a88375f 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ FORK_URL= NODE_ENV= +DEV_RPC= STAKING_TEST_KEYS_PATH= -DEV_RPC= \ No newline at end of file +IS_STAGING= diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 000000000..58691e7b4 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,29 @@ +name: "Test Operate Installation E2E" +on: + push: + branches: + - develop + - main + pull_request: +jobs: + test: + continue-on-error: False + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-12, macos-14] + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: "20.11" + - name: Setup + run: | + npm install + # Uninstall brew + sudo bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" + - name: Run Test + run: | + node electron/test.js diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9737db6c3..71bf0b5f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,6 +63,7 @@ jobs: env: NODE_ENV: production DEV_RPC: https://rpc-gate.autonolas.tech/gnosis-rpc/ + IS_STAGING: ${{ github.ref != 'refs/heads/main' && 'true' || 'false' }} FORK_URL: https://rpc-gate.autonolas.tech/gnosis-rpc/ - run: rm -rf /dist - name: "Build, notarize, publish" diff --git a/.gitleaksignore b/.gitleaksignore index 158702af9..d5ebe0a15 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -22,8 +22,9 @@ d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api- d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:406 d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:454 d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:455 -91ec07457f69e9a29f63693ac8ef887e4b5f49f0:operate/services/manage.py:generic-api-key:454 +d8149e9b5b7bd6a7ed7bc1039900702f1d4f287b:operate/services/manage.py:generic-api-key:45591ec07457f69e9a29f63693ac8ef887e4b5f49f0:operate/services/manage.py:generic-api-key:454 99c0f139b037da2587708212fcf6d0e20786d0ba:operate/services/manage.py:generic-api-key:405 99c0f139b037da2587708212fcf6d0e20786d0ba:operate/services/manage.py:generic-api-key:406 99c0f139b037da2587708212fcf6d0e20786d0ba:operate/services/manage.py:generic-api-key:454 99c0f139b037da2587708212fcf6d0e20786d0ba:operate/services/manage.py:generic-api-key:455 +91ec07457f69e9a29f63693ac8ef887e4b5f49f0:operate/services/manage.py:generic-api-key:454 diff --git a/build.js b/build.js index 29e953fc4..a5059c953 100644 --- a/build.js +++ b/build.js @@ -1,6 +1,6 @@ const dotenv = require('dotenv'); const build = require('electron-builder').build; -const {publishOptions} = require('./electron/constants/publishOptions'); +const { publishOptions } = require('./electron/constants/publishOptions'); dotenv.config(); @@ -24,7 +24,7 @@ const main = async () => { target: [ { target: 'default', - arch: ['x64','arm64'], + arch: ['x64', 'arm64'], }, ], publish: publishOptions, @@ -35,11 +35,11 @@ const main = async () => { entitlements: 'electron/entitlements.mac.plist', entitlementsInherit: 'electron/entitlements.mac.plist', notarize: { - teamId: process.env.APPLETEAMID + teamId: process.env.APPLETEAMID, }, }, }, }); }; -main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); \ No newline at end of file +main().then((response) => { console.log('Build & Notarize complete'); }).catch((e) => console.error(e)); diff --git a/electron/install.js b/electron/install.js index 042f5ba28..90e19fd99 100644 --- a/electron/install.js +++ b/electron/install.js @@ -1,7 +1,6 @@ // Installation helpers. -const https = require('https'); -const path = require('path'); +const nfs = require('node:fs') const fs = require('fs'); const os = require('os'); const sudo = require('sudo-prompt'); @@ -10,8 +9,14 @@ const axios = require('axios'); const Docker = require('dockerode'); const { spawnSync } = require('child_process'); - -const Version = '0.1.0rc45'; +const { BrewScript } = require("./scripts") + +/** + * current version of the pearl release + * - use "" (nothing as a suffix) for latest release candidate, for example "0.1.0rc26" + * - use "alpha" for alpha release, for example "0.1.0rc26-alpha" + */ +const OlasMiddlewareVersion = '0.1.0rc45'; const OperateDirectory = `${os.homedir()}/.operate`; const VenvDir = `${OperateDirectory}/venv`; const TempDir = `${OperateDirectory}/temp`; @@ -22,6 +27,7 @@ const OperateCmd = `${os.homedir()}/.operate/venv/bin/operate`; const Env = { ...process.env, PATH: `${process.env.PATH}:/opt/homebrew/bin:/usr/local/bin`, + HOMEBREW_NO_AUTO_UPDATE: '1', }; const SudoOptions = { name: 'Pearl', @@ -66,33 +72,23 @@ function appendLog(log) { } function runCmdUnix(command, options) { - fs.appendFileSync( - OperateInstallationLog, - `Runninng ${command} with options ${JSON.stringify(options)}`, - { encoding: 'utf-8' }, + console.log( + appendLog(`Running ${command} with options ${JSON.stringify(options)}`), ); let bin = getBinPath(command); if (!bin) { throw new Error(`Command ${command} not found; Path : ${Env.PATH}`); } let output = spawnSync(bin, options); - if (output.stdout) { - appendLog(output.stdout.toString()); - } - if (output.stderr) { - appendLog(output.stdout.toString()); - } if (output.error) { throw new Error( `Error running ${command} with options ${options}; Error: ${output.error}; Stdout: ${output.stdout}; Stderr: ${output.stderr}`, ); } - return { - error: output.error, - stdout: output.stdout?.toString(), - stderr: output.stderr?.toString(), - }; + console.log(appendLog(`Executed ${command} ${options} with`)) + console.log(appendLog(`===== stdout ===== \n${output.stdout}`)) + console.log(appendLog(`===== stderr ===== \n${output.stderr}`)) } function runSudoUnix(command, options) { @@ -100,16 +96,26 @@ function runSudoUnix(command, options) { if (!bin) { throw new Error(`Command ${command} not found`); } - return new Promise(function (resolve, reject) { + return new Promise(function (resolve, _reject) { sudo.exec( `${bin} ${options}`, SudoOptions, function (error, stdout, stderr) { - resolve({ + let output = { error: error, stdout: stdout, stderr: stderr, - }); + }; + if (output.error) { + throw new Error( + `Error running ${command} with options ${options}; + Error: ${output.error}; Stdout: ${output.stdout}; Stderr: ${output.stderr}`, + ); + } + console.log(appendLog(`Executed ${command} ${options} with`)) + console.log(appendLog(`===== stdout ===== \n${output.stdout}`)) + console.log(appendLog(`===== stderr ===== \n${output.stderr}`)) + resolve() }, ); }); @@ -119,11 +125,38 @@ function isBrewInstalled() { return Boolean(getBinPath(getBinPath('brew'))); } -function installBrew() { - return runCmdUnix('bash', [ - '-c', - '$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)', - ]); +async function installBrew() { + console.log(appendLog("Fetching homebrew source")) + let outdir = `${os.homedir()}/homebrew` + let outfile = `${os.homedir()}/homebrew.tar` + + // Make temporary source dir + fs.mkdirSync(outdir) + + // Fetch brew source + runCmdUnix("curl", ["-L", "https://github.com/Homebrew/brew/tarball/master", "--output", outfile]) + runCmdUnix("tar", ["-xvf", outfile, "--strip-components", "1", "-C", outdir]) + + // Check for cache and uninstall leftovers + if (fs.existsSync("/opt/homebrew")) { + console.log(appendLog("Removing homebrew leftovers")) + if (!Env.CI) { + await runSudoUnix("rm", `-rf /opt/homebrew`) + } else { + fs.rmdirSync("/opt/homebrew") + } + } + + console.log(appendLog("Installing homebrew")) + if (!Env.CI) { + await runSudoUnix("mv", `${outdir} /opt/homebrew`) + await runSudoUnix("chown", `-R ${os.userInfo().username} /opt/homebrew`) + } else { + runCmdUnix("mv", [outdir, "/opt/homebrew"]) + runCmdUnix("chown", ["-R", os.userInfo().username, "/opt/homebrew"]) + } + runCmdUnix("brew", ["doctor"]) + fs.rmSync(outfile) } function isTendermintInstalledUnix() { @@ -162,8 +195,15 @@ async function installTendermintUnix() { await downloadFile(url, `${TempDir}/tendermint.tar.gz`); console.log(appendLog(`Installing tendermint binary`)); - await runCmdUnix('tar', ['-xvf', 'tendermint.tar.gz']); - await runSudoUnix('install', 'tendermint /usr/local/bin'); + runCmdUnix('tar', ['-xvf', 'tendermint.tar.gz']); + + // TOFIX: Install tendermint in .operate instead of globally + if (!Env.CI) { + if (!fs.existsSync("/usr/local/bin")) { + await runSudoUnix('mkdir', '/usr/local/bin') + } + await runSudoUnix('install', 'tendermint /usr/local/bin/tendermint'); + } process.chdir(cwd); } @@ -172,7 +212,7 @@ function isDockerInstalledDarwin() { } function installDockerDarwin() { - return runCmdUnix('brew', ['install', 'docker']); + runCmdUnix('brew', ['install', 'docker']); } function isDockerInstalledUbuntu() { @@ -188,11 +228,11 @@ function isPythonInstalledDarwin() { } function installPythonDarwin() { - return runCmdUnix('brew', ['install', 'python@3.10']); + runCmdUnix('brew', ['install', 'python@3.10']); } function createVirtualEnvUnix(path) { - return runCmdUnix('python3.10', ['-m', 'venv', path]); + runCmdUnix('python3.10', ['-m', 'venv', path]); } function isPythonInstalledUbuntu() { @@ -212,25 +252,25 @@ function installGitUbuntu() { } function createVirtualEnvUbuntu(path) { - return runCmdUnix('python3.10', ['-m', 'venv', path]); + runCmdUnix('python3.10', ['-m', 'venv', path]); } function installOperatePackageUnix(path) { - return runCmdUnix(`${path}/venv/bin/python3.10`, [ + runCmdUnix(`${path}/venv/bin/python3.10`, [ '-m', 'pip', 'install', - `olas-operate-middleware==${Version}`, + `olas-operate-middleware==${OlasMiddlewareVersion}`, ]); } function reInstallOperatePackageUnix(path) { console.log(appendLog('Reinstalling pearl CLI')); - return runCmdUnix(`${path}/venv/bin/python3.10`, [ + runCmdUnix(`${path}/venv/bin/python3.10`, [ '-m', 'pip', 'install', - `olas-operate-middleware==${Version}`, + `olas-operate-middleware==${OlasMiddlewareVersion}`, '--force-reinstall', ]); } @@ -240,11 +280,11 @@ function installOperateCli(path) { if (fs.existsSync(installPath)) { fs.rmSync(installPath); } - return new Promise((resolve, reject) => { + return new Promise((resolve, _reject) => { fs.copyFile( `${OperateDirectory}/venv/bin/operate`, installPath, - function (error, stdout, stderr) { + function (error, _stdout, _stderr) { resolve(!error); }, ); @@ -255,7 +295,7 @@ function createDirectory(path) { if (fs.existsSync(path)) { return; } - return new Promise((resolve, reject) => { + return new Promise((resolve, _reject) => { fs.mkdir(path, { recursive: true }, (error) => { resolve(!error); }); @@ -263,15 +303,15 @@ function createDirectory(path) { } function writeVersion() { - fs.writeFileSync(VersionFile, Version); + fs.writeFileSync(VersionFile, OlasMiddlewareVersion); } function versionBumpRequired() { if (!fs.existsSync(VersionFile)) { return true; } - const version = fs.readFileSync(VersionFile).toString(); - return version != Version; + const olasMiddlewareVersionInFile = fs.readFileSync(VersionFile).toString(); + return olasMiddlewareVersionInFile != OlasMiddlewareVersion; } function removeLogFile() { @@ -296,7 +336,7 @@ async function setupDarwin(ipcChannel) { if (!isBrewInstalled()) { ipcChannel.send('response', 'Installing Pearl Daemon'); console.log(appendLog('Installing brew')); - installBrew(); + await installBrew(); } console.log(appendLog('Checking python installation')); @@ -328,7 +368,9 @@ async function setupDarwin(ipcChannel) { console.log(appendLog('Checking if upgrade is required')); if (versionBumpRequired()) { - console.log(appendLog(`Upgrading pearl daemon to ${Version}`)); + console.log( + appendLog(`Upgrading pearl daemon to ${OlasMiddlewareVersion}`), + ); reInstallOperatePackageUnix(OperateDirectory); writeVersion(); removeLogFile(); @@ -382,7 +424,9 @@ async function setupUbuntu(ipcChannel) { console.log(appendLog('Checking if upgrade is required')); if (versionBumpRequired()) { - console.log(appendLog(`Upgrading pearl daemon to ${Version}`)); + console.log( + appendLog(`Upgrading pearl daemon to ${OlasMiddlewareVersion}`), + ); reInstallOperatePackageUnix(OperateDirectory); writeVersion(); removeLogFile(); @@ -435,4 +479,4 @@ module.exports = { LogFile, OperateInstallationLog, }, -}; +}; \ No newline at end of file diff --git a/electron/main.js b/electron/main.js index faf838883..ab1b8abcc 100644 --- a/electron/main.js +++ b/electron/main.js @@ -259,7 +259,10 @@ const createMainWindow = () => { mainWindow.hide(); }); - setupStoreIpc(ipcMain, mainWindow); + const storeInitialValues = { + environmentName: process.env.IS_STAGING ? 'staging' : '', + }; + setupStoreIpc(ipcMain, mainWindow, storeInitialValues); if (isDev) { mainWindow.webContents.openDevTools(); diff --git a/electron/scripts.js b/electron/scripts.js new file mode 100644 index 000000000..d3f388aa7 --- /dev/null +++ b/electron/scripts.js @@ -0,0 +1,1098 @@ +const BrewScript = "# We don't need return codes for \"$(command)\", only stdout is needed.\n" + +"# Allow `[[ -n \"$(command)\" ]]`, `func \"$(command)\"`, pipes, etc.\n" + +"# shellcheck disable=SC2312\n" + +"\n" + +"set -u\n" + +"\n" + +"abort() {\n" + +" printf \"%s\\n\" \"$@\" >&2\n" + +" exit 1\n" + +"}\n" + +"\n" + +"# Fail fast with a concise message when not using bash\n" + +"# Single brackets are needed here for POSIX compatibility\n" + +"# shellcheck disable=SC2292\n" + +"if [ -z \"${BASH_VERSION:-}\" ]\n" + +"then\n" + +" abort \"Bash is required to interpret this script.\"\n" + +"fi\n" + +"\n" + +"# Check if script is run with force-interactive mode in CI\n" + +"if [[ -n \"${CI-}\" && -n \"${INTERACTIVE-}\" ]]\n" + +"then\n" + +" abort \"Cannot run force-interactive mode in CI.\"\n" + +"fi\n" + +"\n" + +"# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set\n" + +"# Always use single-quoted strings with `exp` expressions\n" + +"# shellcheck disable=SC2016\n" + +"if [[ -n \"${INTERACTIVE-}\" && -n \"${NONINTERACTIVE-}\" ]]\n" + +"then\n" + +" abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.'\n" + +"fi\n" + +"\n" + +"# Check if script is run in POSIX mode\n" + +"if [[ -n \"${POSIXLY_CORRECT+1}\" ]]\n" + +"then\n" + +" abort 'Bash must not run in POSIX mode. Please unset POSIXLY_CORRECT and try again.'\n" + +"fi\n" + +"\n" + +"usage() {\n" + +" cat <${tty_bold} %s${tty_reset}\\n\" \"$(shell_join \"$@\")\"\n" + +"}\n" + +"\n" + +"warn() {\n" + +" printf \"${tty_red}Warning${tty_reset}: %s\\n\" \"$(chomp \"$1\")\" >&2\n" + +"}\n" + +"\n" + +"# Check if script is run non-interactively (e.g. CI)\n" + +"# If it is run non-interactively we should not prompt for passwords.\n" + +"# Always use single-quoted strings with `exp` expressions\n" + +"# shellcheck disable=SC2016\n" + +"if [[ -z \"${NONINTERACTIVE-}\" ]]\n" + +"then\n" + +" if [[ -n \"${CI-}\" ]]\n" + +" then\n" + +" warn 'Running in non-interactive mode because `$CI` is set.'\n" + +" NONINTERACTIVE=1\n" + +" elif [[ ! -t 0 ]]\n" + +" then\n" + +" if [[ -z \"${INTERACTIVE-}\" ]]\n" + +" then\n" + +" warn 'Running in non-interactive mode because `stdin` is not a TTY.'\n" + +" NONINTERACTIVE=1\n" + +" else\n" + +" warn 'Running in interactive mode despite `stdin` not being a TTY because `$INTERACTIVE` is set.'\n" + +" fi\n" + +" fi\n" + +"else\n" + +" ohai 'Running in non-interactive mode because `$NONINTERACTIVE` is set.'\n" + +"fi\n" + +"\n" + +"# USER isn't always set so provide a fall back for the installer and subprocesses.\n" + +"if [[ -z \"${USER-}\" ]]\n" + +"then\n" + +" USER=\"$(chomp \"$(id -un)\")\"\n" + +" export USER\n" + +"fi\n" + +"\n" + +"# First check OS.\n" + +"OS=\"$(uname)\"\n" + +"if [[ \"${OS}\" == \"Linux\" ]]\n" + +"then\n" + +" HOMEBREW_ON_LINUX=1\n" + +"elif [[ \"${OS}\" == \"Darwin\" ]]\n" + +"then\n" + +" HOMEBREW_ON_MACOS=1\n" + +"else\n" + +" abort \"Homebrew is only supported on macOS and Linux.\"\n" + +"fi\n" + +"\n" + +"# Required installation paths. To install elsewhere (which is unsupported)\n" + +"# you can untar https://github.com/Homebrew/brew/tarball/master\n" + +"# anywhere you like.\n" + +"if [[ -n \"${HOMEBREW_ON_MACOS-}\" ]]\n" + +"then\n" + +" UNAME_MACHINE=\"$(/usr/bin/uname -m)\"\n" + +"\n" + +" if [[ \"${UNAME_MACHINE}\" == \"arm64\" ]]\n" + +" then\n" + +" # On ARM macOS, this script installs to /opt/homebrew only\n" + +" HOMEBREW_PREFIX=\"/opt/homebrew\"\n" + +" HOMEBREW_REPOSITORY=\"${HOMEBREW_PREFIX}\"\n" + +" else\n" + +" # On Intel macOS, this script installs to /usr/local only\n" + +" HOMEBREW_PREFIX=\"/usr/local\"\n" + +" HOMEBREW_REPOSITORY=\"${HOMEBREW_PREFIX}/Homebrew\"\n" + +" fi\n" + +" HOMEBREW_CACHE=\"${HOME}/Library/Caches/Homebrew\"\n" + +"\n" + +" STAT_PRINTF=(\"/usr/bin/stat\" \"-f\")\n" + +" PERMISSION_FORMAT=\"%A\"\n" + +" CHOWN=(\"/usr/sbin/chown\")\n" + +" CHGRP=(\"/usr/bin/chgrp\")\n" + +" GROUP=\"admin\"\n" + +" TOUCH=(\"/usr/bin/touch\")\n" + +" INSTALL=(\"/usr/bin/install\" -d -o \"root\" -g \"wheel\" -m \"0755\")\n" + +"else\n" + +" UNAME_MACHINE=\"$(uname -m)\"\n" + +"\n" + +" # On Linux, this script installs to /home/linuxbrew/.linuxbrew only\n" + +" HOMEBREW_PREFIX=\"/home/linuxbrew/.linuxbrew\"\n" + +" HOMEBREW_REPOSITORY=\"${HOMEBREW_PREFIX}/Homebrew\"\n" + +" HOMEBREW_CACHE=\"${HOME}/.cache/Homebrew\"\n" + +"\n" + +" STAT_PRINTF=(\"/usr/bin/stat\" \"--printf\")\n" + +" PERMISSION_FORMAT=\"%a\"\n" + +" CHOWN=(\"/bin/chown\")\n" + +" CHGRP=(\"/bin/chgrp\")\n" + +" GROUP=\"$(id -gn)\"\n" + +" TOUCH=(\"/bin/touch\")\n" + +" INSTALL=(\"/usr/bin/install\" -d -o \"${USER}\" -g \"${GROUP}\" -m \"0755\")\n" + +"fi\n" + +"CHMOD=(\"/bin/chmod\")\n" + +"MKDIR=(\"/bin/mkdir\" \"-p\")\n" + +"HOMEBREW_BREW_DEFAULT_GIT_REMOTE=\"https://github.com/Homebrew/brew\"\n" + +"HOMEBREW_CORE_DEFAULT_GIT_REMOTE=\"https://github.com/Homebrew/homebrew-core\"\n" + +"\n" + +"# Use remote URLs of Homebrew repositories from environment if set.\n" + +"HOMEBREW_BREW_GIT_REMOTE=\"${HOMEBREW_BREW_GIT_REMOTE:-\"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}\"}\"\n" + +"HOMEBREW_CORE_GIT_REMOTE=\"${HOMEBREW_CORE_GIT_REMOTE:-\"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}\"}\"\n" + +"# The URLs with and without the '.git' suffix are the same Git remote. Do not prompt.\n" + +"if [[ \"${HOMEBREW_BREW_GIT_REMOTE}\" == \"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}.git\" ]]\n" + +"then\n" + +" HOMEBREW_BREW_GIT_REMOTE=\"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}\"\n" + +"fi\n" + +"if [[ \"${HOMEBREW_CORE_GIT_REMOTE}\" == \"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}.git\" ]]\n" + +"then\n" + +" HOMEBREW_CORE_GIT_REMOTE=\"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}\"\n" + +"fi\n" + +"export HOMEBREW_{BREW,CORE}_GIT_REMOTE\n" + +"\n" + +"# TODO: bump version when new macOS is released or announced\n" + +"MACOS_NEWEST_UNSUPPORTED=\"15.0\"\n" + +"# TODO: bump version when new macOS is released\n" + +"MACOS_OLDEST_SUPPORTED=\"12.0\"\n" + +"\n" + +"# For Homebrew on Linux\n" + +"REQUIRED_RUBY_VERSION=2.6 # https://github.com/Homebrew/brew/pull/6556\n" + +"REQUIRED_GLIBC_VERSION=2.13 # https://docs.brew.sh/Homebrew-on-Linux#requirements\n" + +"REQUIRED_CURL_VERSION=7.41.0 # HOMEBREW_MINIMUM_CURL_VERSION in brew.sh in Homebrew/brew\n" + +"REQUIRED_GIT_VERSION=2.7.0 # HOMEBREW_MINIMUM_GIT_VERSION in brew.sh in Homebrew/brew\n" + +"\n" + +"# no analytics during installation\n" + +"export HOMEBREW_NO_ANALYTICS_THIS_RUN=1\n" + +"export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1\n" + +"\n" + +"unset HAVE_SUDO_ACCESS # unset this from the environment\n" + +"\n" + +"have_sudo_access() {\n" + +" if [[ ! -x \"/usr/bin/sudo\" ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" local -a SUDO=(\"/usr/bin/sudo\")\n" + +" if [[ -n \"${SUDO_ASKPASS-}\" ]]\n" + +" then\n" + +" SUDO+=(\"-A\")\n" + +" elif [[ -n \"${NONINTERACTIVE-}\" ]]\n" + +" then\n" + +" SUDO+=(\"-n\")\n" + +" fi\n" + +"\n" + +" if [[ -z \"${HAVE_SUDO_ACCESS-}\" ]]\n" + +" then\n" + +" if [[ -n \"${NONINTERACTIVE-}\" ]]\n" + +" then\n" + +" \"${SUDO[@]}\" -l mkdir &>/dev/null\n" + +" else\n" + +" \"${SUDO[@]}\" -v && \"${SUDO[@]}\" -l mkdir &>/dev/null\n" + +" fi\n" + +" HAVE_SUDO_ACCESS=\"$?\"\n" + +" fi\n" + +"\n" + +" if [[ -n \"${HOMEBREW_ON_MACOS-}\" ]] && [[ \"${HAVE_SUDO_ACCESS}\" -ne 0 ]]\n" + +" then\n" + +" abort \"Need sudo access on macOS (e.g. the user ${USER} needs to be an Administrator)!\"\n" + +" fi\n" + +"\n" + +" return \"${HAVE_SUDO_ACCESS}\"\n" + +"}\n" + +"\n" + +"execute() {\n" + +" if ! \"$@\"\n" + +" then\n" + +" abort \"$(printf \"Failed during: %s\" \"$(shell_join \"$@\")\")\"\n" + +" fi\n" + +"}\n" + +"\n" + +"execute_sudo() {\n" + +" local -a args=(\"$@\")\n" + +" if [[ \"${EUID:-${UID}}\" != \"0\" ]] && have_sudo_access\n" + +" then\n" + +" if [[ -n \"${SUDO_ASKPASS-}\" ]]\n" + +" then\n" + +" args=(\"-A\" \"${args[@]}\")\n" + +" fi\n" + +" ohai \"/usr/bin/sudo\" \"${args[@]}\"\n" + +" execute \"/usr/bin/sudo\" \"${args[@]}\"\n" + +" else\n" + +" ohai \"${args[@]}\"\n" + +" execute \"${args[@]}\"\n" + +" fi\n" + +"}\n" + +"\n" + +"getc() {\n" + +" local save_state\n" + +" save_state=\"$(/bin/stty -g)\"\n" + +" /bin/stty raw -echo\n" + +" IFS='' read -r -n 1 -d '' \"$@\"\n" + +" /bin/stty \"${save_state}\"\n" + +"}\n" + +"\n" + +"ring_bell() {\n" + +" # Use the shell's audible bell.\n" + +" if [[ -t 1 ]]\n" + +" then\n" + +" printf \"\\a\"\n" + +" fi\n" + +"}\n" + +"\n" + +"wait_for_user() {\n" + +" local c\n" + +" echo\n" + +" echo \"Press ${tty_bold}RETURN${tty_reset}/${tty_bold}ENTER${tty_reset} to continue or any other key to abort:\"\n" + +" getc c\n" + +" if ! [[ \"${c}\" == $'\\r' || \"${c}\" == $'\\n' ]]\n" + +" then\n" + +" exit 1\n" + +" fi\n" + +"}\n" + +"\n" + +"major_minor() {\n" + +" echo \"${1%%.*}.$(\n" + +" x=\"${1#*.}\"\n" + +" echo \"${x%%.*}\"\n" + +" )\"\n" + +"}\n" + +"\n" + +"version_gt() {\n" + +" [[ \"${1%.*}\" -gt \"${2%.*}\" ]] || [[ \"${1%.*}\" -eq \"${2%.*}\" && \"${1#*.}\" -gt \"${2#*.}\" ]]\n" + +"}\n" + +"version_ge() {\n" + +" [[ \"${1%.*}\" -gt \"${2%.*}\" ]] || [[ \"${1%.*}\" -eq \"${2%.*}\" && \"${1#*.}\" -ge \"${2#*.}\" ]]\n" + +"}\n" + +"version_lt() {\n" + +" [[ \"${1%.*}\" -lt \"${2%.*}\" ]] || [[ \"${1%.*}\" -eq \"${2%.*}\" && \"${1#*.}\" -lt \"${2#*.}\" ]]\n" + +"}\n" + +"\n" + +"check_run_command_as_root() {\n" + +" [[ \"${EUID:-${UID}}\" == \"0\" ]] || return\n" + +"\n" + +" # Allow Azure Pipelines/GitHub Actions/Docker/Concourse/Kubernetes to do everything as root (as it's normal there)\n" + +" [[ -f /.dockerenv ]] && return\n" + +" [[ -f /run/.containerenv ]] && return\n" + +" [[ -f /proc/1/cgroup ]] && grep -E \"azpl_job|actions_job|docker|garden|kubepods\" -q /proc/1/cgroup && return\n" + +"\n" + +" abort \"Don't run this as root!\"\n" + +"}\n" + +"\n" + +"should_install_command_line_tools() {\n" + +" if [[ -n \"${HOMEBREW_ON_LINUX-}\" ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" if version_gt \"${macos_version}\" \"10.13\"\n" + +" then\n" + +" ! [[ -e \"/Library/Developer/CommandLineTools/usr/bin/git\" ]]\n" + +" else\n" + +" ! [[ -e \"/Library/Developer/CommandLineTools/usr/bin/git\" ]] ||\n" + +" ! [[ -e \"/usr/include/iconv.h\" ]]\n" + +" fi\n" + +"}\n" + +"\n" + +"get_permission() {\n" + +" \"${STAT_PRINTF[@]}\" \"${PERMISSION_FORMAT}\" \"$1\"\n" + +"}\n" + +"\n" + +"user_only_chmod() {\n" + +" [[ -d \"$1\" ]] && [[ \"$(get_permission \"$1\")\" != 75[0145] ]]\n" + +"}\n" + +"\n" + +"exists_but_not_writable() {\n" + +" [[ -e \"$1\" ]] && ! [[ -r \"$1\" && -w \"$1\" && -x \"$1\" ]]\n" + +"}\n" + +"\n" + +"get_owner() {\n" + +" \"${STAT_PRINTF[@]}\" \"%u\" \"$1\"\n" + +"}\n" + +"\n" + +"file_not_owned() {\n" + +" [[ \"$(get_owner \"$1\")\" != \"$(id -u)\" ]]\n" + +"}\n" + +"\n" + +"get_group() {\n" + +" \"${STAT_PRINTF[@]}\" \"%g\" \"$1\"\n" + +"}\n" + +"\n" + +"file_not_grpowned() {\n" + +" [[ \" $(id -G \"${USER}\") \" != *\" $(get_group \"$1\") \"* ]]\n" + +"}\n" + +"\n" + +"# Please sync with 'test_ruby()' in 'Library/Homebrew/utils/ruby.sh' from the Homebrew/brew repository.\n" + +"test_ruby() {\n" + +" if [[ ! -x \"$1\" ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" \"$1\" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \\\n" + +" \"abort if Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) != \\\n" + +" Gem::Version.new('${REQUIRED_RUBY_VERSION}').to_s.split('.').first(2)\" 2>/dev/null\n" + +"}\n" + +"\n" + +"test_curl() {\n" + +" if [[ ! -x \"$1\" ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" local curl_version_output curl_name_and_version\n" + +" curl_version_output=\"$(\"$1\" --version 2>/dev/null)\"\n" + +" curl_name_and_version=\"${curl_version_output%% (*}\"\n" + +" version_ge \"$(major_minor \"${curl_name_and_version##* }\")\" \"$(major_minor \"${REQUIRED_CURL_VERSION}\")\"\n" + +"}\n" + +"\n" + +"test_git() {\n" + +" if [[ ! -x \"$1\" ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" local git_version_output\n" + +" git_version_output=\"$(\"$1\" --version 2>/dev/null)\"\n" + +" if [[ \"${git_version_output}\" =~ \"git version \"([^ ]*).* ]]\n" + +" then\n" + +" version_ge \"$(major_minor \"${BASH_REMATCH[1]}\")\" \"$(major_minor \"${REQUIRED_GIT_VERSION}\")\"\n" + +" else\n" + +" abort \"Unexpected Git version: '${git_version_output}'!\"\n" + +" fi\n" + +"}\n" + +"\n" + +"# Search for the given executable in PATH (avoids a dependency on the `which` command)\n" + +"which() {\n" + +" # Alias to Bash built-in command `type -P`\n" + +" type -P \"$@\"\n" + +"}\n" + +"\n" + +"# Search PATH for the specified program that satisfies Homebrew requirements\n" + +"# function which is set above\n" + +"# shellcheck disable=SC2230\n" + +"find_tool() {\n" + +" if [[ $# -ne 1 ]]\n" + +" then\n" + +" return 1\n" + +" fi\n" + +"\n" + +" local executable\n" + +" while read -r executable\n" + +" do\n" + +" if [[ \"${executable}\" != /* ]]\n" + +" then\n" + +" warn \"Ignoring ${executable} (relative paths don't work)\"\n" + +" elif \"test_$1\" \"${executable}\"\n" + +" then\n" + +" echo \"${executable}\"\n" + +" break\n" + +" fi\n" + +" done < <(which -a \"$1\")\n" + +"}\n" + +"\n" + +"no_usable_ruby() {\n" + +" [[ -z \"$(find_tool ruby)\" ]]\n" + +"}\n" + +"\n" + +"outdated_glibc() {\n" + +" local glibc_version\n" + +" glibc_version=\"$(ldd --version | head -n1 | grep -o '[0-9.]*$' | grep -o '^[0-9]\\\+\\\.[0-9]\\\+')\"\n" + +" version_lt \"${glibc_version}\" \"${REQUIRED_GLIBC_VERSION}\"\n" + +"}\n" + +"\n" + +"if [[ -n \"${HOMEBREW_ON_LINUX-}\" ]] && no_usable_ruby && outdated_glibc\n" + +"then\n" + +" abort \"$(\n" + +" cat </dev/null\n" + +"then\n" + +" trap '/usr/bin/sudo -k' EXIT\n" + +"fi\n" + +"\n" + +"# Things can fail later if `pwd` doesn't exist.\n" + +"# Also sudo prints a warning message for no good reason\n" + +"cd \"/usr\" || exit 1\n" + +"\n" + +"####################################################################### script\n" + +"\n" + +"# shellcheck disable=SC2016\n" + +"ohai 'Checking for `sudo` access (which may request your password)...'\n" + +"\n" + +"if [[ -n \"${HOMEBREW_ON_MACOS-}\" ]]\n" + +"then\n" + +" [[ \"${EUID:-${UID}}\" == \"0\" ]] || have_sudo_access\n" + +"elif ! [[ -w \"${HOMEBREW_PREFIX}\" ]] &&\n" + +" ! [[ -w \"/home/linuxbrew\" ]] &&\n" + +" ! [[ -w \"/home\" ]] &&\n" + +" ! have_sudo_access\n" + +"then\n" + +" abort \"$(\n" + +" cat <&1)\" && [[ \"${output}\" == *\"license\"* ]]\n" + +"then\n" + +" abort \"$(\n" + +" cat </dev/null\n" + +"then\n" + +" abort \"$(\n" + +" cat </dev/null || return\n" + +"\n" + +" # we do it in four steps to avoid merge errors when reinstalling\n" + +" execute \"${USABLE_GIT}\" \"-c\" \"init.defaultBranch=master\" \"init\" \"--quiet\"\n" + +"\n" + +" # \"git remote add\" will fail if the remote is defined in the global config\n" + +" execute \"${USABLE_GIT}\" \"config\" \"remote.origin.url\" \"${HOMEBREW_BREW_GIT_REMOTE}\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"remote.origin.fetch\" \"+refs/heads/*:refs/remotes/origin/*\"\n" + +"\n" + +" # ensure we don't munge line endings on checkout\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--bool\" \"core.autocrlf\" \"false\"\n" + +"\n" + +" # make sure symlinks are saved as-is\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--bool\" \"core.symlinks\" \"true\"\n" + +"\n" + +" execute \"${USABLE_GIT}\" \"fetch\" \"--force\" \"origin\"\n" + +" execute \"${USABLE_GIT}\" \"fetch\" \"--force\" \"--tags\" \"origin\"\n" + +" execute \"${USABLE_GIT}\" \"remote\" \"set-head\" \"origin\" \"--auto\" >/dev/null\n" + +"\n" + +" LATEST_GIT_TAG=\"$(\"${USABLE_GIT}\" tag --list --sort=\"-version:refname\" | head -n1)\"\n" + +" if [[ -z \"${LATEST_GIT_TAG}\" ]]\n" + +" then\n" + +" abort \"Failed to query latest Homebrew/brew Git tag.\"\n" + +" fi\n" + +" execute \"${USABLE_GIT}\" \"checkout\" \"--force\" \"-B\" \"stable\" \"${LATEST_GIT_TAG}\"\n" + +"\n" + +" if [[ \"${HOMEBREW_REPOSITORY}\" != \"${HOMEBREW_PREFIX}\" ]]\n" + +" then\n" + +" if [[ \"${HOMEBREW_REPOSITORY}\" == \"${HOMEBREW_PREFIX}/Homebrew\" ]]\n" + +" then\n" + +" execute \"ln\" \"-sf\" \"../Homebrew/bin/brew\" \"${HOMEBREW_PREFIX}/bin/brew\"\n" + +" else\n" + +" abort \"The Homebrew/brew repository should be placed in the Homebrew prefix directory.\"\n" + +" fi\n" + +" fi\n" + +"\n" + +" if [[ -n \"${HOMEBREW_NO_INSTALL_FROM_API-}\" && ! -d \"${HOMEBREW_CORE}\" ]]\n" + +" then\n" + +" # Always use single-quoted strings with `exp` expressions\n" + +" # shellcheck disable=SC2016\n" + +" ohai 'Tapping homebrew/core because `$HOMEBREW_NO_INSTALL_FROM_API` is set.'\n" + +" (\n" + +" execute \"${MKDIR[@]}\" \"${HOMEBREW_CORE}\"\n" + +" cd \"${HOMEBREW_CORE}\" >/dev/null || return\n" + +"\n" + +" execute \"${USABLE_GIT}\" \"-c\" \"init.defaultBranch=master\" \"init\" \"--quiet\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"remote.origin.url\" \"${HOMEBREW_CORE_GIT_REMOTE}\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"remote.origin.fetch\" \"+refs/heads/*:refs/remotes/origin/*\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--bool\" \"core.autocrlf\" \"false\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--bool\" \"core.symlinks\" \"true\"\n" + +" execute \"${USABLE_GIT}\" \"fetch\" \"--force\" \"origin\" \"refs/heads/master:refs/remotes/origin/master\"\n" + +" execute \"${USABLE_GIT}\" \"remote\" \"set-head\" \"origin\" \"--auto\" >/dev/null\n" + +" execute \"${USABLE_GIT}\" \"reset\" \"--hard\" \"origin/master\"\n" + +"\n" + +" cd \"${HOMEBREW_REPOSITORY}\" >/dev/null || return\n" + +" ) || exit 1\n" + +" fi\n" + +"\n" + +" execute \"${HOMEBREW_PREFIX}/bin/brew\" \"update\" \"--force\" \"--quiet\"\n" + +") || exit 1\n" + +"\n" + +"if [[ \":${PATH}:\" != *\":${HOMEBREW_PREFIX}/bin:\"* ]]\n" + +"then\n" + +" warn \"${HOMEBREW_PREFIX}/bin is not in your PATH.\n" + +" Instructions on how to configure your shell for Homebrew\n" + +" can be found in the 'Next steps' section below.\"\n" + +"fi\n" + +"\n" + +"ohai \"Installation successful!\"\n" + +"echo\n" + +"\n" + +"ring_bell\n" + +"\n" + +"# Use an extra newline and bold to avoid this being missed.\n" + +"ohai \"Homebrew has enabled anonymous aggregate formulae and cask analytics.\"\n" + +"echo \"$(\n" + +" cat </dev/null || return\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--replace-all\" \"homebrew.analyticsmessage\" \"true\"\n" + +" execute \"${USABLE_GIT}\" \"config\" \"--replace-all\" \"homebrew.caskanalyticsmessage\" \"true\"\n" + +") || exit 1\n" + +"\n" + +"ohai \"Next steps:\"\n" + +"case \"${SHELL}\" in\n" + +" */bash*)\n" + +" if [[ -n \"${HOMEBREW_ON_LINUX-}\" ]]\n" + +" then\n" + +" shell_rcfile=\"${HOME}/.bashrc\"\n" + +" else\n" + +" shell_rcfile=\"${HOME}/.bash_profile\"\n" + +" fi\n" + +" ;;\n" + +" */zsh*)\n" + +" if [[ -n \"${HOMEBREW_ON_LINUX-}\" ]]\n" + +" then\n" + +" shell_rcfile=\"${ZDOTDIR:-\"${HOME}\"}/.zshrc\"\n" + +" else\n" + +" shell_rcfile=\"${ZDOTDIR:-\"${HOME}\"}/.zprofile\"\n" + +" fi\n" + +" ;;\n" + +" */fish*)\n" + +" shell_rcfile=\"${HOME}/.config/fish/config.fish\"\n" + +" ;;\n" + +" *)\n" + +" shell_rcfile=\"${ENV:-\"${HOME}/.profile\"}\"\n" + +" ;;\n" + +"esac\n" + +"\n" + +"if grep -qs \"eval \\\"\\$(${HOMEBREW_PREFIX}/bin/brew shellenv)\\\"\" \"${shell_rcfile}\"\n" + +"then\n" + +" if ! [[ -x \"$(command -v brew)\" ]]\n" + +" then\n" + +" cat <> ${shell_rcfile}\n" + +" eval \"\\$(${HOMEBREW_PREFIX}/bin/brew shellenv)\"\n" + +"EOS\n" + +"fi\n" + +"\n" + +"if [[ -n \"${non_default_repos}\" ]]\n" + +"then\n" + +" plural=\"\"\n" + +" if [[ \"${#additional_shellenv_commands[@]}\" -gt 1 ]]\n" + +" then\n" + +" plural=\"s\"\n" + +" fi\n" + +" printf -- \"- Run these commands in your terminal to add the non-default Git remote%s for %s:\\n\" \"${plural}\" \"${non_default_repos}\"\n" + +" printf \" echo '# Set PATH, MANPATH, etc., for Homebrew.' >> %s\\n\" \"${shell_rcfile}\"\n" + +" printf \" echo '%s' >> ${shell_rcfile}\\n\" \"${additional_shellenv_commands[@]}\"\n" + +" printf \" %s\\n\" \"${additional_shellenv_commands[@]}\"\n" + +"fi\n" + +"\n" + +"if [[ -n \"${HOMEBREW_ON_LINUX-}\" ]]\n" + +"then\n" + +" echo \"- Install Homebrew's dependencies if you have sudo access:\"\n" + +"\n" + +" if [[ -x \"$(command -v apt-get)\" ]]\n" + +" then\n" + +" echo \" sudo apt-get install build-essential\"\n" + +" elif [[ -x \"$(command -v yum)\" ]]\n" + +" then\n" + +" echo \" sudo yum groupinstall 'Development Tools'\"\n" + +" elif [[ -x \"$(command -v pacman)\" ]]\n" + +" then\n" + +" echo \" sudo pacman -S base-devel\"\n" + +" elif [[ -x \"$(command -v apk)\" ]]\n" + +" then\n" + +" echo \" sudo apk add build-base\"\n" + +" fi\n" + +"\n" + +" cat <&2 + exit 1 +} + +# Fail fast with a concise message when not using bash +# Single brackets are needed here for POSIX compatibility +# shellcheck disable=SC2292 +if [ -z "${BASH_VERSION:-}" ] +then + abort "Bash is required to interpret this script." +fi + +# Check if script is run with force-interactive mode in CI +if [[ -n "${CI-}" && -n "${INTERACTIVE-}" ]] +then + abort "Cannot run force-interactive mode in CI." +fi + +# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set +# Always use single-quoted strings with `exp` expressions +# shellcheck disable=SC2016 +if [[ -n "${INTERACTIVE-}" && -n "${NONINTERACTIVE-}" ]] +then + abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.' +fi + +# Check if script is run in POSIX mode +if [[ -n "${POSIXLY_CORRECT+1}" ]] +then + abort 'Bash must not run in POSIX mode. Please unset POSIXLY_CORRECT and try again.' +fi + +usage() { + cat <${tty_bold} %s${tty_reset}\n" "$(shell_join "$@")" +} + +warn() { + printf "${tty_red}Warning${tty_reset}: %s\n" "$(chomp "$1")" >&2 +} + +# Check if script is run non-interactively (e.g. CI) +# If it is run non-interactively we should not prompt for passwords. +# Always use single-quoted strings with `exp` expressions +# shellcheck disable=SC2016 +if [[ -z "${NONINTERACTIVE-}" ]] +then + if [[ -n "${CI-}" ]] + then + warn 'Running in non-interactive mode because `$CI` is set.' + NONINTERACTIVE=1 + elif [[ ! -t 0 ]] + then + if [[ -z "${INTERACTIVE-}" ]] + then + warn 'Running in non-interactive mode because `stdin` is not a TTY.' + NONINTERACTIVE=1 + else + warn 'Running in interactive mode despite `stdin` not being a TTY because `$INTERACTIVE` is set.' + fi + fi +else + ohai 'Running in non-interactive mode because `$NONINTERACTIVE` is set.' +fi + +# USER isn't always set so provide a fall back for the installer and subprocesses. +if [[ -z "${USER-}" ]] +then + USER="$(chomp "$(id -un)")" + export USER +fi + +# First check OS. +OS="$(uname)" +if [[ "${OS}" == "Linux" ]] +then + HOMEBREW_ON_LINUX=1 +elif [[ "${OS}" == "Darwin" ]] +then + HOMEBREW_ON_MACOS=1 +else + abort "Homebrew is only supported on macOS and Linux." +fi + +# Required installation paths. To install elsewhere (which is unsupported) +# you can untar https://github.com/Homebrew/brew/tarball/master +# anywhere you like. +if [[ -n "${HOMEBREW_ON_MACOS-}" ]] +then + UNAME_MACHINE="$(/usr/bin/uname -m)" + + if [[ "${UNAME_MACHINE}" == "arm64" ]] + then + # On ARM macOS, this script installs to /opt/homebrew only + HOMEBREW_PREFIX="/opt/homebrew" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}" + else + # On Intel macOS, this script installs to /usr/local only + HOMEBREW_PREFIX="/usr/local" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" + fi + HOMEBREW_CACHE="${HOME}/Library/Caches/Homebrew" + + STAT_PRINTF=("/usr/bin/stat" "-f") + PERMISSION_FORMAT="%A" + CHOWN=("/usr/sbin/chown") + CHGRP=("/usr/bin/chgrp") + GROUP="admin" + TOUCH=("/usr/bin/touch") + INSTALL=("/usr/bin/install" -d -o "root" -g "wheel" -m "0755") +else + UNAME_MACHINE="$(uname -m)" + + # On Linux, this script installs to /home/linuxbrew/.linuxbrew only + HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew" + HOMEBREW_REPOSITORY="${HOMEBREW_PREFIX}/Homebrew" + HOMEBREW_CACHE="${HOME}/.cache/Homebrew" + + STAT_PRINTF=("/usr/bin/stat" "--printf") + PERMISSION_FORMAT="%a" + CHOWN=("/bin/chown") + CHGRP=("/bin/chgrp") + GROUP="$(id -gn)" + TOUCH=("/bin/touch") + INSTALL=("/usr/bin/install" -d -o "${USER}" -g "${GROUP}" -m "0755") +fi +CHMOD=("/bin/chmod") +MKDIR=("/bin/mkdir" "-p") +HOMEBREW_BREW_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/brew" +HOMEBREW_CORE_DEFAULT_GIT_REMOTE="https://github.com/Homebrew/homebrew-core" + +# Use remote URLs of Homebrew repositories from environment if set. +HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_GIT_REMOTE:-"${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}"}" +HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_GIT_REMOTE:-"${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}"}" +# The URLs with and without the '.git' suffix are the same Git remote. Do not prompt. +if [[ "${HOMEBREW_BREW_GIT_REMOTE}" == "${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}.git" ]] +then + HOMEBREW_BREW_GIT_REMOTE="${HOMEBREW_BREW_DEFAULT_GIT_REMOTE}" +fi +if [[ "${HOMEBREW_CORE_GIT_REMOTE}" == "${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}.git" ]] +then + HOMEBREW_CORE_GIT_REMOTE="${HOMEBREW_CORE_DEFAULT_GIT_REMOTE}" +fi +export HOMEBREW_{BREW,CORE}_GIT_REMOTE + +# TODO: bump version when new macOS is released or announced +MACOS_NEWEST_UNSUPPORTED="15.0" +# TODO: bump version when new macOS is released +MACOS_OLDEST_SUPPORTED="12.0" + +# For Homebrew on Linux +REQUIRED_RUBY_VERSION=2.6 # https://github.com/Homebrew/brew/pull/6556 +REQUIRED_GLIBC_VERSION=2.13 # https://docs.brew.sh/Homebrew-on-Linux#requirements +REQUIRED_CURL_VERSION=7.41.0 # HOMEBREW_MINIMUM_CURL_VERSION in brew.sh in Homebrew/brew +REQUIRED_GIT_VERSION=2.7.0 # HOMEBREW_MINIMUM_GIT_VERSION in brew.sh in Homebrew/brew + +# no analytics during installation +export HOMEBREW_NO_ANALYTICS_THIS_RUN=1 +export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1 + +unset HAVE_SUDO_ACCESS # unset this from the environment + +have_sudo_access() { + if [[ ! -x "/usr/bin/sudo" ]] + then + return 1 + fi + + local -a SUDO=("/usr/bin/sudo") + if [[ -n "${SUDO_ASKPASS-}" ]] + then + SUDO+=("-A") + elif [[ -n "${NONINTERACTIVE-}" ]] + then + SUDO+=("-n") + fi + + if [[ -z "${HAVE_SUDO_ACCESS-}" ]] + then + if [[ -n "${NONINTERACTIVE-}" ]] + then + "${SUDO[@]}" -l mkdir &>/dev/null + else + "${SUDO[@]}" -v && "${SUDO[@]}" -l mkdir &>/dev/null + fi + HAVE_SUDO_ACCESS="$?" + fi + + if [[ -n "${HOMEBREW_ON_MACOS-}" ]] && [[ "${HAVE_SUDO_ACCESS}" -ne 0 ]] + then + abort "Need sudo access on macOS (e.g. the user ${USER} needs to be an Administrator)!" + fi + + return "${HAVE_SUDO_ACCESS}" +} + +execute() { + if ! "$@" + then + abort "$(printf "Failed during: %s" "$(shell_join "$@")")" + fi +} + +execute_sudo() { + local -a args=("$@") + if [[ "${EUID:-${UID}}" != "0" ]] && have_sudo_access + then + if [[ -n "${SUDO_ASKPASS-}" ]] + then + args=("-A" "${args[@]}") + fi + ohai "/usr/bin/sudo" "${args[@]}" + execute "/usr/bin/sudo" "${args[@]}" + else + ohai "${args[@]}" + execute "${args[@]}" + fi +} + +getc() { + local save_state + save_state="$(/bin/stty -g)" + /bin/stty raw -echo + IFS='' read -r -n 1 -d '' "$@" + /bin/stty "${save_state}" +} + +ring_bell() { + # Use the shell's audible bell. + if [[ -t 1 ]] + then + printf "\a" + fi +} + +wait_for_user() { + local c + echo + echo "Press ${tty_bold}RETURN${tty_reset}/${tty_bold}ENTER${tty_reset} to continue or any other key to abort:" + getc c + if ! [[ "${c}" == $'\r' || "${c}" == $'\n' ]] + then + exit 1 + fi +} + +major_minor() { + echo "${1%%.*}.$( + x="${1#*.}" + echo "${x%%.*}" + )" +} + +version_gt() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] +} +version_ge() { + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -ge "${2#*.}" ]] +} +version_lt() { + [[ "${1%.*}" -lt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -lt "${2#*.}" ]] +} + +check_run_command_as_root() { + [[ "${EUID:-${UID}}" == "0" ]] || return + + # Allow Azure Pipelines/GitHub Actions/Docker/Concourse/Kubernetes to do everything as root (as it's normal there) + [[ -f /.dockerenv ]] && return + [[ -f /run/.containerenv ]] && return + [[ -f /proc/1/cgroup ]] && grep -E "azpl_job|actions_job|docker|garden|kubepods" -q /proc/1/cgroup && return + + abort "Don't run this as root!" +} + +should_install_command_line_tools() { + if [[ -n "${HOMEBREW_ON_LINUX-}" ]] + then + return 1 + fi + + if version_gt "${macos_version}" "10.13" + then + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] + else + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || + ! [[ -e "/usr/include/iconv.h" ]] + fi +} + +get_permission() { + "${STAT_PRINTF[@]}" "${PERMISSION_FORMAT}" "$1" +} + +user_only_chmod() { + [[ -d "$1" ]] && [[ "$(get_permission "$1")" != 75[0145] ]] +} + +exists_but_not_writable() { + [[ -e "$1" ]] && ! [[ -r "$1" && -w "$1" && -x "$1" ]] +} + +get_owner() { + "${STAT_PRINTF[@]}" "%u" "$1" +} + +file_not_owned() { + [[ "$(get_owner "$1")" != "$(id -u)" ]] +} + +get_group() { + "${STAT_PRINTF[@]}" "%g" "$1" +} + +file_not_grpowned() { + [[ " $(id -G "${USER}") " != *" $(get_group "$1") "* ]] +} + +# Please sync with 'test_ruby()' in 'Library/Homebrew/utils/ruby.sh' from the Homebrew/brew repository. +test_ruby() { + if [[ ! -x "$1" ]] + then + return 1 + fi + + "$1" --enable-frozen-string-literal --disable=gems,did_you_mean,rubyopt -rrubygems -e \ + "abort if Gem::Version.new(RUBY_VERSION.to_s.dup).to_s.split('.').first(2) != \ + Gem::Version.new('${REQUIRED_RUBY_VERSION}').to_s.split('.').first(2)" 2>/dev/null +} + +test_curl() { + if [[ ! -x "$1" ]] + then + return 1 + fi + + local curl_version_output curl_name_and_version + curl_version_output="$("$1" --version 2>/dev/null)" + curl_name_and_version="${curl_version_output%% (*}" + version_ge "$(major_minor "${curl_name_and_version##* }")" "$(major_minor "${REQUIRED_CURL_VERSION}")" +} + +test_git() { + if [[ ! -x "$1" ]] + then + return 1 + fi + + local git_version_output + git_version_output="$("$1" --version 2>/dev/null)" + if [[ "${git_version_output}" =~ "git version "([^ ]*).* ]] + then + version_ge "$(major_minor "${BASH_REMATCH[1]}")" "$(major_minor "${REQUIRED_GIT_VERSION}")" + else + abort "Unexpected Git version: '${git_version_output}'!" + fi +} + +# Search for the given executable in PATH (avoids a dependency on the `which` command) +which() { + # Alias to Bash built-in command `type -P` + type -P "$@" +} + +# Search PATH for the specified program that satisfies Homebrew requirements +# function which is set above +# shellcheck disable=SC2230 +find_tool() { + if [[ $# -ne 1 ]] + then + return 1 + fi + + local executable + while read -r executable + do + if [[ "${executable}" != /* ]] + then + warn "Ignoring ${executable} (relative paths don't work)" + elif "test_$1" "${executable}" + then + echo "${executable}" + break + fi + done < <(which -a "$1") +} + +no_usable_ruby() { + [[ -z "$(find_tool ruby)" ]] +} + +outdated_glibc() { + local glibc_version + glibc_version="$(ldd --version | head -n1 | grep -o '[0-9.]*$' | grep -o '^[0-9]\+\.[0-9]\+')" + version_lt "${glibc_version}" "${REQUIRED_GLIBC_VERSION}" +} + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]] && no_usable_ruby && outdated_glibc +then + abort "$( + cat </dev/null +then + trap '/usr/bin/sudo -k' EXIT +fi + +# Things can fail later if `pwd` doesn't exist. +# Also sudo prints a warning message for no good reason +cd "/usr" || exit 1 + +####################################################################### script + +# shellcheck disable=SC2016 +ohai 'Checking for `sudo` access (which may request your password)...' + +if [[ -n "${HOMEBREW_ON_MACOS-}" ]] +then + [[ "${EUID:-${UID}}" == "0" ]] || have_sudo_access +elif ! [[ -w "${HOMEBREW_PREFIX}" ]] && + ! [[ -w "/home/linuxbrew" ]] && + ! [[ -w "/home" ]] && + ! have_sudo_access +then + abort "$( + cat </dev/null +then + abort "$( + cat </dev/null || return + + # we do it in four steps to avoid merge errors when reinstalling + execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" + + # "git remote add" will fail if the remote is defined in the global config + execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_BREW_GIT_REMOTE}" + execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + + # ensure we don't munge line endings on checkout + execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" + + # make sure symlinks are saved as-is + execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" + + execute "${USABLE_GIT}" "fetch" "--force" "origin" + execute "${USABLE_GIT}" "fetch" "--force" "--tags" "origin" + execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" >/dev/null + + LATEST_GIT_TAG="$("${USABLE_GIT}" tag --list --sort="-version:refname" | head -n1)" + if [[ -z "${LATEST_GIT_TAG}" ]] + then + abort "Failed to query latest Homebrew/brew Git tag." + fi + execute "${USABLE_GIT}" "checkout" "--force" "-B" "stable" "${LATEST_GIT_TAG}" + + if [[ "${HOMEBREW_REPOSITORY}" != "${HOMEBREW_PREFIX}" ]] + then + if [[ "${HOMEBREW_REPOSITORY}" == "${HOMEBREW_PREFIX}/Homebrew" ]] + then + execute "ln" "-sf" "../Homebrew/bin/brew" "${HOMEBREW_PREFIX}/bin/brew" + else + abort "The Homebrew/brew repository should be placed in the Homebrew prefix directory." + fi + fi + + if [[ -n "${HOMEBREW_NO_INSTALL_FROM_API-}" && ! -d "${HOMEBREW_CORE}" ]] + then + # Always use single-quoted strings with `exp` expressions + # shellcheck disable=SC2016 + ohai 'Tapping homebrew/core because `$HOMEBREW_NO_INSTALL_FROM_API` is set.' + ( + execute "${MKDIR[@]}" "${HOMEBREW_CORE}" + cd "${HOMEBREW_CORE}" >/dev/null || return + + execute "${USABLE_GIT}" "-c" "init.defaultBranch=master" "init" "--quiet" + execute "${USABLE_GIT}" "config" "remote.origin.url" "${HOMEBREW_CORE_GIT_REMOTE}" + execute "${USABLE_GIT}" "config" "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*" + execute "${USABLE_GIT}" "config" "--bool" "core.autocrlf" "false" + execute "${USABLE_GIT}" "config" "--bool" "core.symlinks" "true" + execute "${USABLE_GIT}" "fetch" "--force" "origin" "refs/heads/master:refs/remotes/origin/master" + execute "${USABLE_GIT}" "remote" "set-head" "origin" "--auto" >/dev/null + execute "${USABLE_GIT}" "reset" "--hard" "origin/master" + + cd "${HOMEBREW_REPOSITORY}" >/dev/null || return + ) || exit 1 + fi + + execute "${HOMEBREW_PREFIX}/bin/brew" "update" "--force" "--quiet" +) || exit 1 + +if [[ ":${PATH}:" != *":${HOMEBREW_PREFIX}/bin:"* ]] +then + warn "${HOMEBREW_PREFIX}/bin is not in your PATH. + Instructions on how to configure your shell for Homebrew + can be found in the 'Next steps' section below." +fi + +ohai "Installation successful!" +echo + +ring_bell + +# Use an extra newline and bold to avoid this being missed. +ohai "Homebrew has enabled anonymous aggregate formulae and cask analytics." +echo "$( + cat </dev/null || return + execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.analyticsmessage" "true" + execute "${USABLE_GIT}" "config" "--replace-all" "homebrew.caskanalyticsmessage" "true" +) || exit 1 + +ohai "Next steps:" +case "${SHELL}" in + */bash*) + if [[ -n "${HOMEBREW_ON_LINUX-}" ]] + then + shell_rcfile="${HOME}/.bashrc" + else + shell_rcfile="${HOME}/.bash_profile" + fi + ;; + */zsh*) + if [[ -n "${HOMEBREW_ON_LINUX-}" ]] + then + shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zshrc" + else + shell_rcfile="${ZDOTDIR:-"${HOME}"}/.zprofile" + fi + ;; + */fish*) + shell_rcfile="${HOME}/.config/fish/config.fish" + ;; + *) + shell_rcfile="${ENV:-"${HOME}/.profile"}" + ;; +esac + +if grep -qs "eval \"\$(${HOMEBREW_PREFIX}/bin/brew shellenv)\"" "${shell_rcfile}" +then + if ! [[ -x "$(command -v brew)" ]] + then + cat <> ${shell_rcfile} + eval "\$(${HOMEBREW_PREFIX}/bin/brew shellenv)" +EOS +fi + +if [[ -n "${non_default_repos}" ]] +then + plural="" + if [[ "${#additional_shellenv_commands[@]}" -gt 1 ]] + then + plural="s" + fi + printf -- "- Run these commands in your terminal to add the non-default Git remote%s for %s:\n" "${plural}" "${non_default_repos}" + printf " echo '# Set PATH, MANPATH, etc., for Homebrew.' >> %s\n" "${shell_rcfile}" + printf " echo '%s' >> ${shell_rcfile}\n" "${additional_shellenv_commands[@]}" + printf " %s\n" "${additional_shellenv_commands[@]}" +fi + +if [[ -n "${HOMEBREW_ON_LINUX-}" ]] +then + echo "- Install Homebrew's dependencies if you have sudo access:" + + if [[ -x "$(command -v apt-get)" ]] + then + echo " sudo apt-get install build-essential" + elif [[ -x "$(command -v yum)" ]] + then + echo " sudo yum groupinstall 'Development Tools'" + elif [[ -x "$(command -v pacman)" ]] + then + echo " sudo pacman -S base-devel" + elif [[ -x "$(command -v apk)" ]] + then + echo " sudo apk add build-base" + fi + + cat < { +const setupStoreIpc = async (ipcChannel, mainWindow, storeInitialValues) => { const Store = (await import('electron-store')).default; - /** @type import Store from 'electron-store' */ - const store = new Store({ - schema, + // set default values for store + const schema = Object.assign({}, defaultSchema); + Object.keys(schema).forEach((key) => { + if (storeInitialValues[key] !== undefined) { + schema[key].default = storeInitialValues[key]; + } }); + /** @type import Store from 'electron-store' */ + const store = new Store({ schema }); + store.onDidAnyChange((data) => { if (mainWindow?.webContents) mainWindow.webContents.send('store-changed', data); diff --git a/electron/test.js b/electron/test.js new file mode 100644 index 000000000..92a03a639 --- /dev/null +++ b/electron/test.js @@ -0,0 +1,16 @@ + +const { setupDarwin, setupUbuntu } = require("./install") + +ipcChannel = { + send: function (channel, message) { + console.log(`${channel} -> ${message}`) + } +} + +if (process.platform == "darwin") { + setupDarwin(ipcChannel) +} else if (process.platform == "linux") { + setupUbuntu(ipcChannel) +} else { + throw new Error(`Unknown platform ${process.platform}`) +} \ No newline at end of file diff --git a/electron/update.js b/electron/update.js index d31153f25..b975e5ee6 100644 --- a/electron/update.js +++ b/electron/update.js @@ -4,14 +4,12 @@ const electronLogger = require('electron-log'); const macUpdater = new electronUpdater.MacUpdater({ ...publishOptions, - private: false, + channels: ['latest', 'beta', 'alpha'], // automatically update to all channels }); macUpdater.logger = electronLogger; -macUpdater.setFeedURL({ - ...publishOptions, -}); +macUpdater.setFeedURL({ ...publishOptions }); macUpdater.autoDownload = true; macUpdater.autoInstallOnAppQuit = true; diff --git a/frontend/components/Layout/TopBar.tsx b/frontend/components/Layout/TopBar.tsx index a98b26363..c36f3054f 100644 --- a/frontend/components/Layout/TopBar.tsx +++ b/frontend/components/Layout/TopBar.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components'; import { COLOR } from '@/constants'; import { useElectronApi } from '@/hooks/useElectronApi'; +import { useStore } from '@/hooks/useStore'; const { Text } = Typography; @@ -48,6 +49,9 @@ const TopBarContainer = styled.div` export const TopBar = () => { const electronApi = useElectronApi(); + const store = useStore(); + const envName = store?.storeState?.environmentName; + return ( @@ -56,7 +60,7 @@ export const TopBar = () => { - Pearl (alpha) + {`Pearl (alpha) ${envName ? `(${envName})` : ''}`.trim()} ); }; diff --git a/frontend/types/ElectronApi.ts b/frontend/types/ElectronApi.ts index 221b00000..2f586a0d9 100644 --- a/frontend/types/ElectronApi.ts +++ b/frontend/types/ElectronApi.ts @@ -1,4 +1,5 @@ export type ElectronStore = { + environmentName?: string; isInitialFunded?: boolean; firstStakingRewardAchieved?: boolean; firstRewardNotificationShown?: boolean; diff --git a/package.json b/package.json index ac1374b62..5c738247b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,9 @@ { "author": "Valory AG", + "main": "electron/main.js", + "name": "olas-operate-app", + "productName": "Pearl", + "version": "0.1.0-rc40", "dependencies": { "@ant-design/cssinjs": "^1.18.4", "@ant-design/icons": "^5.3.0", @@ -38,9 +42,6 @@ "net": "^1.0.2", "prettier": "^3.2.5" }, - "main": "electron/main.js", - "name": "olas-operate-app", - "productName": "Pearl", "scripts": { "build:frontend": "cd frontend && yarn build && rm -rf ../electron/.next && cp -r .next ../electron/.next && rm -rf ../electron/public && cp -r public ../electron/public", "dev:backend": "poetry run python operate/cli.py", diff --git a/poetry.lock b/poetry.lock index 198bc7afd..545b014ac 100644 --- a/poetry.lock +++ b/poetry.lock @@ -374,13 +374,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -566,43 +566,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, ] [package.dependencies] @@ -1927,18 +1927,18 @@ files = [ [[package]] name = "pydantic" -version = "2.7.2" +version = "2.7.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, - {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, + {file = "pydantic-2.7.3-py3-none-any.whl", hash = "sha256:ea91b002777bf643bb20dd717c028ec43216b24a6001a280f83877fd2655d0b4"}, + {file = "pydantic-2.7.3.tar.gz", hash = "sha256:c46c76a40bb1296728d7a8b99aa73dd70a48c3510111ff290034f860c99c419e"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.3" +pydantic-core = "2.18.4" typing-extensions = ">=4.6.1" [package.extras] @@ -1946,90 +1946,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.3" +version = "2.18.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, - {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, - {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, - {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, - {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, - {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, - {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, - {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, - {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, - {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, - {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, - {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, - {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, - {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, - {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, - {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, - {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, - {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, - {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, - {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, - {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, - {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, - {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, - {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, - {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, - {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, - {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, - {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, - {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, - {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, - {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, - {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, - {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, - {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, - {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, - {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, - {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, - {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, - {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, - {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, + {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, + {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, + {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, + {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, + {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, + {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, + {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, + {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, + {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, + {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, + {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, + {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, + {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, ] [package.dependencies] @@ -2466,13 +2466,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.1" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.1-py3-none-any.whl", hash = "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a"}, + {file = "typing_extensions-4.12.1.tar.gz", hash = "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1"}, ] [[package]] @@ -2839,18 +2839,18 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.19.0" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, - {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [metadata] lock-version = "2.0"