libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit cc315487c23a0d72ec2f72605c236e79acd9c6a1
parent 5aab7b614273c085d8554b80908ba895a318ce01
Author: Antoine A <>
Date:   Fri, 29 May 2026 14:10:54 +0200

common: die gradle

Diffstat:
MCargo.lock | 62+++++++++++++++++++++++++++++++++++++-------------------------
MCargo.toml | 2+-
Dgradle/wrapper/gradle-wrapper.jar | 0
Dgradle/wrapper/gradle-wrapper.properties | 9---------
Dgradlew | 248-------------------------------------------------------------------------------
Dlibeufin-nexus/build.gradle | 81-------------------------------------------------------------------------------
Dtestbench/build.gradle | 44--------------------------------------------
Dtestbench/clean_test_logs.py | 78------------------------------------------------------------------------------
8 files changed, 38 insertions(+), 486 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -299,9 +299,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a" dependencies = [ "serde_core", ] @@ -1340,9 +1340,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb92f162bf56536459fc83c79b974bb12837acfed43d6bc370a7916d0ae15ecc" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -1598,7 +1598,6 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-link", ] [[package]] @@ -1839,7 +1838,7 @@ dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.8.0", + "redox_syscall 0.8.1", ] [[package]] @@ -1898,9 +1897,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" +checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" [[package]] name = "lopdf" @@ -2007,6 +2006,18 @@ dependencies = [ ] [[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2498,9 +2509,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7591fa2c6b601dfcfe5f043f65a1c39fcdf50efefcd7f1572e538c1f4b398d" +checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7" dependencies = [ "bitflags", ] @@ -2706,9 +2717,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -3382,7 +3393,7 @@ dependencies = [ [[package]] name = "taler-api" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#9df4ad89b8a4c8acbd06b0ebce398449ba4364df" +source = "git+git://git.taler.net/taler-rust.git/#25696769c34802040aa0af5a1022adfe0fd93f54" dependencies = [ "aws-lc-rs", "axum", @@ -3409,12 +3420,12 @@ dependencies = [ [[package]] name = "taler-build" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#9df4ad89b8a4c8acbd06b0ebce398449ba4364df" +source = "git+git://git.taler.net/taler-rust.git/#25696769c34802040aa0af5a1022adfe0fd93f54" [[package]] name = "taler-common" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#9df4ad89b8a4c8acbd06b0ebce398449ba4364df" +source = "git+git://git.taler.net/taler-rust.git/#25696769c34802040aa0af5a1022adfe0fd93f54" dependencies = [ "anyhow", "aws-lc-rs", @@ -3443,7 +3454,7 @@ dependencies = [ [[package]] name = "taler-macros" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#9df4ad89b8a4c8acbd06b0ebce398449ba4364df" +source = "git+git://git.taler.net/taler-rust.git/#25696769c34802040aa0af5a1022adfe0fd93f54" dependencies = [ "proc-macro2", "quote", @@ -3453,7 +3464,7 @@ dependencies = [ [[package]] name = "taler-test-utils" version = "1.5.0" -source = "git+git://git.taler.net/taler-rust.git/#9df4ad89b8a4c8acbd06b0ebce398449ba4364df" +source = "git+git://git.taler.net/taler-rust.git/#25696769c34802040aa0af5a1022adfe0fd93f54" dependencies = [ "aws-lc-rs", "axum", @@ -3495,6 +3506,7 @@ dependencies = [ "jiff", "libeufin-ebics", "libeufin-nexus", + "nix", "owo-colors", "reedline", "shlex", @@ -3829,9 +3841,9 @@ checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicase" @@ -3868,9 +3880,9 @@ checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -4659,18 +4671,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml @@ -36,7 +36,7 @@ aws-lc-rs = "1.15" compact_str = { version = "0.9.0", features = ["serde", "sqlx-postgres"] } reqwest = "0.13.2" libeufin-ebics = { path = "libeufin-ebics" } -jiff = { version = "0.2", default-features = false, features = ["tz-system"] } +jiff = { version = "0.2", default-features = false, features = ["perf-inline", "std"] } clap = { version = "4.5", features = ["derive"] } uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] } rand = "0.10" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differ. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties @@ -1,9 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip -networkTimeout=10000 -retries=0 -retryBackOffMs=500 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# gradlew start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh gradlew -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/libeufin-nexus/build.gradle b/libeufin-nexus/build.gradle @@ -1,81 +0,0 @@ -plugins { - id("kotlin") - id("application") - id("com.gradleup.shadow") version "$shadow_version" - id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" -} - -version = rootProject.version - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -compileKotlin.kotlinOptions.jvmTarget = "17" -compileTestKotlin.kotlinOptions.jvmTarget = "17" - -sourceSets.main.java.srcDirs = ["src/main/kotlin"] - -dependencies { - // Core language libraries - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") - - implementation(project(":libeufin-common")) - implementation(project(":libeufin-ebics")) - - // Metrics - implementation("io.prometheus:prometheus-metrics-core:$prometheus_version") - implementation("io.prometheus:prometheus-metrics-instrumentation-jvm:$prometheus_version") - implementation("io.prometheus:prometheus-metrics-exposition-formats:$prometheus_version") - - // Command line parsing - implementation("com.github.ajalt.clikt:clikt:$clikt_version") - implementation("org.postgresql:postgresql:$postgres_version") - - // Ktor client library - implementation("io.ktor:ktor-server-core:$ktor_version") - implementation("io.ktor:ktor-client-cio:$ktor_version") - implementation("io.ktor:ktor-client-websockets:$ktor_version") - - // UNIX domain sockets support (used to connect to PostgreSQL) - implementation("com.kohlschutter.junixsocket:junixsocket-core:$junixsocket_version") - - // Serialization - implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") - - // OpenAPI spec generation - implementation("io.github.smiley4:ktor-openapi:5.6.0") - implementation("io.github.smiley4:schema-kenerator-core:2.6.0") - - // Unit testing - testImplementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") - testImplementation("io.ktor:ktor-server-test-host:$ktor_version") - testImplementation("io.ktor:ktor-server-cio:$ktor_version") -} - -application { - mainClass = "tech.libeufin.nexus.MainKt" - // junixsocket loads its native library through System.loadLibrary(). - applicationDefaultJvmArgs = ["--enable-native-access=ALL-UNNAMED"] -} - -shadowJar { - version = "" - minimize { - // The OpenAPI schema generator discovers model properties at runtime. - exclude(dependency("org.jetbrains.kotlin:kotlin-reflect:.*")) - // Kotlin serialization - exclude(dependency("io.ktor:ktor-serialization-kotlinx-json:.*")) - // Postgres unix socket driver - exclude(dependency("com.kohlschutter.junixsocket:junixsocket-core:.*")) - // CIO engine - exclude(dependency("io.ktor:ktor-client-cio:.*")) - // Crypto - exclude(dependency("org.bouncycastle:.*")) - // CLI - exclude(dependency("com.github.ajalt.mordant:mordant:.*")) - // PDF - exclude(dependency("com.itextpdf:itext-core:.*")) - } -} diff --git a/testbench/build.gradle b/testbench/build.gradle @@ -1,43 +0,0 @@ -plugins { - id("kotlin") - id("application") - id("org.jetbrains.kotlin.plugin.serialization") version "$kotlin_version" -} - -java { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -compileKotlin.kotlinOptions.jvmTarget = "17" -compileTestKotlin.kotlinOptions.jvmTarget = "17" - -sourceSets.main.java.srcDirs = ["src/main/kotlin"] - -dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") - - implementation(project(":libeufin-common")) - implementation(project(":libeufin-bank")) - implementation(project(":libeufin-nexus")) - implementation(project(":libeufin-ebics")) - implementation(project(":libeufin-ebisync")) - - implementation("com.github.ajalt.clikt:clikt:$clikt_version") - - implementation("org.postgresql:postgresql:$postgres_version") - implementation("org.jline:jline:4.0.0") - implementation("io.ktor:ktor-client-mock:$ktor_version") - implementation("io.ktor:ktor-server-test-host:$ktor_version") - implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") - implementation("org.jetbrains.kotlin:kotlin-test:$kotlin_version") -} - -application { - mainClass = "tech.libeufin.testbench.MainKt" - applicationName = "libeufin-testbench-test" -} - -run { - standardInput = System.in -} -\ No newline at end of file diff --git a/testbench/clean_test_logs.py b/testbench/clean_test_logs.py @@ -1,78 +0,0 @@ -#!/usr/bin/python3 -# Clean testbench logs directory to only keep unique and useful files - -import hashlib -from pathlib import Path -from string import whitespace - -DIR = Path("test") - - -def rmtree(p: Path): - """Recursively delete file or directory""" - if p.exists(): - if p.is_dir(): - for child in p.iterdir(): - rmtree(child) - p.rmdir() - else: - p.unlink() - - -def remove(p: Path, reason: str): - """Announce and recursively remove file or directory""" - print(f"rm {reason} {p}") - rmtree(p) - - -content_hashes = set() - - -def rm_if_similar(p: Path, content: str): - """Delete file if another file has the same content""" - # Remove whitespace from file - normalized = content.translate(str.maketrans("", "", whitespace)) - # Hash their content - hash = hashlib.blake2b(normalized.encode(), usedforsecurity=False).hexdigest() - if hash in content_hashes: - remove(p, "similar") - else: - content_hashes.add(hash) - - -for platform in DIR.iterdir(): - if not platform.is_dir(): - continue - for date in platform.iterdir(): - if not date.is_dir(): - continue - for request in date.iterdir(): - payload_file_path = request.joinpath("payload.xml") - payload_dir_path = request.joinpath("payload") - - if payload_file_path.exists(): - content = payload_file_path.read_text() - if "HAC" in request.name and "ORDER_HAC_FINAL_NEG" not in content: - remove(request, "simple hac") - elif "HAA" in request.name and "<Service>" not in content: - remove(request, "empty haa") - elif "wssparam" in request.name: - remove(request, "wssparam") - else: - rm_if_similar(payload_file_path, content) - elif payload_dir_path.exists(): - for file in payload_dir_path.iterdir(): - content = file.read_text() - rm_if_similar(file, content) - if not any(payload_dir_path.iterdir()): - remove(request, "empty request") - elif ( - request.name != "fetch" - and request.name != "submit" - and not payload_file_path.exists() - and not payload_dir_path.exists() - ): - remove(request, "empty request") - - if not any(date.iterdir()): - remove(date, "empty dir")