Compare commits

..

1 commit

Author SHA1 Message Date
Michiel Borkent
5726dc7b8b Fix #1610: expose babashka.http-client.websocket namespace 2023-08-20 20:45:32 +02:00
98 changed files with 1296 additions and 3852 deletions

View file

@ -62,7 +62,6 @@
(let [base-cmd ["docker" "buildx" "build" (let [base-cmd ["docker" "buildx" "build"
"-t" (str image-name ":" image-tag) "-t" (str image-name ":" image-tag)
"--platform" platform "--platform" platform
"--progress" "plain"
"--push" "--push"
"-f" docker-file]] "-f" docker-file]]
(exec (concat base-cmd label-args ["."])))) (exec (concat base-cmd label-args ["."]))))
@ -76,7 +75,6 @@
(let [base-cmd ["docker" "buildx" "build" (let [base-cmd ["docker" "buildx" "build"
"-t" (str ghcr-image-name ":" image-tag) "-t" (str ghcr-image-name ":" image-tag)
"--platform" platform "--platform" platform
"--progress" "plain"
"--push" "--push"
"-f" docker-file]] "-f" docker-file]]
(exec (concat base-cmd label-args ["."])))) (exec (concat base-cmd label-args ["."]))))

View file

@ -1,11 +1,9 @@
(ns gen-ci (ns gen-ci
(:require (:require
[babashka.tasks :as tasks] [babashka.tasks :as tasks]
[clj-yaml.core :as yaml] [clj-yaml.core :as yaml]
[clojure.string :as str] [clojure.string :as str]
[flatland.ordered.map :refer [ordered-map]])) [flatland.ordered.map :refer [ordered-map]]))
(def graalvm-version "24")
(defn run (defn run
([cmd-name cmd] ([cmd-name cmd]
@ -39,71 +37,71 @@
[shorted?] [shorted?]
(gen-job shorted? (gen-job shorted?
(ordered-map (ordered-map
:resource_class "large" :resource_class "large"
:docker [{:image "circleci/clojure:lein-2.9.8"}] :docker [{:image "circleci/clojure:lein-2.9.8"}]
:working_directory "~/repo" :working_directory "~/repo"
:environment {:LEIN_ROOT "true"} :environment {:LEIN_ROOT "true"}
:steps (gen-steps :steps (gen-steps
shorted? shorted?
[:checkout [:checkout
(pull-submodules) (pull-submodules)
{:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}" {:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}"
"v1-dependencies-"]}} "v1-dependencies-"]}}
{:run ".circleci/script/deploy"} {:run ".circleci/script/deploy"}
{:save_cache {:paths ["~/.m2"] {:save_cache {:paths ["~/.m2"]
:key "v1-dependencies-{{ checksum \"project.clj\" }}"}}])))) :key "v1-dependencies-{{ checksum \"project.clj\" }}"}}]))))
(defn docker (defn docker
[shorted?] [shorted?]
(gen-job (gen-job
shorted? shorted?
(ordered-map (ordered-map
:machine {:image "ubuntu-2004:2024.05.1"} :machine {:image "ubuntu-2004:202111-01"}
:steps :steps
(gen-steps (gen-steps
shorted? shorted?
[:checkout [:checkout
(pull-submodules) (pull-submodules)
"setup-docker-buildx" "setup-docker-buildx"
{:attach_workspace {:at "/tmp"}} {:attach_workspace {:at "/tmp"}}
(run "Build uberjar" "script/uberjar") (run "Build uberjar" "script/uberjar")
{:run {:run
{:name "Build Docker image" {:name "Build Docker image"
:environment {:PLATFORMS "linux/amd64,linux/arm64"} :environment {:PLATFORMS "linux/amd64,linux/arm64"}
:command :command
"java -jar ./target/babashka-$(cat resources/BABASHKA_VERSION)-standalone.jar .circleci/script/docker.clj"}}])))) "java -jar ./target/babashka-$(cat resources/BABASHKA_VERSION)-standalone.jar .circleci/script/docker.clj"}}]))))
(defn jvm (defn jvm
[shorted? graalvm-home] [shorted? graalvm-home]
(gen-job (gen-job
shorted? shorted?
(ordered-map (ordered-map
:docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}] :docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}]
:working_directory "~/repo" :working_directory "~/repo"
:environment {:LEIN_ROOT "true" :environment {:LEIN_ROOT "true"
:BABASHKA_PLATFORM "linux" :BABASHKA_PLATFORM "linux"
:GRAALVM_VERSION graalvm-version :GRAALVM_VERSION "22.3.1"
:GRAALVM_HOME graalvm-home :GRAALVM_HOME graalvm-home
:BABASHKA_TEST_ENV "jvm" :BABASHKA_TEST_ENV "jvm"}
:BABASHKA_SHA (System/getenv "CIRCLE_SHA1")} :resource_class "large"
:resource_class "large" :steps
:steps (gen-steps
(gen-steps shorted?
shorted? [:checkout
[:checkout (pull-submodules)
(pull-submodules) {:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}"
{:restore_cache {:keys ["v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}" "v1-dependencies-"]}}
"v1-dependencies-"]}} (run "Install Clojure" "sudo script/install-clojure")
(run "Install Clojure" "sudo script/install-clojure") (run "Download GraalVM" "script/install-graalvm")
(run "Download GraalVM" "script/install-graalvm") (run
(run "Run JVM tests"
"Run JVM tests" "export BABASHKA_FEATURE_JDBC=true
"export BABASHKA_FEATURE_JDBC=true
export BABASHKA_FEATURE_POSTGRESQL=true export BABASHKA_FEATURE_POSTGRESQL=true
script/test\nscript/run_lib_tests") script/test\nscript/run_lib_tests")
(run (run "Run as lein command" ".circleci/script/lein")
"Create uberjar" (run
"mkdir -p /tmp/release "Create uberjar"
"mkdir -p /tmp/release
script/uberjar script/uberjar
VERSION=$(cat resources/BABASHKA_VERSION) VERSION=$(cat resources/BABASHKA_VERSION)
jar=target/babashka-$VERSION-standalone.jar jar=target/babashka-$VERSION-standalone.jar
@ -114,22 +112,21 @@ java -jar $jar script/reflection.clj
reflection=\"babashka-$VERSION-reflection.json\" reflection=\"babashka-$VERSION-reflection.json\"
java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$jar\" java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$jar\"
java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$reflection\"") java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$reflection\"")
{:store_artifacts {:path "/tmp/release" {:store_artifacts {:path "/tmp/release"
:destination "release"}} :destination "release"}}
{:save_cache {:paths ["~/.m2"] {:save_cache {:paths ["~/.m2"]
:key "v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}"}}])))) :key "v1-dependencies-{{ checksum \"project.clj\" }}-{{ checksum \"deps.edn\" }}"}}]))))
(defn unix (defn unix
[shorted? static? musl? arch executor-conf resource-class graalvm-home platform] [shorted? static? musl? arch executor-conf resource-class graalvm-home platform]
(let [env {:LEIN_ROOT "true" (let [env {:LEIN_ROOT "true"
:GRAALVM_VERSION graalvm-version :GRAALVM_VERSION "22.3.1"
:GRAALVM_HOME graalvm-home :GRAALVM_HOME graalvm-home
:BABASHKA_PLATFORM (if (= "mac" platform) :BABASHKA_PLATFORM (if (= "mac" platform)
"macos" "macos"
platform) platform)
:BABASHKA_TEST_ENV "native" :BABASHKA_TEST_ENV "native"
:BABASHKA_XMX "-J-Xmx6500m" :BABASHKA_XMX "-J-Xmx6500m"}
:BABASHKA_SHA (System/getenv "CIRCLE_SHA1")}
env (if (= "aarch64" arch) env (if (= "aarch64" arch)
(assoc env :BABASHKA_ARCH arch) (assoc env :BABASHKA_ARCH arch)
env) env)
@ -150,87 +147,81 @@ java -jar \"$jar\" --config .build/bb.edn --deps-root . release-artifact \"$refl
""))] ""))]
(gen-job shorted? (gen-job shorted?
(merge (merge
executor-conf executor-conf
(ordered-map (ordered-map
:working_directory "~/repo" :working_directory "~/repo"
:environment env :environment env
:resource_class resource-class :resource_class resource-class
:steps (gen-steps shorted? :steps (gen-steps shorted?
(filter some? (filter some?
[:checkout [:checkout
(when (contains? #{"linux" "linux-aarch64"} platform) (when (contains? #{"linux" "linux-aarch64"} platform)
(run "Check max glibc version" "script/check_glibc.sh")) (run "Check max glibc version" "script/check_glibc.sh"))
{:attach_workspace {:at "/tmp"}} {:attach_workspace {:at "/tmp"}}
(run "Pull Submodules" "git submodule init\ngit submodule update") (run "Pull Submodules" "git submodule init\ngit submodule update")
{:restore_cache {:restore_cache
{:keys [cache-key]}} {:keys [cache-key]}}
(when (= "mac" platform) (run "Install Clojure" "sudo script/install-clojure")
(run "Install Rosetta" "sudo /usr/sbin/softwareupdate --install-rosetta --agree-to-license")) (when (= "mac" platform)
(run "Install Clojure" "sudo script/install-clojure") (run "Install Leiningen" "script/install-leiningen"))
(when (= "mac" platform) (when (not= "mac" platform)
(run "Install Leiningen" "script/install-leiningen")) (run "Install native dev tools"
(when (not= "mac" platform) (if (and static? musl? (not= "aarch64" arch))
(run "Install native dev tools" (str base-install-cmd "\nsudo -E script/setup-musl")
(if (and static? musl? (not= "aarch64" arch)) base-install-cmd)))
(str base-install-cmd "\nsudo -E script/setup-musl") (run "Download GraalVM" "script/install-graalvm")
base-install-cmd))) (run "Build binary" (if (= "aarch64" arch)
(run "Download GraalVM" "script/install-graalvm") "script/uberjar\nscript/compile -H:PageSize=64K"
#_(run "Download iprof" "curl -sLO 'https://github.com/babashka/pgo-profiles/releases/download/2023.10.11/default.iprof'") "script/uberjar\nscript/compile") "30m")
(run "Build binary" (if (= "aarch64" arch) (run "Run tests" "script/test\nscript/run_lib_tests")
"script/uberjar\nscript/compile -H:PageSize=64K # --pgo=default.iprof" (run "Release" ".circleci/script/release")
"script/uberjar\nscript/compile # --pgo=default.iprof") "30m") {:persist_to_workspace {:root "/tmp"
(run "Release" ".circleci/script/release") :paths ["release"]}}
{:persist_to_workspace {:root "/tmp" {:save_cache
:paths ["release"]}} {:paths ["~/.m2" "~/graalvm-ce-java19-22.3.1"]
(run "Run tests" "script/test\nscript/run_lib_tests") :key cache-key}}
(run "Release + publish" {:store_artifacts {:path "/tmp/release"
(str/join "\n" ["export BABASHKA_RELEASE=true" :destination "release"}}
".circleci/script/release"])) (run "Publish artifact link to Slack"
{:save_cache "./bb .circleci/script/publish_artifact.clj || true")])))))))
{:paths ["~/.m2" "~/graalvm"]
:key cache-key}}
{:store_artifacts {:path "/tmp/release"
:destination "release"}}
(run "Publish artifact link to Slack"
"./bb .circleci/script/publish_artifact.clj || true")])))))))
(defn make-config (defn make-config
[shorted?] [shorted?]
(let [docker-executor-conf {:docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}]} (let [docker-executor-conf {:docker [{:image "circleci/clojure:openjdk-11-lein-2.9.8-bullseye"}]}
machine-executor-conf {:machine {:image "ubuntu-2004:2024.05.1"}} machine-executor-conf {:machine {:image "ubuntu-2004:202111-01"}}
mac-executor-conf {:macos {:xcode "13.4.1"}} mac-executor-conf {:macos {:xcode "14.0.0"}}
linux-graalvm-home (str "/home/circleci/graalvm-" graalvm-version) linux-graalvm-home "/home/circleci/graalvm-ce-java19-22.3.1"
mac-graalvm-home (format "/Users/distiller/graalvm-%s/Contents/Home" graalvm-version)] mac-graalvm-home "/Users/distiller/graalvm-ce-java19-22.3.1/Contents/Home"]
(ordered-map (ordered-map
:version 2.1 :version 2.1
:commands :commands
{:setup-docker-buildx {:setup-docker-buildx
{:steps {:steps
[{:run [{:run
{:name "Create multi-platform capabale buildx builder" {:name "Create multi-platform capabale buildx builder"
:command :command
"docker run --privileged --rm tonistiigi/binfmt --install all\ndocker buildx create --name ci-builder --use"}}]}} "docker run --privileged --rm tonistiigi/binfmt --install all\ndocker buildx create --name ci-builder --use"}}]}}
:jobs (ordered-map :jobs (ordered-map
:jvm (jvm shorted? linux-graalvm-home) :jvm (jvm shorted? linux-graalvm-home)
:linux (unix shorted? false false "amd64" docker-executor-conf "large" linux-graalvm-home "linux") :linux (unix shorted? false false "amd64" docker-executor-conf "large" linux-graalvm-home "linux")
:linux-static :linux-static
(unix shorted? true true "amd64" docker-executor-conf "large" linux-graalvm-home "linux") (unix shorted? true true "amd64" docker-executor-conf "large" linux-graalvm-home "linux")
:linux-aarch64-static :linux-aarch64-static
(unix shorted? true false "aarch64" machine-executor-conf "arm.large" linux-graalvm-home "linux") (unix shorted? true false "aarch64" machine-executor-conf "arm.large" linux-graalvm-home "linux")
:mac (unix shorted? false false "amd64" mac-executor-conf "macos.m1.medium.gen1" mac-graalvm-home "mac") :mac (unix shorted? false false "amd64" mac-executor-conf "large" mac-graalvm-home "mac")
:deploy (deploy shorted?) :deploy (deploy shorted?)
:docker (docker shorted?)) :docker (docker shorted?))
:workflows (ordered-map :workflows (ordered-map
:version 2 :version 2
:ci {:jobs ["jvm" :ci {:jobs ["jvm"
"linux" "linux"
"linux-static" "linux-static"
"mac" "mac"
"linux-aarch64-static" "linux-aarch64-static"
{:deploy {:filters {:branches {:only "master"}} {:deploy {:filters {:branches {:only "master"}}
:requires ["jvm" "linux"]}} :requires ["jvm" "linux"]}}
{:docker {:filters {:branches {:only "master"}} {:docker {:filters {:branches {:only "master"}}
:requires ["linux" "linux-static" "linux-aarch64-static"]}}]})))) :requires ["linux" "linux-static" "linux-aarch64-static"]}}]}))))
(def skip-config (def skip-config
{:skip-if-only [#".*.md$" {:skip-if-only [#".*.md$"

View file

@ -29,9 +29,7 @@ tar zcvf "$archive" bb # bbk
cd - cd -
if [ "$BABASHKA_RELEASE" = "true" ]; then ./bb --config .build/bb.edn --deps-root . release-artifact "/tmp/release/$archive"
./bb --config .build/bb.edn --deps-root . release-artifact "/tmp/release/$archive"
fi
## cleanup ## cleanup

View file

@ -5,8 +5,8 @@ task:
skip: "changesIncludeOnly('logo/*', '**.md')" skip: "changesIncludeOnly('logo/*', '**.md')"
env: env:
LEIN_ROOT: "true" LEIN_ROOT: "true"
GRAALVM_VERSION: "24" GRAALVM_VERSION: "22.3.1"
GRAALVM_HOME: ${HOME}/graalvm-${GRAALVM_VERSION}/Contents/Home GRAALVM_HOME: ${HOME}/graalvm-ce-java19-22.3.1/Contents/Home
BABASHKA_PLATFORM: macos # used in release script BABASHKA_PLATFORM: macos # used in release script
BABASHKA_ARCH: aarch64 BABASHKA_ARCH: aarch64
BABASHKA_TEST_ENV: native BABASHKA_TEST_ENV: native
@ -24,11 +24,8 @@ task:
sudo /usr/sbin/softwareupdate --install-rosetta --agree-to-license sudo /usr/sbin/softwareupdate --install-rosetta --agree-to-license
java -version java -version
export BABASHKA_SHA=$(git rev-parse HEAD)
script/uberjar script/uberjar
# curl -sLO 'https://github.com/babashka/pgo-profiles/releases/download/2023.10.11/default.iprof' script/compile
script/compile # --pgo=default.iprof
# script/test # script/test
# script/run_lib_tests # script/run_lib_tests

View file

@ -1,99 +0,0 @@
name: build
on:
push:
paths-ignore:
- "**.md"
- "logo/**"
pull_request:
paths-ignore:
- "**.md"
- "logo/**"
# TODO: Add deploy if needed
jobs:
native:
if: "!contains(github.event.head_commit.message, 'skip ci')"
strategy:
matrix:
include:
- os: windows-2022
name: windows
static: false
runs-on: ${{ matrix.os }}
env:
LEIN_ROOT: "true"
GRAALVM_VERSION: "24"
BABASHKA_PLATFORM: ${{ matrix.name }} # used in release script
BABASHKA_TEST_ENV: native
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BABASHKA_SHA: ${{ github.sha }}
steps:
- name: Git checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
submodules: 'true'
- name: Cache deps
uses: actions/cache@v4
id: cache-deps
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('project.clj') }}
restore-keys: ${{ runner.os }}-maven-
- name: Setup GraalVM
if: "matrix.static == false"
uses: graalvm/setup-graalvm@v1.3.3
with:
java-version: '24'
distribution: 'graalvm'
components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install clojure tools
uses: DeLaGuardo/setup-clojure@13.2
with:
cli: latest
# lein: latest -- skipped because this uses some PS bullshit
- name: Babashka version
id: babashka-version
shell: bash
run: |
BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION)
echo "##[set-output name=version;]${BABASHKA_VERSION}"
- name: Build
shell: cmd
run: |
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein.bat', 'lein.bat')"
call lein self-install
set GRAALVM_HOME=%JAVA_HOME%
call script/uberjar.bat
call script/compile.bat
echo Creating zip archive
set zip=babashka-%BABASHKA_VERSION%-windows-amd64.zip
jar -cMf %zip% bb.exe
bb --config .build/bb.edn --deps-root . release-artifact %zip%
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
path: bb.exe
name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-amd64
- name: Test binary and libs
shell: cmd
run: |
set BABASHKA_CLASSPATH=
set BABASHKA_TEST_ENV=native
call script/test.bat :windows
call script/run_lib_tests.bat

View file

@ -24,7 +24,6 @@ jobs:
LEIN_ROOT: "true" LEIN_ROOT: "true"
BABASHKA_PLATFORM: linux # could be used in jar name BABASHKA_PLATFORM: linux # could be used in jar name
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BABASHKA_SHA: ${{ github.sha }}
steps: steps:
- name: Git checkout - name: Git checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -33,7 +32,7 @@ jobs:
submodules: 'true' submodules: 'true'
- name: Cache deps - name: Cache deps
uses: actions/cache@v4 uses: actions/cache@v2
id: cache-deps id: cache-deps
with: with:
path: ~/.m2/repository path: ~/.m2/repository
@ -60,6 +59,9 @@ jobs:
script/test script/test
script/run_lib_tests script/run_lib_tests
- name: Run as lein command
run: echo '{:a 1}' | lein bb '(:a *in*)'
- name: Build uberjar - name: Build uberjar
run: | run: |
mkdir -p /tmp/release mkdir -p /tmp/release
@ -78,7 +80,7 @@ jobs:
BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION) BABASHKA_VERSION=$(cat resources/BABASHKA_VERSION)
echo "##[set-output name=version;]${BABASHKA_VERSION}" echo "##[set-output name=version;]${BABASHKA_VERSION}"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v1
with: with:
name: babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar name: babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar
path: target/babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar path: target/babashka-${{ steps.babashka-version.outputs.version }}-standalone.jar
@ -88,7 +90,7 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- os: macos-13 - os: macos-12
name: macos name: macos
static: false static: false
#- os: ubuntu-latest #- os: ubuntu-latest
@ -100,12 +102,11 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
env: env:
LEIN_ROOT: "true" LEIN_ROOT: "true"
GRAALVM_VERSION: "24" GRAALVM_VERSION: "22.3.1"
BABASHKA_PLATFORM: ${{ matrix.name }} # used in release script BABASHKA_PLATFORM: ${{ matrix.name }} # used in release script
BABASHKA_TEST_ENV: native BABASHKA_TEST_ENV: native
BABASHKA_XMX: "-J-Xmx6500m" BABASHKA_XMX: "-J-Xmx6500m"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BABASHKA_SHA: ${{ github.sha }}
steps: steps:
- name: Git checkout - name: Git checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -114,7 +115,7 @@ jobs:
submodules: 'true' submodules: 'true'
- name: Cache deps - name: Cache deps
uses: actions/cache@v4 uses: actions/cache@v2
id: cache-deps id: cache-deps
with: with:
path: ~/.m2/repository path: ~/.m2/repository
@ -125,8 +126,8 @@ jobs:
if: "matrix.static == false" if: "matrix.static == false"
uses: graalvm/setup-graalvm@v1 uses: graalvm/setup-graalvm@v1
with: with:
java-version: '24' version: '22.3.1'
distribution: 'graalvm' java-version: '19'
components: 'native-image' components: 'native-image'
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
@ -134,8 +135,8 @@ jobs:
if: "matrix.static == true" if: "matrix.static == true"
uses: graalvm/setup-graalvm@v1 uses: graalvm/setup-graalvm@v1
with: with:
version: '24' version: '22.3.1'
distribution: 'graalvm' java-version: '19'
components: 'native-image' components: 'native-image'
native-image-musl: true native-image-musl: true
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
@ -172,19 +173,6 @@ jobs:
BABASHKA_MUSL: "true" BABASHKA_MUSL: "true"
run: script/compile run: script/compile
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
path: bb
name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-amd64
- name: Upload static artifact
if: "matrix.static == true"
uses: actions/upload-artifact@v4
with:
path: bb
name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-static-amd64
- name: Test binary and libs - name: Test binary and libs
run: | run: |
script/test script/test
@ -193,6 +181,19 @@ jobs:
- name: Release - name: Release
run: .circleci/script/release run: .circleci/script/release
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
path: bb
name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-amd64
- name: Upload static artifact
if: "matrix.static == true"
uses: actions/upload-artifact@v2
with:
path: bb
name: babashka-${{ steps.babashka-version.outputs.version }}-${{ matrix.name }}-static-amd64
docker: docker:
if: ${{ false }} # Disabled if: ${{ false }} # Disabled
# if: "!contains(github.event.head_commit.message, 'skip ci') && github.event_name == 'push' && github.ref == 'refs/heads/master'" # if: "!contains(github.event.head_commit.message, 'skip ci') && github.event_name == 'push' && github.ref == 'refs/heads/master'"
@ -216,13 +217,13 @@ jobs:
run: mkdir -p /tmp/release run: mkdir -p /tmp/release
- name: Download linux binary - name: Download linux binary
uses: actions/download-artifact@v4.1.7 uses: actions/download-artifact@v2
with: with:
name: babashka-${{ steps.babashka-version.outputs.version }}-linux-amd64.zip name: babashka-${{ steps.babashka-version.outputs.version }}-linux-amd64.zip
path: /tmp/release path: /tmp/release
- name: Download static linux binary - name: Download static linux binary
uses: actions/download-artifact@v4.1.7 uses: actions/download-artifact@v2
with: with:
name: babashka-${{ steps.babashka-version.outputs.version }}-linux-static-amd64.zip name: babashka-${{ steps.babashka-version.outputs.version }}-linux-static-amd64.zip
path: /tmp/release-static path: /tmp/release-static

2
.gitignore vendored
View file

@ -37,5 +37,3 @@ target
.nrepl-port .nrepl-port
.DS_Store .DS_Store
.portal .portal
default.iprof
scratch.clj

View file

@ -9,247 +9,6 @@ A preview of the next release can be installed from
## Unreleased ## Unreleased
- [#1818](https://github.com/babashka/babashka/issues/1818): wrong argument order in `clojure.java.io/resource` implementation
- Add `java.text.BreakIterator`
- Bump `fs` to `0.5.25`
- Bump `jsoup` to `1.20.1`
- Bump `edamame` to `1.4.30`
- [#1815](https://github.com/babashka/babashka/issues/1815): Make install-script wget-compatible ([@eval](https://github.com/eval))
## 1.12.200 (2025-04-26)
- Improve Java reflection based on provided type hints (read blog post [here](https://blog.michielborkent.nl/babashka-java-reflection-type-hints.html))
- Add compatibility with the [fusebox](https://github.com/potetm/fusebox) library
- Fix virtual `ThreadBuilder` interop
- Add `java.util.concurrent.ThreadLocalRandom`
- Add `java.util.concurrent.locks.ReentrantLock`
- Add classes:
- `java.time.chrono.ChronoLocalDate`
- `java.time.temporal.TemporalUnit`
- `java.time.chrono.ChronoLocalDateTime`
- `java.time.chrono.ChronoZonedDateTime`
- `java.time.chrono.Chronology`
## 1.12.199 (2025-04-18)
- [#1806](https://github.com/babashka/babashka/issues/1806): Add `cheshire.factory` namespace ([@lread](https://github.com/lread))
## 1.12.198 (2025-04-17)
- Bump GraalVM to `24`
- Bump SCI to `0.9.45`
- Bump edamame to `1.4.28`
- [#1801](https://github.com/babashka/babashka/issues/1801): Add `java.util.regex.PatternSyntaxException`
- Bump core.async to `1.8.735`
- Bump cheshire to `6.0.0`
- Bump babashka.cli to `0.8.65`
## 1.12.197 (2025-02-28)
- [#1785](https://github.com/babashka/babashka/issues/1785): Allow subclasses of `Throwable` to have instance methods invoked ([@bobisageek](https://github.com/bobisageek))
- [#1791](https://github.com/babashka/babashka/issues/1791): interop problem on Jsoup form element
- [#1793](https://github.com/babashka/babashka/issues/1793): Bump `rewrite-clj` to `1.1.49` (fixes parsing of `foo//` among other things)
- Bump `deps.clj`
- Bump `fs`
## 1.12.196 (2024-12-24)
- [#1771](https://github.com/babashka/babashka/issues/1771): `*e*` in REPL should contain exception thrown by user, not a wrapped one
- [#1777](https://github.com/babashka/babashka/issues/1777) Add `java.nio.file.attribute.UserDefinedFileAttributeView`
- [#1776](https://github.com/babashka/babashka/issues/1776) `Add java.nio.file.attribute.PosixFileAttributes`
- [#1761](https://github.com/babashka/babashka/issues/1761) Support calling `clojure.lang.RT/iter`
- [#1760](https://github.com/babashka/babashka/issues/1760) For compatibility with [Fireworks v0.10.3](https://github.com/paintparty/fireworks), added the following to `:instance-checks` entry in `babashka.impl.classes/classes`([@paintparty](https://github.com/paintparty))
- `clojure.lang.PersistentArrayMap$TransientArrayMap`
- `clojure.lang.PersistentHashMap$TransientHashMap`
- `clojure.lang.PersistentVector$TransientVector`
- `java.lang.NoSuchFieldException`
- `java.util.AbstractMap`
- `java.util.AbstractSet`
- `java.util.AbstractList`
- [#1760](https://github.com/babashka/babashka/issues/1760) For compatibility with [Fireworks v0.10.3](https://github.com/paintparty/fireworks), added `volatile?` entry to `babashka.impl.clojure.core/core-extras`([@paintparty](https://github.com/paintparty))
- Bump `babashka.cli` to `0.8.61`
- Bump `clj-yaml` to `1.0.29`
- [#1768](https://github.com/babashka/babashka/issues/1768): Add `taoensso.timbre` `color-str` function
- Add classes:
- `javax.crypto.KeyAgreement`
- `java.security.KeyPairGenerator`
- `java.security.KeyPair`
- `java.security.spec.ECGenParameterSpec`
- `java.security.spec.PKCS8EncodedKeySpec`
- `java.security.spec.X509EncodedKeySpec`
- `java.security.Signature`
- Add `java.util.concurrent.CompletionStage`
- Bump `core.async` to `1.7.701`
- Bump `org.babashka/cli` to `0.8.162`
## 1.12.195 (2024-11-12)
- Include [jsoup](https://jsoup.org/) for HTML parsing. This makes bb compatible with the [hickory](https://github.com/clj-commons/hickory) library (and possibly other libraries?).
- [#1752](https://github.com/babashka/babashka/issues/1752): include `java.lang.SecurityException` for `java.net.http.HttpClient` support ([@grzm](https://github.com/grzm))
- [#1748](https://github.com/babashka/babashka/issues/1748): add `clojure.core/ensure`
- Upgrade `taoensso/timbre`to `v6.6.0`
- Upgrade `babashka.http-client` to `v0.4.22`
- Add `:git/sha` from build to `bb describe` output ([@lispyclouds](https://github.com/lispyclouds))
- Fix NPE with determining if executing from self-contained executable
## 1.12.194 (2024-10-12)
- Upgrade to GraalVM 23
- [#1743](https://github.com/babashka/babashka/issues/1743): fix new fully qualified instance method in call position with GraalVM 23
## 1.12.193 (2024-10-11)
- Clojure 1.12 interop: method thunks, FI coercion, array notation (see below)
- Upgrade SCI reflector based on clojure 1.12 and remove specific workaround for
`Thread/sleep` interop
- Add `tools.reader.edn/read`
- Fix [#1741](https://github.com/babashka/babashka/issues/1741): `(taoensso.timbre/spy)` now relies on macros from `taoensso.encore` previously not available in bb
Examples of the new Clojure interop:
``` clojure
;; Qualified methods in call position:
(String/.length "123") ;;=> 3
(String/new "123") ;;=> "123"
;; Qualified methods in value position, as functions:
(map Integer/parseInt ["1" "22" "333"]) ;;=> (1 22 333)
(map String/.length ["1" "22" "333"]) ;;=> (1 2 3)
(map String/new ["1" "22" "333"]) ;;=> ("1" "22" "333")
;; Typed multi-dimensional array class notation:
long/1 ;;=> 1-dimensional long array class
String/2 ;;=> 2-dimensional String array class
;; Pass Clojure IFn to Java where `java.util.function.Predicate`, etc. is expected:
(into [] (doto (java.util.ArrayList. [1 2 3]) (.removeIf even?))) ;;=> [1 3]
(.computeIfAbsent (java.util.HashMap.) "abc" #(str % %)) ;;=> "abcabc"
```
## 1.4.192 (2024-09-12)
- Upgrade Clojure to `1.12.0`
- [#1722](https://github.com/babashka/babashka/issues/1722): add new clojure 1.12 vars
- [#1720](https://github.com/babashka/babashka/issues/1720): include new clojure 1.12's `clojure.java.process`
- [#1719](https://github.com/babashka/babashka/issues/1719): add new clojure 1.12 `clojure.repl.deps` namespace. Only calls with explicit versions are supported.
- [#1598](https://github.com/babashka/babashka/issues/1598): use Rosetta on CircleCI to build x64 images
- [#1716](https://github.com/babashka/babashka/issues/1716): expose `babashka.http-client.interceptors` namespace
- [#1707](https://github.com/babashka/babashka/issues/1707): support `aset` on primitive array
- [#1676](https://github.com/babashka/babashka/issues/1676): restore compatibility with newest [at-at](https://github.com/overtone/at-at/) version (1.3.58)
- Bump SCI
- Bump `fs`
- Bump `process`
- Bump `deps.clj`
- Bump `http-client`
- Bump `clj-yaml`
- Bump `edamame`
- Bump `rewrite-clj`
- Add `java.io.LineNumberReader`
## 1.3.191 (2024-06-19)
- Fix [#1688](https://github.com/babashka/babashka/issues/1688): `use-fixtures` should add metadata to `*ns*`
- Fix [#1692](https://github.com/babashka/babashka/issues/1692): Add support for `ITransientSet` and `org.flatland/ordered-set`
- Bump org.flatland/ordered to `1.15.12`.
- Partially Fix [#1695](https://github.com/babashka/babashka/issues/1695): `--repl` arg handling should consume only one arg (itself) ([@bobisageek](https://github.com/bobisageek))
- Partially Fix [#1695](https://github.com/babashka/babashka/issues/1695): make `*command-line-args*` value available in the REPL ([@bobisageek](https://github.com/bobisageek))
- Fix [#1686](https://github.com/babashka/babashka/issues/1686): do not fetch dependencies/invoke java for `version`, `help`, and `describe` options ([@bobisageek](https://github.com/bobisageek))
- [#1696](https://github.com/babashka/babashka/issues/1696): add `clojure.lang.DynamicClassLoader` constructors ([@bobisageek](https://github.com/bobisageek))
- [#1696](https://github.com/babashka/babashka/issues/1696): add `clojure.core/*source-path*` (points to the same sci var as `*file*`) ([@bobisageek](https://github.com/bobisageek))
- [#1696](https://github.com/babashka/babashka/issues/1696): add `clojure.main/with-read-known` ([@bobisageek](https://github.com/bobisageek))
- [#1696](https://github.com/babashka/babashka/issues/1696): add `clojure.core.server/repl-read` ([@bobisageek](https://github.com/bobisageek))
- [#1696](https://github.com/babashka/babashka/issues/1696): make the `cognitect-labs/transcriptor` library work ([@bobisageek](https://github.com/bobisageek))
- [#1700](https://github.com/babashka/babashka/issues/1700): catch exceptions from resolving symbolic links during `bb.edn` lookup ([@bobisageek](https://github.com/bobisageek))
- Support `java.nio.channels.ByteChannel` + several other related interop
- Bump `nrepl/bencode` to `1.2.0`
- Bump `babashka/fs`
- Bump `org.babashka/http-client` to `0.4.18`
## 1.3.190 (2024-04-17)
- Fix [#1679](https://github.com/babashka/babashka/issues/1679): bump timbre and fix wrapping `timbre/log!`
- Add `java.util.concurrent.CountDownLatch`
- Add `java.lang.ThreadLocal`
- Bump `babashka.process`
- Bump httpkit to `2.8.0-RC1`
- Bump clojure to `1.11.2`
- Bump deps.clj
- Bump `babashka.cli`
- Bump `cheshire` to `5.13.0`
- Bump `http-client` to `0.4.17`
## 1.3.189 (2024-02-22)
- [#1660](https://github.com/babashka/babashka/issues/1660): add `:deps-root` as part of hash to avoid caching issue with `deps.clj`
- [#1632](https://github.com/babashka/babashka/issues/1632): fix `(.readPassword (System/console))` by upgrading GraalVM to `21.0.2`
- [#1661](https://github.com/babashka/babashka/issues/1661): follow symlink when reading adjacent bb.edn
- [#1665](https://github.com/babashka/babashka/issues/1665): `read-string` should use non-indexing reader for compatibilty with Clojure
- Bump edamame to 1.4.24
- Bump http-client to 0.4.16
- Bump babashka.cli to 0.8.57
- Uberjar task: support reader conditional in .cljc file
- Support reader conditional in .cljc file when creating uberjar
- Add more `javax.net.ssl` classes
- [#1675](https://github.com/babashka/babashka/issues/1675): add `hash-unordered-coll`
## 1.3.188 (2024-01-12)
- [#1658](https://github.com/babashka/babashka/issues/1658): fix command line parsing for scripts that parse `--version` or `version` etc
## 1.3.187 (2024-01-09)
- Add `clojure.reflect/reflect`
- Add `java.util.ScheduledFuture`, `java.time.temporal.WeekFields`
- Support `Runnable` to be used without import
- Allow `catch` to be used as var name
- [#1646](https://github.com/babashka/babashka/issues/1646): command-line-args are dropped when file exists with same name
- [#1645](https://github.com/babashka/babashka/issues/1645): Support for `clojure.lang.LongRange`
- [#1652](https://github.com/babashka/babashka/issues/1652): allow `bb.edn` to be empty
- [#1586](https://github.com/babashka/babashka/issues/1586): warn when config file doesn't exist and `--debug` is enabled
- [#1410](https://github.com/babashka/babashka/issues/1410): better error message when exec fn doesn't exist
- Bump `babashka.cli` to `0.8.55` which contains subcommand improvements
- Bump `deps.clj` to `1.11.1.1435`
- Bump `babashka.fs` to `0.5.20`
- Compatibility with `plumbing.core`
- Compatibility with `shadow.css` by improving `tools.reader` compatibility
- [#1647](https://github.com/babashka/babashka/issues/1647): Allow capturing env vars at build time (only relevant for building bb)
## 1.3.186 (2023-11-02)
- [Support self-contained binaries as uberjars!](https://github.com/babashka/babashka/wiki/Self-contained-executable#uberjar)
- Add `java.security.KeyFactory`, `java.security.spec.PKCS8EncodedKeySpec`, `java.net.URISyntaxException`, `javax.crypto.spec.IvParameterSpec`
- Fix babashka.process/exec wrt `babashka.process/*defaults*`
- [#1632](https://github.com/babashka/babashka/issues/1632): Partial fix for `(.readPassword (System/console))`
- Enable producing self-contained binaries using [uberjars](https://github.com/babashka/babashka/wiki/Self-contained-executable#uberjar)
- Bump httpkit to `2.8.0-beta3` (fixes GraalVM issue with virtual threads)
- Bump `deps.clj` and `fs`
- Expose `taoensso.timbre.appenders.core`
- nREPL: implement `ns-list` op
- SCI: optimize `swap!`, `deref` and `reset!` for normal atoms (rather than user-created `IAtom`s)
- Add test for [#1639](https://github.com/babashka/babashka/issues/1639)
- Upgrade to GraalVM 21.0.1
## 1.3.185 (2023-09-28)
- [#1624](https://github.com/babashka/babashka/pull/1624): Use Oracle GraalVM 21 ([@lispyclouds](https://github.com/lispyclouds))
- Use PGO to speed up loops (now 2-3x faster for `(time (loop [val 0 cnt 10000000] (if (pos? cnt) (recur (inc val) (dec cnt)) val)))`!)
- Bump babashka.http-client to v0.4.15
- Bump rewrite-clj to v0.1.1.47
- [#1619](https://github.com/babashka/babashka/issues/1619): Fix reflection issue with `Thread/sleep` in `core.async/timeout`
- Support interop on `java.util.stream.IntStream`
- [#1513](https://github.com/babashka/babashka/issues/1513): Fix interop on `Thread/sleep` with numbers that aren't already longs
- Bump babashka.cli to 0.7.53
- Fix [#babashka.nrepl/66](https://github.com/babashka/babashka.nrepl/issues/66)
- Various nREPL server improvements (classpath op, file lookup information for `cider-find-var`)
- Bump cheshire to 5.12.0
## 1.3.184 (2023-08-22)
- Remove leftover debugging output from deps.clj
## 1.3.183 (2023-08-22)
- [#1592](https://github.com/babashka/babashka/issues/1592): expose `sci.core` in babashka - [#1592](https://github.com/babashka/babashka/issues/1592): expose `sci.core` in babashka
- [#1596](https://github.com/babashka/babashka/issues/1596): Fix `clojure.java.browse/browse-url` truncates URLs with multiple query parameters on Windows - [#1596](https://github.com/babashka/babashka/issues/1596): Fix `clojure.java.browse/browse-url` truncates URLs with multiple query parameters on Windows
- [#1599](https://github.com/babashka/babashka/issues/1599): propagate error from `run` when task does not exist - [#1599](https://github.com/babashka/babashka/issues/1599): propagate error from `run` when task does not exist
@ -258,9 +17,7 @@ String/2 ;;=> 2-dimensional String array class
- Bump integrant CI tests - Bump integrant CI tests
- [#1600](https://github.com/babashka/babashka/issues/1600): use pagesize of 64K on linux aarch64, so it works on Asahi linux - [#1600](https://github.com/babashka/babashka/issues/1600): use pagesize of 64K on linux aarch64, so it works on Asahi linux
- Expose `selmer.parser/resolve-arg` - Expose `selmer.parser/resolve-arg`
- [#1610](https://github.com/babashka/babashka/issues/1610): expose `babashka.http-client.websocket` namespace - #1610: expose `babashka.http-client.websocket` namespace
- Bump `babashka.http-client` to `0.4.14`
- [#1568](https://github.com/babashka/babashka/issues/1568): warn when task overrides built-in command
## 1.3.182 (2023-07-20) ## 1.3.182 (2023-07-20)

View file

@ -5,25 +5,24 @@ RUN apt update
RUN apt install --no-install-recommends -yy build-essential zlib1g-dev RUN apt install --no-install-recommends -yy build-essential zlib1g-dev
WORKDIR "/opt" WORKDIR "/opt"
ENV GRAALVM_VERSION="24" ENV GRAALVM_VERSION="22.3.1"
ARG TARGETARCH ARG TARGETARCH
# Do not set those directly, use TARGETARCH instead # Do not set those directly, use TARGETARCH instead
ENV BABASHKA_ARCH= ENV BABASHKA_ARCH=
ENV GRAALVM_ARCH= ENV GRAALVM_ARCH=
RUN if [ "${TARGETARCH}" = "" ] || [ "${TARGETARCH}" = "amd64" ]; then \ RUN if [ "${TARGETARCH}" = "" ] || [ "${TARGETARCH}" = "amd64" ]; then \
export GRAALVM_ARCH=x64; export BABASHKA_ARCH=x86_64; \ export GRAALVM_ARCH=amd64; export BABASHKA_ARCH=x86_64; \
elif [ "${TARGETARCH}" = "arm64" ]; then \ elif [ "${TARGETARCH}" = "arm64" ]; then \
export GRAALVM_ARCH=aarch64; \ export GRAALVM_ARCH=aarch64; \
fi && \ fi && \
echo "Installing GraalVM for ${GRAALVM_ARCH}" && \ echo "Installing GraalVM for ${GRAALVM_ARCH}" && \
curl -sLO https://download.oracle.com/graalvm/${GRAALVM_VERSION}/archive/graalvm-jdk-${GRAALVM_VERSION}_linux-${GRAALVM_ARCH}_bin.tar.gz && \ curl -sLO https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${GRAALVM_VERSION}/graalvm-ce-java19-linux-${GRAALVM_ARCH}-${GRAALVM_VERSION}.tar.gz && \
mkdir "graalvm-$GRAALVM_VERSION" && \ tar -xzf graalvm-ce-java19-linux-${GRAALVM_ARCH}-${GRAALVM_VERSION}.tar.gz
tar -xzf graalvm-jdk-${GRAALVM_VERSION}_linux-${GRAALVM_ARCH}_bin.tar.gz -C graalvm-$GRAALVM_VERSION --strip-components 1
ARG BABASHKA_XMX="-J-Xmx4500m" ARG BABASHKA_XMX="-J-Xmx4500m"
ENV GRAALVM_HOME="/opt/graalvm-$GRAALVM_VERSION" ENV GRAALVM_HOME="/opt/graalvm-ce-java19-${GRAALVM_VERSION}"
ENV JAVA_HOME="$GRAALVM_HOME/bin" ENV JAVA_HOME="/opt/graalvm-ce-java19-${GRAALVM_VERSION}/bin"
ENV PATH="$JAVA_HOME:$PATH" ENV PATH="$JAVA_HOME:$PATH"
ENV BABASHKA_XMX=$BABASHKA_XMX ENV BABASHKA_XMX=$BABASHKA_XMX

View file

@ -13,10 +13,7 @@ RUN echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswit
# TODO: Run actual native tests when they are ported # TODO: Run actual native tests when they are ported
RUN curl --version RUN bb -e "(curl/get \"https://clojure.org\")" # cURL http test
# RUN bb -e '(prn (java.io.File/createTempFile "babashka.curl" ".headers"))'
# RUN bb -e '(spit (java.io.File/createTempFile "babashka.curl" ".headers") "hello")'
# RUN bb -e "(curl/get \"https://clojure.org\")" # cURL http test
RUN bb -e "(require '[org.httpkit.client :as http]) (when-let [error (:error @(http/get \"https://clojure.org\"))] (throw error))" # JVM http test RUN bb -e "(require '[org.httpkit.client :as http]) (when-let [error (:error @(http/get \"https://clojure.org\"))] (throw error))" # JVM http test
RUN bb -e "(.length \"Hello, Babashka\")" # Java interop test RUN bb -e "(.length \"Hello, Babashka\")" # Java interop test
RUN bb -e "(require '[babashka.pods :as pods]) (pods/load-pod 'org.babashka/go-sqlite3 \"0.0.1\") (require '[pod.babashka.go-sqlite3 :as sqlite]) (sqlite/execute! \"/tmp/foo.db\" [\"SELECT 1 + 1\"])" # Pod test RUN bb -e "(require '[babashka.pods :as pods]) (pods/load-pod 'org.babashka/go-sqlite3 \"0.0.1\") (require '[pod.babashka.go-sqlite3 :as sqlite]) (sqlite/execute! \"/tmp/foo.db\" [\"SELECT 1 + 1\"])" # Pod test

136
README.md
View file

@ -4,7 +4,7 @@
[![project chat](https://img.shields.io/badge/slack-join_chat-brightgreen.svg)](https://app.slack.com/client/T03RZGPFR/CLX41ASCS) [![project chat](https://img.shields.io/badge/slack-join_chat-brightgreen.svg)](https://app.slack.com/client/T03RZGPFR/CLX41ASCS)
[![Financial Contributors on Open Collective](https://opencollective.com/babashka/all/badge.svg?label=financial+contributors)](https://opencollective.com/babashka) [![Clojars Project](https://img.shields.io/clojars/v/babashka/babashka.svg)](https://clojars.org/babashka/babashka) [![Financial Contributors on Open Collective](https://opencollective.com/babashka/all/badge.svg?label=financial+contributors)](https://opencollective.com/babashka) [![Clojars Project](https://img.shields.io/clojars/v/babashka/babashka.svg)](https://clojars.org/babashka/babashka)
[![twitter](https://img.shields.io/badge/twitter-%23babashka-blue)](https://twitter.com/search?q=%23babashka&src=typed_query&f=live) [![twitter](https://img.shields.io/badge/twitter-%23babashka-blue)](https://twitter.com/search?q=%23babashka&src=typed_query&f=live)
[![docs](https://img.shields.io/badge/website-docs-blue)](https://book.babashka.org) [![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20Babashka%20Guru-006BFF)](https://gurubase.io/g/babashka) [![docs](https://img.shields.io/badge/website-docs-blue)](https://book.babashka.org)
<blockquote class="twitter-tweet" data-lang="en"> <blockquote class="twitter-tweet" data-lang="en">
<p lang="en" dir="ltr">Life's too short to remember how to write Bash code. I feel liberated.</p> <p lang="en" dir="ltr">Life's too short to remember how to write Bash code. I feel liberated.</p>
@ -40,10 +40,10 @@ As one user described it:
## Quickstart ## Quickstart
For installation options check [Installation](https://github.com/babashka/babashka#installation). For installation options check [Installation](https://github.com/babashka/babashka#installation).
For quick installation using `bash`, use: For quick installation use:
``` shell ``` shell
bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install) $ bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)
``` ```
or grab a binary from [Github or grab a binary from [Github
@ -53,12 +53,9 @@ anywhere on the path.
Then you're ready to go: Then you're ready to go:
``` shellsession ``` shellsession
time bb -e '(->> (fs/list-dir ".") (filter fs/directory?) (map fs/normalize) (map str) (take 3))' $ ls | bb -i '(filter fs/directory? *input*)'
``` ("doc" "resources" "sci" "script" "src" "target" "test")
bb took 4ms.
``` clojure
(".build" "feature-lanterna" ".repl")
bb -e 0,01s user 0,01s system 70% cpu 0,017 total
``` ```
## Support :heart: ## Support :heart:
@ -118,10 +115,50 @@ To get an overview of babashka, you can watch this talk ([slides](https://speake
The [babashka book](https://book.babashka.org) contains detailed information The [babashka book](https://book.babashka.org) contains detailed information
about how to get the most out of babashka scripting. about how to get the most out of babashka scripting.
There is also the book [Babashka Babooka](https://www.braveclojure.com/quests/babooka/), If you're a fan of [Clojure for the Brave and
by Daniel Higginbotham, who has also helped a lot of people learn Clojure with True](https://www.braveclojure.com/clojure-for-the-brave-and-true/), you might
[Clojure for the Brave and enjoy [Babashka Babooka](https://www.braveclojure.com/quests/babooka/), a book
True](https://www.braveclojure.com/clojure-for-the-brave-and-true/). by the same author, Daniel Higginbotham!
## Examples
Read the output from a shell command as a lazy seq of strings:
``` shell
$ ls | bb -i '(take 2 *input*)'
("CHANGES.md" "Dockerfile")
```
Read EDN from stdin and write the result to stdout:
``` shell
$ bb '(vec (dedupe *input*))' <<< '[1 1 1 1 2]'
[1 2]
```
Read more about `*input*` and in- and output flags
[here](https://book.babashka.org/#_input_and_output_flags).
Execute a script. E.g. print the current time in California using the
`java.time` API:
File `pst.clj`:
``` clojure
#!/usr/bin/env bb
(def now (java.time.ZonedDateTime/now))
(def LA-timezone (java.time.ZoneId/of "America/Los_Angeles"))
(def LA-time (.withZoneSameInstant now LA-timezone))
(def pattern (java.time.format.DateTimeFormatter/ofPattern "HH:mm"))
(println (.format LA-time pattern))
```
``` shell
$ bb pst.clj
05:17
```
More examples can be found [here](examples/README.md).
## Try online ## Try online
@ -175,25 +212,13 @@ linux binary.
### asdf ### asdf
[asdf](https://github.com/asdf-vm/asdf) is an extendable version manager for linux and macOS. Note that asdf will add significant startup time to any babashka script, consider using [mise](#mise) instead. [asdf](https://github.com/asdf-vm/asdf) is an extendable version manager for linux and macOS.
Babashka can be installed using a plugin as follows: Babashka can be installed using a plugin as follows:
asdf plugin add babashka https://github.com/pitch-io/asdf-babashka asdf plugin add babashka https://github.com/pitch-io/asdf-babashka
asdf install babashka latest asdf install babashka latest
### mise
[mise](https://mise.jdx.dev/) is a development environment setup tool for linux and macOS.
Install:
mise use --global babashka@latest
Upgrade:
mise upgrade babashka
### Windows ### Windows
#### Scoop #### Scoop
@ -232,8 +257,6 @@ Install via the installer script for linux and macOS:
``` shell ``` shell
$ curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install $ curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install
# or
$ wget -qO install https://raw.githubusercontent.com/babashka/babashka/master/install
$ chmod +x install $ chmod +x install
$ ./install $ ./install
``` ```
@ -305,16 +328,63 @@ Go [here](https://book.babashka.org/#built-in-namespaces) to see the full list o
A list of projects (scripts, libraries, pods and tools) known to work with babashka. A list of projects (scripts, libraries, pods and tools) known to work with babashka.
## Badges ## Badges
<!-- note to editor: it seems a blank line must appear before code blocks within <details> -->
[![bb compatible](/logo/badge.svg)](https://babashka.org)
The babashka compatible badge indicates that a [library can be used as babashka dependency](doc/projects.md).
[![bb compatible](/logo/badge.svg)](https://book.babashka.org#badges)
The babashka compatible badge indicates that a library can be used as babashka dependency.
If this is the case for your library, we encourage you to proudly display this badge. If this is the case for your library, we encourage you to proudly display this badge.
[![bb built-in](/logo/built-in-badge.svg)](https://book.babashka.org#badges) <details><summary>Markdown</summary>
The babashka built-in badge means that a library has been built directly into babashka and requires no extra dependencies to use it.
```markdown
[![bb compatible](https://raw.githubusercontent.com/babashka/babashka/master/logo/badge.svg)](https://babashka.org)
```
</details>
<details><summary>AsciiDoc</summary>
```asciidoc
https://babashka.org[image:https://raw.githubusercontent.com/babashka/babashka/master/logo/badge.svg[bb compatible]]
```
</details>
<details><summary>HTML</summary>
```html
<a href="https://babashka.org" rel="nofollow"><img src="https://github.com/babashka/babashka/raw/master/logo/badge.svg" alt="bb compatible" style="max-width: 100%;"></a>
```
</details>
<br/>
[![bb built-in](/logo/built-in-badge.svg)](https://babashka.org)
The babashka built-in badge means that a [library has been built directly into babashka](https://book.babashka.org/#built-in-namespaces) and requires no extra dependencies to use it.
If this rare honor belongs to your library, you should display this badge. If this rare honor belongs to your library, you should display this badge.
See [the babashka book for details](https://book.babashka.org#badges). <details><summary>Markdown</summary>
```markdown
[![bb built-in](https://raw.githubusercontent.com/babashka/babashka/master/logo/built-in-badge.svg)](https://babashka.org)
```
</details>
<details><summary>AsciiDoc</summary>
```asciidoc
https://babashka.org[image:https://raw.githubusercontent.com/babashka/babashka/master/logo/built-in-badge.svg[bb built-in]]
```
</details>
<details><summary>HTML</summary>
```html
<a href="https://babashka.org" rel="nofollow"><img src="https://github.com/babashka/babashka/raw/master/logo/built-in-badge.svg" alt="bb built-in" style="max-width: 100%;"></a>
```
</details>
</br>
## Swag ## Swag

View file

@ -2,13 +2,13 @@
version: "v-{build}" version: "v-{build}"
image: Visual Studio 2022 image: Visual Studio 2019
clone_folder: C:\projects\babashka clone_folder: C:\projects\babashka
environment: environment:
GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-jdk-24+36.1 GRAALVM_HOME: C:\projects\babashka\graalvm\graalvm-ce-java19-22.3.1
JAVA_HOME: C:\projects\babashka\graalvm\graalvm-jdk-24+36.1 JAVA_HOME: C:\projects\babashka\graalvm\graalvm-ce-java19-22.3.1
BABASHKA_XMX: "-J-Xmx5g" BABASHKA_XMX: "-J-Xmx5g"
skip_commits: skip_commits:
@ -23,9 +23,6 @@ cache:
clone_script: clone_script:
- cmd: git config --global core.autocrlf true - cmd: git config --global core.autocrlf true
- cmd: git config --global core.symlinks true
- ps: >- - ps: >-
if(-not $env:APPVEYOR_PULL_REQUEST_NUMBER) { if(-not $env:APPVEYOR_PULL_REQUEST_NUMBER) {
git clone -q --branch=$env:APPVEYOR_REPO_BRANCH https://github.com/$env:APPVEYOR_REPO_NAME.git $env:APPVEYOR_BUILD_FOLDER git clone -q --branch=$env:APPVEYOR_REPO_BRANCH https://github.com/$env:APPVEYOR_REPO_NAME.git $env:APPVEYOR_BUILD_FOLDER
@ -39,12 +36,9 @@ clone_script:
} }
- cmd: git submodule update --init --recursive - cmd: git submodule update --init --recursive
- cmd: git reset --hard
build_script: build_script:
# TODO: Extract the zip by removing the top level folder to remove the hardcoded path for GRAALVM_HOME
- cmd: >- - cmd: >-
powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://download.oracle.com/graalvm/24/archive/graalvm-jdk-24_windows-x64_bin.zip', 'graalvm.zip') }" powershell -Command "if (Test-Path('graalvm')) { return } else { (New-Object Net.WebClient).DownloadFile('https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.1/graalvm-ce-java19-windows-amd64-22.3.1.zip', 'graalvm.zip') }"
powershell -Command "if (Test-Path('graalvm')) { return } else { Expand-Archive graalvm.zip graalvm }" powershell -Command "if (Test-Path('graalvm')) { return } else { Expand-Archive graalvm.zip graalvm }"
@ -61,7 +55,7 @@ build_script:
# see https://github.com/quarkusio/quarkus/pull/7663 # see https://github.com/quarkusio/quarkus/pull/7663
- cmd: >- - cmd: >-
set BABASHKA_SHA=%APPVEYOR_REPO_COMMIT% call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
call script/uberjar.bat call script/uberjar.bat

@ -1 +1 @@
Subproject commit edd3d613bfb9bf3adabfd0bda5c3f5c6ee85ec20 Subproject commit c6c3553404f424ff5c591cffe24254f01cc2f92a

@ -1 +1 @@
Subproject commit 976cf7b0e54901ada3f7e83f12a4c0aed039adc9 Subproject commit 93dd739d7cf92349599d0127eb1fb18390012819

View file

@ -18,41 +18,42 @@
"deps.clj/src" "deps.clj/resources" "deps.clj/src" "deps.clj/resources"
"resources" "sci/resources" "resources" "sci/resources"
"impl-java/src"], "impl-java/src"],
:deps {org.clojure/clojure {:mvn/version "1.12.0"}, :deps {org.clojure/clojure {:mvn/version "1.11.1"},
org.babashka/sci {:local/root "sci"} org.babashka/sci {:local/root "sci"}
org.babashka/babashka.impl.java {:mvn/version "0.1.10"} org.babashka/babashka.impl.java {:mvn/version "0.1.8"}
org.babashka/sci.impl.types {:mvn/version "0.0.2"} org.babashka/sci.impl.types {:mvn/version "0.0.2"}
babashka/babashka.curl {:local/root "babashka.curl"} babashka/babashka.curl {:local/root "babashka.curl"}
babashka/fs {:local/root "fs"} babashka/fs {:local/root "fs"}
babashka/babashka.core {:local/root "babashka.core"} babashka/babashka.core {:local/root "babashka.core"}
org.clojure/core.async {:mvn/version "1.8.741"}, borkdude/graal.locking {:mvn/version "0.0.2"},
org.clojure/core.async {:mvn/version "1.6.673"},
org.clojure/tools.cli {:mvn/version "1.0.214"}, org.clojure/tools.cli {:mvn/version "1.0.214"},
org.clojure/data.csv {:mvn/version "1.0.0"}, org.clojure/data.csv {:mvn/version "1.0.0"},
cheshire/cheshire {:mvn/version "6.0.0"} cheshire/cheshire {:mvn/version "5.11.0"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha8"} org.clojure/data.xml {:mvn/version "0.2.0-alpha8"}
clj-commons/clj-yaml {:mvn/version "1.0.29"} clj-commons/clj-yaml {:mvn/version "1.0.27"}
com.cognitect/transit-clj {:mvn/version "1.0.333"} com.cognitect/transit-clj {:mvn/version "1.0.333"}
org.clojure/test.check {:mvn/version "1.1.1"} org.clojure/test.check {:mvn/version "1.1.1"}
nrepl/bencode {:mvn/version "1.2.0"} nrepl/bencode {:mvn/version "1.1.0"}
seancorfield/next.jdbc {:mvn/version "1.1.610"} seancorfield/next.jdbc {:mvn/version "1.1.610"}
org.postgresql/postgresql {:mvn/version "42.2.18"} org.postgresql/postgresql {:mvn/version "42.2.18"}
org.hsqldb/hsqldb {:mvn/version "2.5.1"} org.hsqldb/hsqldb {:mvn/version "2.5.1"}
datascript/datascript {:mvn/version "1.0.1"} datascript/datascript {:mvn/version "1.0.1"}
http-kit/http-kit {:mvn/version "2.8.0-RC1"} http-kit/http-kit {:mvn/version "2.7.0-RC1"}
babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"} babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"}
org.clojure/core.match {:mvn/version "1.0.0"} org.clojure/core.match {:mvn/version "1.0.0"}
hiccup/hiccup {:mvn/version "2.0.0-RC1"} hiccup/hiccup {:mvn/version "2.0.0-RC1"}
rewrite-clj/rewrite-clj {:mvn/version "1.1.49"} rewrite-clj/rewrite-clj {:mvn/version "1.1.46"}
selmer/selmer {:mvn/version "1.12.59"} selmer/selmer {:mvn/version "1.12.59"}
com.taoensso/timbre {:mvn/version "6.6.0"} com.taoensso/timbre {:mvn/version "6.0.1"}
org.clojure/tools.logging {:mvn/version "1.1.0"} org.clojure/tools.logging {:mvn/version "1.1.0"}
org.clojure/data.priority-map {:mvn/version "1.1.0"} org.clojure/data.priority-map {:mvn/version "1.1.0"}
insn/insn {:mvn/version "0.5.2"} insn/insn {:mvn/version "0.5.2"}
org.clojure/core.rrb-vector {:mvn/version "0.1.2"} org.clojure/core.rrb-vector {:mvn/version "0.1.2"}
org.babashka/cli {:mvn/version "0.8.65"} org.babashka/cli {:mvn/version "0.7.51"}
org.babashka/http-client {:mvn/version "0.4.22"} org.babashka/http-client {:mvn/version "0.4.13"}
org.flatland/ordered {:mvn/version "1.15.12"} ;; native image bloat with ordered 1.5.10
org.jsoup/jsoup {:mvn/version "1.20.1"}} org.flatland/ordered {:mvn/version "1.5.9"}}
:aliases {:babashka/dev :aliases {:babashka/dev
{:main-opts ["-m" "babashka.main"]} {:main-opts ["-m" "babashka.main"]}
:profile :profile
@ -170,15 +171,7 @@
:deps/manifest :deps} :deps/manifest :deps}
net.cgrand/xforms {:git/url "https://github.com/cgrand/xforms" net.cgrand/xforms {:git/url "https://github.com/cgrand/xforms"
:git/sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6" :git/sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6"
:deps/manifest :deps} :deps/manifest :deps}}
prismatic/plumbing {:git/url "https://github.com/plumatic/plumbing",
:git/sha "424bc704f2db422de34269c139a5494314b3a43b"}
org.clj-commons/hickory {:git/url "https://github.com/clj-commons/hickory"
:git/sha "9385b6708ef35f161732d8464b3a3aa57dd79f30"}
com.potetm/fusebox {:git/url "https://github.com/potetm/fusebox"
:git/sha "ac6d6a0a69510b009b3c1bb2247cd110fd9f7246"}
net.sekao/odoyle-rules {:git/url "https://github.com/oakes/odoyle-rules"
:git/sha "0b1d825ec45a998c4d3481dfb292e08ce6a47f0b"}}
:classpath-overrides {org.clojure/clojure nil :classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}} org.clojure/spec.alpha nil}}
:clj-nvd :clj-nvd

@ -1 +1 @@
Subproject commit 2bf9d3c9f15298d7dd9de033674a42f830e23d6f Subproject commit c419b8c82041855d55593c5b561fc7cea8234712

View file

@ -3,24 +3,24 @@
## Prerequisites ## Prerequisites
- Install [lein](https://leiningen.org/) for producing uberjars - Install [lein](https://leiningen.org/) for producing uberjars
- Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *Oracle GraalVM 24*. - Download [GraalVM](https://www.graalvm.org/downloads/). Currently we use *java19-22.3.1*.
- For Windows, installing Visual Studio 2019 with the "Desktop development - For Windows, installing Visual Studio 2019 with the "Desktop development
with C++" workload is recommended. with C++" workload is recommended.
- Set `$GRAALVM_HOME` to the GraalVM distribution directory. On macOS this can look like: - Set `$GRAALVM_HOME` to the GraalVM distribution directory. On macOS this can look like:
``` shell ``` shell
export GRAALVM_HOME=~/Downloads/graalvm-jdk-21.0.0.1/Contents/Home export GRAALVM_HOME=~/Downloads/graalvm-ce-java19-22.3.1/Contents/Home
``` ```
On linux: On linux:
``` shell ``` shell
export GRAALVM_HOME=~/Downloads/graalvm-jdk-21.0.0.1 export GRAALVM_HOME=~/Downloads/graalvm-ce-java19-22.3.1
``` ```
On Windows, from the [Visual Studio 2019 x64 Native Tools Command Prompt](https://github.com/oracle/graal/issues/2116#issuecomment-590470806) or `cmd.exe` (not Powershell): On Windows, from the [Visual Studio 2019 x64 Native Tools Command Prompt](https://github.com/oracle/graal/issues/2116#issuecomment-590470806) or `cmd.exe` (not Powershell):
``` ```
set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-jdk-21.0.0.1 set GRAALVM_HOME=%USERPROFILE%\Downloads\graalvm-ce-java19-22.3.1
``` ```
If you are not running from the x64 Native Tools Command Prompt, you will need to set additional environment variables using: If you are not running from the x64 Native Tools Command Prompt, you will need to set additional environment variables using:
``` ```

View file

@ -22,9 +22,6 @@ agreement, the PR will be merged.
Each bug fix, change or new feature should be tested well to prevent future Each bug fix, change or new feature should be tested well to prevent future
regressions. regressions.
If possible, tests should use public APIs. If the bug is in private/internal
code, try to trigger it from a public API.
### Force-push ### Force-push
Please do not use `git push --force` on your PR branch for the following Please do not use `git push --force` on your PR branch for the following
@ -40,7 +37,7 @@ reasons:
## Requirements ## Requirements
You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use Oracle GraalVM 24. You need [lein](https://leiningen.org/) for running JVM tests and/or producing uberjars. For building binaries you need GraalVM. Currently we use java19-22.3.1.
## Clone repository ## Clone repository
@ -114,47 +111,6 @@ If the library you want to add doesn't work automatically, you can manually do t
Note: If you have to modify any test file or configuration to have it work with Note: If you have to modify any test file or configuration to have it work with
bb, add an inline comment with prefix `BB-TEST-PATCH:` explaining what you did. bb, add an inline comment with prefix `BB-TEST-PATCH:` explaining what you did.
## Windows
We have corresponding `.bat` scripts for Windows, examples from a CMD Shell:
```shell
script\test.bat
script\run_lib_tests.bat
set BABASHKA_TEST_ENV=native
script\run_lib_tests.bat
```
### Enable Windows Symbolic Links
You'll need to **enable symbolic links**.
You must do this before you git clone babashka otherwise some tests will fail.
There seems to be many ways to achieve this; I found the following worked from PowerShell:
```shell
Install-Module -Name Carbon -Force
Import-Module Carbon
Grant-CPrivilege -Identity lee -Privilege SeCreateSymbolicLinkPrivilege
```
You'll need to reboot:
```shell
shutdown /r /t 0
```
After reboot, verify the new privilege via:
```shell
whoami /priv
```
Test if you can create a symbolic link via:
```
mklink foofoo barbar
```
> **TIP**: Symbolic links are not supported in some folder-sharing technologies.
For example, if you are running Windows as a VirtualBox guest, sharing babashka
source folders from your host OS will not share the symbolic links as symbolic links.
One solution is to re-clone babashka to a non-shared folder on Windows.
### Git for Windows
Install [Git for Windows](https://gitforwindows.org/).
It includes a version of `cat` that babashka tests currently rely on.
## Build ## Build
See [build.md](build.md). See [build.md](build.md).

View file

@ -9,7 +9,6 @@ borkdude/missing.test.assertions,https://github.com/borkdude/missing.test.assert
borkdude/rewrite-edn,https://github.com/borkdude/rewrite-edn borkdude/rewrite-edn,https://github.com/borkdude/rewrite-edn
camel-snake-kebab/camel-snake-kebab,https://github.com/clj-commons/camel-snake-kebab camel-snake-kebab/camel-snake-kebab,https://github.com/clj-commons/camel-snake-kebab
cc.qbits/auspex,https://github.com/mpenet/auspex cc.qbits/auspex,https://github.com/mpenet/auspex
cheshire/cheshire,https://github.com/dakrone/cheshire
circleci/bond,https://github.com/circleci/bond circleci/bond,https://github.com/circleci/bond
cli-matic/cli-matic,https://github.com/l3nz/cli-matic.git cli-matic/cli-matic,https://github.com/l3nz/cli-matic.git
clj-commons/clj-yaml,https://github.com/clj-commons/clj-yaml clj-commons/clj-yaml,https://github.com/clj-commons/clj-yaml

1 maven-name git-url
9 borkdude/rewrite-edn https://github.com/borkdude/rewrite-edn
10 camel-snake-kebab/camel-snake-kebab https://github.com/clj-commons/camel-snake-kebab
11 cc.qbits/auspex https://github.com/mpenet/auspex
cheshire/cheshire https://github.com/dakrone/cheshire
12 circleci/bond https://github.com/circleci/bond
13 cli-matic/cli-matic https://github.com/l3nz/cli-matic.git
14 clj-commons/clj-yaml https://github.com/clj-commons/clj-yaml

View file

@ -3,8 +3,9 @@
[clojure.tools.logging.impl :as impl] [clojure.tools.logging.impl :as impl]
[clojure.tools.logging.readable] [clojure.tools.logging.readable]
[sci.core :as sci] [sci.core :as sci]
[taoensso.encore :as encore :refer [have]] [taoensso.encore :as enc :refer [have]]
[taoensso.timbre :as timbre])) [taoensso.timbre :as timbre]
[taoensso.timbre.appenders.core :as appenders]))
;;;; timbre ;;;; timbre
@ -12,80 +13,56 @@
(defn- fline [and-form] (:line (meta and-form))) (defn- fline [and-form] (:line (meta and-form)))
(defonce callsite-counter
(encore/counter))
(defmacro log! ; Public wrapper around `-log!` (defmacro log! ; Public wrapper around `-log!`
"Core low-level log macro. Useful for tooling/library authors, etc. "Core low-level log macro. Useful for tooling, etc.
* `level` - must eval to a valid logging level
* `msg-type` - must eval to e/o #{:p :f nil}
* `opts` - ks e/o #{:config :?err :?ns-str :?file :?line :?base-data :spying?}
Supports compile-time elision when compile-time const vals
provided for `level` and/or `?ns-str`."
[level msg-type args & [opts]]
(have [:or nil? sequential?] args) ; To allow -> (delay [~@args])
(let [{:keys [?ns-str] :or {?ns-str (str @sci/ns)}} opts]
;; level, ns may/not be compile-time consts:
(when-not (timbre/-elide? level ?ns-str)
(let [{:keys [config ?err ?file ?line ?base-data spying?]
:or {config 'taoensso.timbre/*config*
?err :auto ; => Extract as err-type v0
?file @sci/file
;; NB waiting on CLJ-865:
?line (fline &form)}} opts
* `level` - must eval to a valid logging level ?file (when (not= ?file "NO_SOURCE_PATH") ?file)
* `msg-type` - must eval to e/o #{:p :f nil}
* `args` - arguments seq (ideally vec) for logging call
* `opts` - ks e/o #{:config ?err ?base-data spying?
:?ns-str :?file :?line :?column}
Supports compile-time elision when compile-time const vals ;; Identifies this particular macro expansion; note that this'll
provided for `level` and/or `?ns-str`. ;; be fixed for any fns wrapping `log!` (notably `tools.logging`,
;; `slf4j-timbre`, etc.):
callsite-id
(hash [level msg-type args ; Unevaluated args (arg forms)
?ns-str ?file ?line (rand)])]
Logging wrapper examples: `(taoensso.timbre/-log! ~config ~level ~?ns-str ~?file ~?line ~msg-type ~?err
(delay [~@args]) ~?base-data ~callsite-id ~spying?)))))
(defn log-wrapper-fn [& args] (timbre/log! :info :p args))
(defmacro log-wrapper-macro [& args] (timbre/keep-callsite `(timbre/log! :info :p ~args)))"
([{:as opts
:keys [loc level msg-type args vargs
config ?err ?base-data spying?]
:or
{config 'taoensso.timbre/*config*
?err :auto}}]
(have [:or nil? sequential? symbol?] args)
(let [callsite-id (callsite-counter)
{:keys [line column]} (merge (meta &form) loc)
{:keys [ns file line column]} {:ns @sci/ns :file @sci/file :line line :column column}
ns (or (get opts :?ns-str) ns)
file (or (get opts :?file) file)
line (or (get opts :?line) line)
column (or (get opts :?column) column)
elide? (and #_(enc/const-forms? level ns) (timbre/-elide? level ns))]
(when-not elide?
(let [vargs-form
(or vargs
(if (symbol? args)
`(taoensso.timbre/-ensure-vec ~args)
`[ ~@args]))]
;; Note pre-resolved expansion
`(taoensso.timbre/-log! ~config ~level ~ns ~file ~line ~column ~msg-type ~?err
(delay ~vargs-form) ~?base-data ~callsite-id ~spying?
~(get opts :instant)
~(get opts :may-log?))))))
([level msg-type args & [opts]]
(let [{:keys [line column]} (merge (meta &form))
{:keys [ns file line column]} {:ns @sci/ns :file @sci/file :line line :column column}
loc {:ns ns :file file :line line :column column}
opts (assoc (conj {:loc loc} opts)
:level level, :msg-type msg-type, :args args)]
`(taoensso.timbre/log! ~opts))))
(defn make-ns [ns sci-ns ks] (defn make-ns [ns sci-ns ks]
(reduce (fn [ns-map [var-name var]] (reduce (fn [ns-map [var-name var]]
(let [m (meta var) (let [m (meta var)
no-doc (:no-doc m)
doc (:doc m) doc (:doc m)
arglists (:arglists m)] arglists (:arglists m)]
(assoc ns-map var-name (if no-doc ns-map
(sci/new-var (symbol var-name) @var (assoc ns-map var-name
(cond-> {:ns sci-ns (sci/new-var (symbol var-name) @var
:name (:name m)} (cond-> {:ns sci-ns
(:macro m) (assoc :macro true) :name (:name m)}
doc (assoc :doc doc) (:macro m) (assoc :macro true)
arglists (assoc :arglists arglists)))))) doc (assoc :doc doc)
arglists (assoc :arglists arglists)))))))
{} {}
(select-keys (ns-publics ns) ks))) (select-keys (ns-publics ns) ks)))
(def atomic-println @#'appenders/atomic-println)
(defn println-appender (defn println-appender
"Returns a simple `println` appender for Clojure/Script. "Returns a simple `println` appender for Clojure/Script.
Use with ClojureScript requires that `cljs.core/*print-fn*` be set. Use with ClojureScript requires that `cljs.core/*print-fn*` be set.
@ -115,7 +92,7 @@
:*err* @sci/err :*err* @sci/err
stream)] stream)]
(binding [*out* stream] (binding [*out* stream]
(encore/println-atomic (force output_)))))})) (atomic-println (force output_)))))}))
(def default-config (assoc-in timbre/*config* [:appenders :println] (def default-config (assoc-in timbre/*config* [:appenders :println]
(println-appender {:stream :auto}))) (println-appender {:stream :auto})))
@ -128,7 +105,7 @@
(defn set-level! [level] (swap-config! (fn [m] (assoc m :min-level level)))) (defn set-level! [level] (swap-config! (fn [m] (assoc m :min-level level))))
(defn merge-config! [m] (swap-config! (fn [old] (encore/nested-merge old m)))) (defn merge-config! [m] (swap-config! (fn [old] (enc/nested-merge old m))))
(defmacro -log-and-rethrow-errors [?line & body] (defmacro -log-and-rethrow-errors [?line & body]
`(try (do ~@body) `(try (do ~@body)
@ -143,27 +120,14 @@
'info 'infof 'warn 'warnf 'info 'infof 'warn 'warnf
'error 'errorf 'error 'errorf
'-log! 'with-level '-log! 'with-level
'spit-appender '-spy 'spy 'spit-appender '-spy 'spy])
'color-str])
'log! (sci/copy-var log! tns) 'log! (sci/copy-var log! tns)
'*config* config '*config* config
'swap-config! (sci/copy-var swap-config! tns) 'swap-config! (sci/copy-var swap-config! tns)
'merge-config! (sci/copy-var merge-config! tns) 'merge-config! (sci/copy-var merge-config! tns)
'set-level! (sci/copy-var set-level! tns) 'set-level! (sci/copy-var set-level! tns)
'println-appender (sci/copy-var println-appender tns) 'println-appender (sci/copy-var println-appender tns)
'-log-and-rethrow-errors (sci/copy-var -log-and-rethrow-errors tns) '-log-and-rethrow-errors (sci/copy-var -log-and-rethrow-errors tns)))
'-ensure-vec (sci/copy-var encore/ensure-vec tns)))
(def enc-ns (sci/create-ns 'taoensso.encore))
(def encore-namespace
{'catching (sci/copy-var encore/catching enc-ns)
'try* (sci/copy-var encore/try* enc-ns)})
(def timbre-appenders-namespace
(let [tan (sci/create-ns 'taoensso.timbre.appenders.core nil)]
{'println-appender (sci/copy-var println-appender tan)
'spit-appender (sci/copy-var #_:clj-kondo/ignore timbre/spit-appender tan)}))
;;;; clojure.tools.logging ;;;; clojure.tools.logging
@ -196,7 +160,7 @@
#'clojure.tools.logging/*logger-factory* #'clojure.tools.logging/*logger-factory*
(fn [_] (fn [_]
(LoggerFactory. (LoggerFactory.
(encore/memoize (fn [logger-ns] (Logger. (str logger-ns) config)))))) (enc/memoize (fn [logger-ns] (Logger. (str logger-ns) config))))))
(def lns (sci/create-ns 'clojure.tools.logging nil)) (def lns (sci/create-ns 'clojure.tools.logging nil))

View file

@ -1,14 +1,9 @@
(ns babashka.impl.ordered (ns babashka.impl.ordered
{:no-doc true} {:no-doc true}
(:require [flatland.ordered.map :as omap] (:require [flatland.ordered.map :as omap]
[flatland.ordered.set :as oset]
[sci.core :as sci])) [sci.core :as sci]))
(def omap-ns (sci/create-ns 'flatland.ordered.map nil)) (def omap-ns (sci/create-ns 'flatland.ordered.map nil))
(def oset-ns (sci/create-ns 'flatland.ordered.set nil))
(def ordered-map-ns (def ordered-map-ns
{'ordered-map (sci/copy-var omap/ordered-map omap-ns)}) {'ordered-map (sci/copy-var omap/ordered-map omap-ns)})
(def ordered-set-ns
{'ordered-set (sci/copy-var oset/ordered-set oset-ns)})

2
fs

@ -1 +1 @@
Subproject commit fdd5780bc4df4931332b56082c6c3a5c3c85066d Subproject commit 8c9e048a60d28a4736c18e34cea4df510056f3fb

View file

@ -3,7 +3,7 @@
[clojure.tools.build.api :as b])) [clojure.tools.build.api :as b]))
(def lib 'org.babashka/babashka.impl.java) (def lib 'org.babashka/babashka.impl.java)
(def version "0.1.10") (def version "0.1.8")
(def class-dir "target/classes") (def class-dir "target/classes")
(def basis (b/create-basis {:project "deps.edn"})) (def basis (b/create-basis {:project "deps.edn"}))
(def jar-file (format "target/%s-%s.jar" (name lib) version)) (def jar-file (format "target/%s-%s.jar" (name lib) version))
@ -17,8 +17,7 @@
(defn compile-java [_] (defn compile-java [_]
(b/javac {:src-dirs ["src-java"] (b/javac {:src-dirs ["src-java"]
:class-dir class-dir :class-dir class-dir
:basis basis :basis basis}))
:javac-opts ["--release" "8"]}))
(defn jar [_] (defn jar [_]
(compile-java nil) (compile-java nil)
@ -27,12 +26,7 @@
:lib lib :lib lib
:version version :version version
:basis basis :basis basis
:src-dirs ["src"] :src-dirs ["src"]})
:pom-data
[[:licenses
[:license
[:name "MIT License"]
[:url "https://opensource.org/license/mit/"]]]]})
(b/copy-dir {:src-dirs ["src"] (b/copy-dir {:src-dirs ["src"]
:target-dir class-dir}) :target-dir class-dir})
(b/jar {:class-dir class-dir (b/jar {:class-dir class-dir

View file

@ -2,7 +2,7 @@
:aliases :aliases
{:build ;; added by neil {:build ;; added by neil
{:paths ["." "build" "src"] {:paths ["." "build" "src"]
:deps {io.github.clojure/tools.build {:git/tag "v0.9.6" :git/sha "8e78bcc"} :deps {io.github.clojure/tools.build {:git/tag "v0.8.1" :git/sha "7d40500"}
slipset/deps-deploy {:mvn/version "0.2.0"} slipset/deps-deploy {:mvn/version "0.2.0"}
org.babashka/sci.impl.types {:mvn/version "0.0.2"} org.babashka/sci.impl.types {:mvn/version "0.0.2"}
;; insn/insn {:mvn/version "0.5.3"} ;; insn/insn {:mvn/version "0.5.3"}

View file

@ -1,7 +1,6 @@
(ns babashka.impl.reify2.interfaces) (ns babashka.impl.reify2.interfaces)
(def interfaces [java.nio.file.FileVisitor (def interfaces [java.nio.file.FileVisitor
java.nio.file.DirectoryStream$Filter
java.io.FileFilter java.io.FileFilter
java.io.FilenameFilter java.io.FilenameFilter
clojure.lang.Associative clojure.lang.Associative

36
install
View file

@ -29,32 +29,6 @@ print_help() {
exit 1 exit 1
} }
has() {
command -v "$1" >/dev/null 2>&1
}
fetch() {
local url=$1
local outfile=${2:-}
if has wget; then
if [[ -n $outfile ]]; then
wget -qO "$outfile" "$url"
else
wget -qO - "$url"
fi
elif has curl; then
if [[ -n $outfile ]]; then
curl -fsSL "$url" -o "$outfile"
else
curl -fsSL "$url"
fi
else
>&2 echo "Either 'wget' or 'curl' needs to be on PATH!"
exit 1
fi
}
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
key="$1" key="$1"
@ -106,9 +80,9 @@ fi
if [[ "$version" == "" ]]; then if [[ "$version" == "" ]]; then
if [[ "$dev_build" == "true" ]]; then if [[ "$dev_build" == "true" ]]; then
version="$(fetch https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_VERSION)" version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_VERSION)"
else else
version="$(fetch https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_RELEASED_VERSION)" version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_RELEASED_VERSION)"
fi fi
fi fi
@ -170,9 +144,9 @@ download_url="https://github.com/babashka/$repo/releases/download/v$version/$fil
# macOS only have shasum available by default # macOS only have shasum available by default
# Some Linux distros (RHEL-like) only have sha256sum available by default (others have both) # Some Linux distros (RHEL-like) only have sha256sum available by default (others have both)
if has sha256sum; then if command -v sha256sum >/dev/null; then
sha256sum_cmd="sha256sum" sha256sum_cmd="sha256sum"
elif has shasum; then elif command -v shasum >/dev/null; then
sha256sum_cmd="shasum -a 256" sha256sum_cmd="shasum -a 256"
else else
>&2 echo "Either 'sha256sum' or 'shasum' needs to be on PATH for '--checksum' flag!" >&2 echo "Either 'sha256sum' or 'shasum' needs to be on PATH for '--checksum' flag!"
@ -185,7 +159,7 @@ mkdir -p "$download_dir" && (
cd "$download_dir" cd "$download_dir"
echo -e "Downloading $download_url to $download_dir" echo -e "Downloading $download_url to $download_dir"
fetch "$download_url" "$filename" curl -o "$filename" -sL "$download_url"
if [[ -n "$checksum" ]]; then if [[ -n "$checksum" ]]; then
if ! echo "$checksum *$filename" | $sha256sum_cmd --check --status; then if ! echo "$checksum *$filename" | $sha256sum_cmd --check --status; then
>&2 echo "Failed checksum on $filename" >&2 echo "Failed checksum on $filename"

2
pods

@ -1 +1 @@
Subproject commit 717cef7af5cb1c1b091bd10e012b2e71b7b8b9bc Subproject commit 6ad6045b94bc871c5107bfc75d39643b6c1bc8ba

@ -1 +1 @@
Subproject commit 2058c79fb63f80ca71917432eddea73e0c58717c Subproject commit d24961a8b101ee1a95569256c9ddb260d0f9bb36

View file

@ -21,31 +21,31 @@
:non-flaky (complement :flaky) :non-flaky (complement :flaky)
:flaky :flaky} :flaky :flaky}
:jvm-opts ["--enable-preview"] :jvm-opts ["--enable-preview"]
:dependencies [[org.clojure/clojure "1.12.0"] :dependencies [[org.clojure/clojure "1.11.1"]
[borkdude/edamame "1.4.30"] [borkdude/edamame "1.3.23"]
[borkdude/graal.locking "0.0.2"]
[org.clojure/tools.cli "1.0.214"] [org.clojure/tools.cli "1.0.214"]
[cheshire "6.0.0"] [cheshire "5.11.0"]
[nrepl/bencode "1.2.0"] [nrepl/bencode "1.1.0"]
[borkdude/sci.impl.reflector "0.0.4"] [borkdude/sci.impl.reflector "0.0.1"]
[org.babashka/sci.impl.types "0.0.2"] [org.babashka/sci.impl.types "0.0.2"]
[org.babashka/babashka.impl.java "0.1.10"] [org.babashka/babashka.impl.java "0.1.8"]
[org.clojure/core.async "1.8.741"] [org.clojure/core.async "1.6.673"]
[org.clojure/test.check "1.1.1"] [org.clojure/test.check "1.1.1"]
[com.github.clj-easy/graal-build-time "0.1.0"] [com.github.clj-easy/graal-build-time "0.1.0"]
[rewrite-clj/rewrite-clj "1.1.49"] [rewrite-clj/rewrite-clj "1.1.46"]
[insn/insn "0.5.2"] [insn/insn "0.5.2"]
[org.babashka/cli "0.8.65"] [org.babashka/cli "0.7.51"]
[org.babashka/http-client "0.4.22"] [org.babashka/http-client "0.4.13"]]
[org.jsoup/jsoup "1.20.1"]
[borkdude/graal.locking "0.0.2"]]
:plugins [[org.kipz/lein-meta-bom "0.1.1"]] :plugins [[org.kipz/lein-meta-bom "0.1.1"]]
:metabom {:jar-name "metabom.jar"} :metabom {:jar-name "metabom.jar"}
:profiles {:feature/xml {:source-paths ["feature-xml"] :profiles {:feature/xml {:source-paths ["feature-xml"]
:dependencies [[org.clojure/data.xml "0.2.0-alpha8"]]} :dependencies [[org.clojure/data.xml "0.2.0-alpha8"]]}
:feature/yaml {:source-paths ["feature-yaml"] :feature/yaml {:source-paths ["feature-yaml"]
:dependencies [[clj-commons/clj-yaml "1.0.29" :dependencies [[clj-commons/clj-yaml "1.0.27"
:exclusions [org.flatland/ordered]#_#_clj-commons/clj-yaml "0.7.110"] :exclusions [org.flatland/ordered]#_#_clj-commons/clj-yaml "0.7.110"]
[org.flatland/ordered "1.15.12"]]} ;; 1.15.10 cause native image bloat problem
[org.flatland/ordered "1.5.9"]]}
:feature/jdbc {:source-paths ["feature-jdbc"] :feature/jdbc {:source-paths ["feature-jdbc"]
:dependencies [[seancorfield/next.jdbc "1.1.610"]]} :dependencies [[seancorfield/next.jdbc "1.1.610"]]}
:feature/sqlite [:feature/jdbc {:dependencies [[org.xerial/sqlite-jdbc "3.36.0.3"]]}] :feature/sqlite [:feature/jdbc {:dependencies [[org.xerial/sqlite-jdbc "3.36.0.3"]]}]
@ -60,9 +60,9 @@
:feature/datascript {:source-paths ["feature-datascript"] :feature/datascript {:source-paths ["feature-datascript"]
:dependencies [[datascript "1.3.10"]]} :dependencies [[datascript "1.3.10"]]}
:feature/httpkit-client {:source-paths ["feature-httpkit-client"] :feature/httpkit-client {:source-paths ["feature-httpkit-client"]
:dependencies [[http-kit "2.8.0-RC1"]]} :dependencies [[http-kit "2.7.0-RC1"]]}
:feature/httpkit-server {:source-paths ["feature-httpkit-server"] :feature/httpkit-server {:source-paths ["feature-httpkit-server"]
:dependencies [[http-kit "2.8.0-RC1"]]} :dependencies [[http-kit "2.7.0-RC1"]]}
:feature/lanterna {:source-paths ["feature-lanterna"] :feature/lanterna {:source-paths ["feature-lanterna"]
:dependencies [[babashka/clojure-lanterna "0.9.8-SNAPSHOT"]]} :dependencies [[babashka/clojure-lanterna "0.9.8-SNAPSHOT"]]}
:feature/core-match {:source-paths ["feature-core-match"] :feature/core-match {:source-paths ["feature-core-match"]
@ -74,7 +74,7 @@
:feature/selmer {:source-paths ["feature-selmer"] :feature/selmer {:source-paths ["feature-selmer"]
:dependencies [[selmer/selmer "1.12.59"]]} :dependencies [[selmer/selmer "1.12.59"]]}
:feature/logging {:source-paths ["feature-logging"] :feature/logging {:source-paths ["feature-logging"]
:dependencies [[com.taoensso/timbre "6.6.0"] :dependencies [[com.taoensso/timbre "6.0.4"]
[org.clojure/tools.logging "1.1.0"]]} [org.clojure/tools.logging "1.1.0"]]}
:feature/priority-map {:source-paths ["feature-priority-map"] :feature/priority-map {:source-paths ["feature-priority-map"]
:dependencies [[org.clojure/data.priority-map "1.1.0"]]} :dependencies [[org.clojure/data.priority-map "1.1.0"]]}

View file

@ -1 +1 @@
1.12.200 1.3.182

View file

@ -1 +1 @@
1.12.201-SNAPSHOT 1.3.183-SNAPSHOT

View file

@ -18,41 +18,42 @@
"deps.clj/src" "deps.clj/resources" "deps.clj/src" "deps.clj/resources"
"resources" "sci/resources" "resources" "sci/resources"
"impl-java/src"], "impl-java/src"],
:deps {org.clojure/clojure {:mvn/version "1.12.0"}, :deps {org.clojure/clojure {:mvn/version "1.11.1"},
org.babashka/sci {:local/root "sci"} org.babashka/sci {:local/root "sci"}
org.babashka/babashka.impl.java {:mvn/version "0.1.10"} org.babashka/babashka.impl.java {:mvn/version "0.1.8"}
org.babashka/sci.impl.types {:mvn/version "0.0.2"} org.babashka/sci.impl.types {:mvn/version "0.0.2"}
babashka/babashka.curl {:local/root "babashka.curl"} babashka/babashka.curl {:local/root "babashka.curl"}
babashka/fs {:local/root "fs"} babashka/fs {:local/root "fs"}
babashka/babashka.core {:local/root "babashka.core"} babashka/babashka.core {:local/root "babashka.core"}
org.clojure/core.async {:mvn/version "1.8.741"}, borkdude/graal.locking {:mvn/version "0.0.2"},
org.clojure/core.async {:mvn/version "1.6.673"},
org.clojure/tools.cli {:mvn/version "1.0.214"}, org.clojure/tools.cli {:mvn/version "1.0.214"},
org.clojure/data.csv {:mvn/version "1.0.0"}, org.clojure/data.csv {:mvn/version "1.0.0"},
cheshire/cheshire {:mvn/version "6.0.0"} cheshire/cheshire {:mvn/version "5.11.0"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha8"} org.clojure/data.xml {:mvn/version "0.2.0-alpha8"}
clj-commons/clj-yaml {:mvn/version "1.0.29"} clj-commons/clj-yaml {:mvn/version "1.0.26"}
com.cognitect/transit-clj {:mvn/version "1.0.333"} com.cognitect/transit-clj {:mvn/version "1.0.333"}
org.clojure/test.check {:mvn/version "1.1.1"} org.clojure/test.check {:mvn/version "1.1.1"}
nrepl/bencode {:mvn/version "1.2.0"} nrepl/bencode {:mvn/version "1.1.0"}
seancorfield/next.jdbc {:mvn/version "1.1.610"} seancorfield/next.jdbc {:mvn/version "1.1.610"}
org.postgresql/postgresql {:mvn/version "42.2.18"} org.postgresql/postgresql {:mvn/version "42.2.18"}
org.hsqldb/hsqldb {:mvn/version "2.5.1"} org.hsqldb/hsqldb {:mvn/version "2.5.1"}
datascript/datascript {:mvn/version "1.0.1"} datascript/datascript {:mvn/version "1.0.1"}
http-kit/http-kit {:mvn/version "2.8.0-RC1"} http-kit/http-kit {:mvn/version "2.7.0-RC1"}
babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"} babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"}
org.clojure/core.match {:mvn/version "1.0.0"} org.clojure/core.match {:mvn/version "1.0.0"}
hiccup/hiccup {:mvn/version "2.0.0-RC1"} hiccup/hiccup {:mvn/version "2.0.0-RC1"}
rewrite-clj/rewrite-clj {:mvn/version "1.1.49"} rewrite-clj/rewrite-clj {:mvn/version "1.1.46"}
selmer/selmer {:mvn/version "1.12.59"} selmer/selmer {:mvn/version "1.12.59"}
com.taoensso/timbre {:mvn/version "6.6.0"} com.taoensso/timbre {:mvn/version "6.0.1"}
org.clojure/tools.logging {:mvn/version "1.1.0"} org.clojure/tools.logging {:mvn/version "1.1.0"}
org.clojure/data.priority-map {:mvn/version "1.1.0"} org.clojure/data.priority-map {:mvn/version "1.1.0"}
insn/insn {:mvn/version "0.5.2"} insn/insn {:mvn/version "0.5.2"}
org.clojure/core.rrb-vector {:mvn/version "0.1.2"} org.clojure/core.rrb-vector {:mvn/version "0.1.2"}
org.babashka/cli {:mvn/version "0.8.65"} org.babashka/cli {:mvn/version "0.7.51"}
org.babashka/http-client {:mvn/version "0.4.22"} org.babashka/http-client {:mvn/version "0.4.13"}
org.flatland/ordered {:mvn/version "1.15.12"} ;; native image bloat with ordered 1.5.10
org.jsoup/jsoup {:mvn/version "1.20.1"}} org.flatland/ordered {:mvn/version "1.5.9"}}
:aliases {:babashka/dev :aliases {:babashka/dev
{:main-opts ["-m" "babashka.main"]} {:main-opts ["-m" "babashka.main"]}
:profile :profile
@ -108,7 +109,7 @@
exoscale/coax {:mvn/version "1.0.0-alpha14"} exoscale/coax {:mvn/version "1.0.0-alpha14"}
orchestra/orchestra {:mvn/version "2021.01.01-1"} orchestra/orchestra {:mvn/version "2021.01.01-1"}
expound/expound {:mvn/version "0.8.10"} expound/expound {:mvn/version "0.8.10"}
integrant/integrant {:git/url "https://github.com/weavejester/integrant", :git/sha "a9fd7c02bd7201f36344b47142badc3c3ef22f88"} integrant/integrant {:mvn/version "0.8.0"}
com.stuartsierra/dependency {:mvn/version "1.0.0"} com.stuartsierra/dependency {:mvn/version "1.0.0"}
listora/again {:mvn/version "1.0.0"} listora/again {:mvn/version "1.0.0"}
org.clojure/tools.gitlibs {:mvn/version "2.4.172"} org.clojure/tools.gitlibs {:mvn/version "2.4.172"}
@ -170,15 +171,7 @@
:deps/manifest :deps} :deps/manifest :deps}
net.cgrand/xforms {:git/url "https://github.com/cgrand/xforms" net.cgrand/xforms {:git/url "https://github.com/cgrand/xforms"
:git/sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6" :git/sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6"
:deps/manifest :deps} :deps/manifest :deps}}
prismatic/plumbing {:git/url "https://github.com/plumatic/plumbing",
:git/sha "424bc704f2db422de34269c139a5494314b3a43b"}
org.clj-commons/hickory {:git/url "https://github.com/clj-commons/hickory"
:git/sha "9385b6708ef35f161732d8464b3a3aa57dd79f30"}
com.potetm/fusebox {:git/url "https://github.com/potetm/fusebox"
:git/sha "ac6d6a0a69510b009b3c1bb2247cd110fd9f7246"}
net.sekao/odoyle-rules {:git/url "https://github.com/oakes/odoyle-rules"
:git/sha "0b1d825ec45a998c4d3481dfb292e08ce6a47f0b"}}
:classpath-overrides {org.clojure/clojure nil :classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}} org.clojure/spec.alpha nil}}
:clj-nvd :clj-nvd

View file

@ -7,7 +7,7 @@ Args=-H:+ReportExceptionStackTraces \
-H:IncludeResources=src/babashka/.* \ -H:IncludeResources=src/babashka/.* \
-H:IncludeResources=SCI_VERSION \ -H:IncludeResources=SCI_VERSION \
-H:Log=registerResource:3 \ -H:Log=registerResource:3 \
--enable-url-protocols=http,https,jar,unix \ -H:EnableURLProtocols=http,https,jar,unix \
--enable-all-security-services \ --enable-all-security-services \
-H:+JNI \ -H:+JNI \
--no-server \ --no-server \
@ -26,32 +26,4 @@ Args=-H:+ReportExceptionStackTraces \
-H:ServiceLoaderFeatureExcludeServices=javax.sound.midi.spi.SoundbankReader \ -H:ServiceLoaderFeatureExcludeServices=javax.sound.midi.spi.SoundbankReader \
-H:ServiceLoaderFeatureExcludeServices=javax.sound.midi.spi.MidiFileWriter \ -H:ServiceLoaderFeatureExcludeServices=javax.sound.midi.spi.MidiFileWriter \
-H:ServiceLoaderFeatureExcludeServices=java.net.ContentHandlerFactory \ -H:ServiceLoaderFeatureExcludeServices=java.net.ContentHandlerFactory \
-H:ServiceLoaderFeatureExcludeServices=java.nio.charset.spi.CharsetProvider \ -H:ServiceLoaderFeatureExcludeServices=java.nio.charset.spi.CharsetProvider
-EBABASHKA_STATIC \
-EBABASHKA_MUSL \
-EBABASHKA_FEATURE_YAML \
-EBABASHKA_FEATURE_XML \
-EBABASHKA_FEATURE_CSV \
-EBABASHKA_FEATURE_TRANSIT \
-EBABASHKA_FEATURE_JAVA_TIME \
-EBABASHKA_FEATURE_JAVA_NET_HTTP \
-EBABASHKA_FEATURE_JAVA_NIO \
-EBABASHKA_FEATURE_HTTPKIT_CLIENT \
-EBABASHKA_FEATURE_HTTPKIT_SERVER \
-EBABASHKA_FEATURE_CORE_MATCH \
-EBABASHKA_FEATURE_HICCUP \
-EBABASHKA_FEATURE_TEST_CHECK \
-EBABASHKA_FEATURE_SELMER \
-EBABASHKA_FEATURE_LOGGING \
-EBABASHKA_FEATURE_PRIORITY_MAP \
-EBABASHKA_FEATURE_JDBC \
-EBABASHKA_FEATURE_SQLITE \
-EBABASHKA_FEATURE_POSTGRESQL \
-EBABASHKA_FEATURE_ORACLEDB \
-EBABASHKA_FEATURE_HSQLDB \
-EBABASHKA_FEATURE_DATASCRIPT \
-EBABASHKA_FEATURE_LANTERNA \
-EBABASHKA_FEATURE_SPEC_ALPHA \
-EBABASHKA_FEATURE_RRB_VECTOR \
-EBABASHKA_REQUIRE_SCAN \
-EBABASHKA_SHA

View file

@ -1,31 +0,0 @@
[{
"interfaces": [
"java.util.function.Predicate"
]
},
{
"interfaces": [
"java.util.function.Function"
]
},
{
"interfaces": [
"java.io.FileFilter"
]
},
{
"interfaces": [
"java.nio.file.DirectoryStream$Filter"
]
},
{
"interfaces": [
"java.util.function.Supplier"
]
},
{
"interfaces": [
"java.util.function.UnaryOperator"
]
}
]

View file

@ -1,31 +0,0 @@
(ns clojure.repl.deps
(:require [babashka.deps :as deps]))
(defn add-libs
"Given lib-coords, a map of lib to coord, will resolve all transitive deps for the libs
together and add them to the repl classpath, unlike separate calls to add-lib."
{:added "1.12"}
[lib-coords]
(deps/add-deps {:deps lib-coords})
nil)
(defn add-lib
"Given a lib that is not yet on the repl classpath, make it available by
downloading the library if necessary and adding it to the classloader.
Libs already on the classpath are not updated. Requires a valid parent
DynamicClassLoader.
lib - symbol identifying a library, for Maven: groupId/artifactId
coord - optional map of location information specific to the procurer,
or latest if not supplied
Returns coll of libs loaded, including transitive (or nil if none).
For info on libs, coords, and versions, see:
https://clojure.org/reference/deps_and_cli"
{:added "1.12"}
([lib coord]
(add-libs {lib coord}))
([lib]
(throw (ex-info "add-lib without explicit version isn't supported in babashka (yet)" {:lib lib}))))

2
sci

@ -1 +1 @@
Subproject commit e85433a0214114fdceb4ca896e1b9c27b1bdf713 Subproject commit 292431c7fd13e5ce9cdc20cb78be742dabd15d8d

View file

@ -45,8 +45,8 @@
"appveyor.yml" "appveyor.yml"
"project.clj" "project.clj"
"script/bump_graal_version.clj" "script/bump_graal_version.clj"
".cirrus.yml" ".circleci/script/short_ci.clj"
"script/install-graalvm"]) ".cirrus.yml"])
;; We might have to keep changing these from ;; We might have to keep changing these from
;; time to time whenever the version is bumped ;; time to time whenever the version is bumped
@ -54,7 +54,8 @@
;; OR ;; OR
;; ;;
;; We could have them as environment variables ;; We could have them as environment variables
(def current-graal-version "24") (def current-graal-version "22.3.1")
(def current-java-version "java19")
(def cl-options (def cl-options
[["-g" "--graal VERSION" "graal version"] [["-g" "--graal VERSION" "graal version"]
@ -90,12 +91,19 @@
[args] [args]
(when (empty? args) (when (empty? args)
(display-help)) (display-help))
(let [new-graal-version (:graal args)] (let [new-graal-version (:graal args)
new-java-version (:java args)]
(when (not (nil? new-graal-version)) (when (not (nil? new-graal-version))
(if (is-valid-bump? new-graal-version nil) (if (is-valid-bump? new-graal-version nil)
(do (do
(println "Performing Graal bump...") (println "Performing Graal bump...")
(bump-current current-graal-version new-graal-version)) (bump-current current-graal-version new-graal-version))
(show-error new-graal-version))))) (show-error new-graal-version)))
(when (not (nil? new-java-version))
(if (is-valid-bump? new-java-version nil)
(do
(println "Performing Java bump...")
(bump-current current-java-version new-java-version))
(show-error new-java-version)))))
(exec-script cl-args) (exec-script cl-args)

View file

@ -39,29 +39,26 @@ args=("-jar" "$BABASHKA_JAR"
# "-H:DashboardDump=reports/dump" # "-H:DashboardDump=reports/dump"
# "-H:+DashboardPretty" # "-H:+DashboardPretty"
# "-H:+DashboardJson" # "-H:+DashboardJson"
# "-H:ReportAnalysisForbiddenType=java.awt.Toolkit:Instantiated" "-H:ReportAnalysisForbiddenType=java.awt.Toolkit:InHeap,Allocated"
"--verbose" "--verbose"
"--no-fallback" "--no-fallback"
"--native-image-info" "--native-image-info"
"--install-exit-handlers" "--install-exit-handlers"
# --trace-class-initialization=jdk.internal.net.http.common.DebugLogger,jdk.internal.net.http.websocket.WebSocketImpl,jdk.internal.net.http.common.Utils # --trace-class-initialization=jdk.internal.net.http.common.DebugLogger,jdk.internal.net.http.websocket.WebSocketImpl,jdk.internal.net.http.common.Utils
"$BABASHKA_XMX" "$BABASHKA_XMX"
"--enable-preview" "--enable-preview")
"-march=compatibility" # necessary for compatibility with older machines, e.g. see https://github.com/borkdude/deps.clj/actions/runs/6337277754/job/17212028399
"-O1")
BABASHKA_STATIC=${BABASHKA_STATIC:-} BABASHKA_STATIC=${BABASHKA_STATIC:-}
BABASHKA_MUSL=${BABASHKA_MUSL:-} BABASHKA_MUSL=${BABASHKA_MUSL:-}
if [ "$BABASHKA_STATIC" = "true" ]; then if [ "$BABASHKA_STATIC" = "true" ]; then
args+=("--static")
if [ "$BABASHKA_MUSL" = "true" ]; then if [ "$BABASHKA_MUSL" = "true" ]; then
args+=("--static")
args+=("--libc=musl" args+=("--libc=musl"
# see https://github.com/oracle/graal/issues/3398 # see https://github.com/oracle/graal/issues/3398
"-H:CCompilerOption=-Wl,-z,stack-size=2097152") "-H:CCompilerOption=-Wl,-z,stack-size=2097152")
else else
# see https://github.com/oracle/graal/issues/3737 # see https://github.com/oracle/graal/issues/3737
args+=("-H:+UnlockExperimentalVMOptions")
args+=("-H:+StaticExecutableWithDynamicLibC") args+=("-H:+StaticExecutableWithDynamicLibC")
fi fi
fi fi
@ -107,14 +104,4 @@ then
export BABASHKA_FEATURE_PRIORITY_MAP="${BABASHKA_FEATURE_PRIORITY_MAP:-false}" export BABASHKA_FEATURE_PRIORITY_MAP="${BABASHKA_FEATURE_PRIORITY_MAP:-false}"
fi fi
if [[ -z "${BABASHKA_SHA:-}" ]]
then
sha=$(git rev-parse HEAD)
if [[ $? -eq 0 ]]; then
export BABASHKA_SHA=$sha
fi
fi
"$GRAALVM_HOME/bin/native-image" "${args[@]}" "$@" "$GRAALVM_HOME/bin/native-image" "${args[@]}" "$@"
./"$BABASHKA_BINARY" describe

View file

@ -23,13 +23,6 @@ Rem -H:EnableURLProtocols=jar,http,https is also not supported.
call %GRAALVM_HOME%\bin\gu.cmd install native-image call %GRAALVM_HOME%\bin\gu.cmd install native-image
if "%BABASHKA_SHA%"=="" (
for /f %%i in ('git rev-parse HEAD') do set sha=%%i
if not errorlevel 1 (
set BABASHKA_SHA=%sha%
)
)
call %GRAALVM_HOME%\bin\native-image.cmd ^ call %GRAALVM_HOME%\bin\native-image.cmd ^
"-jar" "target/babashka-%BABASHKA_VERSION%-standalone.jar" ^ "-jar" "target/babashka-%BABASHKA_VERSION%-standalone.jar" ^
"-H:Name=bb" ^ "-H:Name=bb" ^
@ -38,12 +31,8 @@ call %GRAALVM_HOME%\bin\native-image.cmd ^
"--no-fallback" ^ "--no-fallback" ^
"--enable-preview" ^ "--enable-preview" ^
"--install-exit-handlers" ^ "--install-exit-handlers" ^
"-march=compatibility" ^ "%BABASHKA_XMX%"
"-O1" ^
"%BABASHKA_XMX%" ^
%*
if %errorlevel% neq 0 exit /b %errorlevel% if %errorlevel% neq 0 exit /b %errorlevel%
call bb "(+ 1 2 3)" call bb "(+ 1 2 3)"
call bb describe

View file

@ -4,33 +4,37 @@ set -euo pipefail
INSTALL_DIR="${1:-$HOME}" INSTALL_DIR="${1:-$HOME}"
GRAALVM_VERSION="${GRAALVM_VERSION:-24}" GRAALVM_VERSION="${GRAALVM_VERSION:-21.2.0}"
GRAALVM_PLATFORM=$BABASHKA_PLATFORM case "$BABASHKA_PLATFORM" in
macos)
GRAALVM_PLATFORM="darwin"
;;
linux)
GRAALVM_PLATFORM="linux"
;;
esac
case "${BABASHKA_ARCH:-}" in case "${BABASHKA_ARCH:-}" in
aarch64) aarch64)
GRAALVM_ARCH="aarch64" GRAALVM_ARCH="aarch64"
;; ;;
*) *)
GRAALVM_ARCH="x64" GRAALVM_ARCH="amd64"
;; ;;
esac esac
GRAALVM_DIR_NAME="graalvm-$GRAALVM_VERSION" GRAALVM_FILENAME="graalvm-ce-java19-$GRAALVM_PLATFORM-$GRAALVM_ARCH-$GRAALVM_VERSION.tar.gz"
GRAALVM_FILENAME="graalvm-jdk-${GRAALVM_VERSION}_${GRAALVM_PLATFORM}-${GRAALVM_ARCH}_bin.tar.gz"
DOWNLOAD_URL="https://download.oracle.com/graalvm/${GRAALVM_VERSION}/archive/${GRAALVM_FILENAME}"
pushd "$INSTALL_DIR" >/dev/null pushd "$INSTALL_DIR" >/dev/null
if ! [ -d "$GRAALVM_DIR_NAME" ]; then if ! [ -d "graalvm-ce-java19-$GRAALVM_VERSION" ]; then
echo "Downloading GraalVM $GRAALVM_PLATFORM-$GRAALVM_ARCH-$GRAALVM_VERSION on '$PWD'..." echo "Downloading GraalVM $GRAALVM_PLATFORM-$GRAALVM_ARCH-$GRAALVM_VERSION on '$PWD'..."
echo "$DOWNLOAD_URL" echo "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-$GRAALVM_VERSION/$GRAALVM_FILENAME"
curl --fail -LO "$DOWNLOAD_URL" curl -LO "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-$GRAALVM_VERSION/$GRAALVM_FILENAME"
ls -la ls -la
mkdir "$GRAALVM_DIR_NAME" tar xzvf "$GRAALVM_FILENAME"
tar xzvf "$GRAALVM_FILENAME" -C "$GRAALVM_DIR_NAME" --strip-components 1 ls -la "graalvm-ce-java19-$GRAALVM_VERSION"
ls -la "$GRAALVM_DIR_NAME"
fi fi
popd >/dev/null popd >/dev/null

View file

@ -2,18 +2,12 @@
set -eo pipefail set -eo pipefail
: "${BABASHKA_TEST_ENV:=jvm}"
export BABASHKA_TEST_ENV
if [ "$BABASHKA_TEST_ENV" = "native" ]; then if [ "$BABASHKA_TEST_ENV" = "native" ]; then
BB_CMD="./bb" BB_CMD="./bb"
else else
BB_CMD="lein bb" BB_CMD="lein bb"
fi fi
export PATH
PATH=$(pwd)/process/target/test/on-path:$PATH
export BABASHKA_CLASSPATH export BABASHKA_CLASSPATH
BABASHKA_CLASSPATH=$(clojure -Spath -A:lib-tests) BABASHKA_CLASSPATH=$(clojure -Spath -A:lib-tests)

View file

@ -1,11 +1,7 @@
if not defined BABASHKA_TEST_ENV set BABASHKA_TEST_ENV=jvm
if "%BABASHKA_TEST_ENV%" EQU "native" (set BB_CMD=.\bb) else (set BB_CMD=lein bb) if "%BABASHKA_TEST_ENV%" EQU "native" (set BB_CMD=.\bb) else (set BB_CMD=lein bb)
set EDN=lib_tests.edn set EDN=lib_tests.edn
set PATH=%CD%\process\target\test\on-path;%PATH%
.\bb -f script/lib_tests/bb_edn_from_deps.clj %EDN% .\bb -f script/lib_tests/bb_edn_from_deps.clj %EDN%
%BB_CMD% --config %EDN% --deps-root . -f test-resources/lib_tests/babashka/run_all_libtests.clj %* %BB_CMD% --config %EDN% --deps-root . -f test-resources/lib_tests/babashka/run_all_libtests.clj %*

View file

@ -175,9 +175,6 @@ else
BABASHKA_LEIN_PROFILES+=",-feature/rrb-vector" BABASHKA_LEIN_PROFILES+=",-feature/rrb-vector"
fi fi
#lein with-profiles "$BABASHKA_LEIN_PROFILES,+reflection,-uberjar" deps :tree
#exit 0
mkdir -p resources/META-INF/babashka mkdir -p resources/META-INF/babashka
cp deps.edn resources/META-INF/babashka/deps.edn cp deps.edn resources/META-INF/babashka/deps.edn

View file

@ -1,8 +1,7 @@
(ns aaaa-this-has-to-be-first.because-patches (ns aaaa-this-has-to-be-first.because-patches
;; we need pprint loaded first, it patches pprint to not bloat the GraalVM binary ;; we need pprint loaded first, it patches pprint to not bloat the GraalVM binary
(:require [babashka.impl.patches.datafy] (:require [babashka.impl.patches.datafy]
[babashka.impl.pprint] [babashka.impl.pprint]))
))
;; Enable this for scanning requiring usage: ;; Enable this for scanning requiring usage:
(def enable-require-scan (def enable-require-scan

View file

@ -22,7 +22,7 @@
Examples: Examples:
(-> (clojure {:out :string} '-M '-e '(+ 1 2 3)]) deref :out) returns (-> (clojure '[-M -e (+ 1 2 3)] {:out :string}) deref :out) returns
\"6\n\". \"6\n\".
(-> @(clojure) :exit) starts a clojure REPL, waits for it (-> @(clojure) :exit) starts a clojure REPL, waits for it

View file

@ -1,120 +1,25 @@
(ns babashka.impl.cheshire (ns babashka.impl.cheshire
{:no-doc true} {:no-doc true}
(:require [cheshire.core :as json] (:require [cheshire.core :as json]
[cheshire.factory :as fact]
[sci.core :as sci :refer [copy-var]])) [sci.core :as sci :refer [copy-var]]))
(def tns (sci/create-ns 'cheshire.core nil)) (def tns (sci/create-ns 'cheshire.core nil))
(def fns (sci/create-ns 'cheshire.factory nil))
(def json-factory (sci/new-dynamic-var '*json-factory* nil {:ns fns}))
;; wrap cheshire fns to support `*json-factory*` dynamic var
(defn generate-string
([obj]
(binding [fact/*json-factory* @json-factory]
(json/generate-string obj)))
([obj opt-map]
(binding [fact/*json-factory* @json-factory]
(json/generate-string obj opt-map))))
(defn generate-stream
([obj writer]
(binding [fact/*json-factory* @json-factory]
(json/generate-stream obj writer)))
([obj writer opt-map]
(binding [fact/*json-factory* @json-factory]
(json/generate-stream obj writer opt-map))))
(defn parse-string
([string]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string string))))
([string key-fn]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string string key-fn))))
([^String string key-fn array-coerce-fn]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string string key-fn array-coerce-fn)))))
(defn parse-string-strict
([string]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string-strict string))))
([string key-fn]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string-strict string key-fn))))
([^String string key-fn array-coerce-fn]
(when string
(binding [fact/*json-factory* @json-factory]
(json/parse-string-strict string key-fn array-coerce-fn)))))
(defn parse-stream
([rdr]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream rdr))))
([rdr key-fn]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream rdr key-fn))))
([rdr key-fn array-coerce-fn]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream rdr key-fn array-coerce-fn)))))
(defn parse-stream-strict
([rdr]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream-strict rdr))))
([rdr key-fn]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream-strict rdr key-fn))))
([rdr key-fn array-coerce-fn]
(when rdr
(binding [fact/*json-factory* @json-factory]
(json/parse-stream-strict rdr key-fn array-coerce-fn)))))
(defn parsed-seq
([reader]
(binding [fact/*json-factory* @json-factory]
(json/parsed-seq reader)))
([reader key-fn]
(binding [fact/*json-factory* @json-factory]
(json/parsed-seq reader key-fn)))
([reader key-fn array-coerce-fn]
(binding [fact/*json-factory* @json-factory]
(json/parsed-seq reader key-fn array-coerce-fn))))
(def cheshire-core-namespace (def cheshire-core-namespace
{'encode (copy-var generate-string tns) {'encode (copy-var json/encode tns)
'generate-string (copy-var generate-string tns) 'generate-string (copy-var json/generate-string tns)
'encode-stream (copy-var generate-stream tns) 'encode-stream (copy-var json/encode-stream tns)
'generate-stream (copy-var generate-stream tns) 'generate-stream (copy-var json/generate-stream tns)
;;'encode-smile (copy-var json/encode-smile tns) ;;'encode-smile (copy-var json/encode-smile tns)
;;'generate-smile (copy-var json/generate-smile tns) ;;'generate-smile (copy-var json/generate-smile tns)
'decode (copy-var parse-string tns) 'decode (copy-var json/decode tns)
'parse-string (copy-var parse-string tns) 'parse-string (copy-var json/parse-string tns)
'parse-string-strict (copy-var parse-string-strict tns) 'parse-string-strict (copy-var json/parse-string-strict tns)
;;'parse-smile (copy-var json/parse-smile tns) ;;'parse-smile (copy-var json/parse-smile tns)
'parse-stream (copy-var parse-stream tns) 'parse-stream (copy-var json/parse-stream tns)
'parse-stream-strict (copy-var parse-stream-strict tns) 'parse-stream-strict (copy-var json/parse-stream-strict tns)
'parsed-seq (copy-var parsed-seq tns) 'parsed-seq (copy-var json/parsed-seq tns)
;;'parsed-smile-seq (copy-var json/parsed-smile-seq tns) ;;'parsed-smile-seq (copy-var json/parsed-smile-seq tns)
;;'decode-smile (copy-var json/decode-smile tns) ;;'decode-smile (copy-var json/decode-smile tns)
'default-pretty-print-options (copy-var json/default-pretty-print-options tns) 'default-pretty-print-options (copy-var json/default-pretty-print-options tns)
'create-pretty-printer (copy-var json/create-pretty-printer tns)}) 'create-pretty-printer (copy-var json/create-pretty-printer tns)})
(def cheshire-factory-namespace
{'*json-factory* json-factory
'default-factory-options (copy-var fact/default-factory-options fns)
'json-factory (copy-var fact/json-factory fns)
'make-json-factory (copy-var fact/make-json-factory fns)})

View file

@ -8,8 +8,6 @@
[sci.core :as sci] [sci.core :as sci]
[sci.impl.types :as t])) [sci.impl.types :as t]))
(set! *warn-on-reflection* true)
(def has-of-virtual? (def has-of-virtual?
(some #(= "ofVirtual" (.getName ^java.lang.reflect.Method %)) (some #(= "ofVirtual" (.getName ^java.lang.reflect.Method %))
(.getMethods Thread))) (.getMethods Thread)))
@ -91,8 +89,7 @@
java.util.Arrays java.util.Arrays
{:methods [{:name "copyOf"} {:methods [{:name "copyOf"}
{:name "copyOfRange"} {:name "copyOfRange"}
{:name "equals"} {:name "equals"}]}
{:name "fill"}]}
;; this fixes clojure.lang.Reflector for Java 11 ;; this fixes clojure.lang.Reflector for Java 11
java.lang.reflect.AccessibleObject java.lang.reflect.AccessibleObject
{:methods [{:name "canAccess"}]} {:methods [{:name "canAccess"}]}
@ -128,7 +125,6 @@
{:methods [{:name "aget"} {:methods [{:name "aget"}
{:name "aset"} {:name "aset"}
{:name "aclone"} {:name "aclone"}
{:name "iter"}
;; we expose this via the Compiler/LOADER dynamic var ;; we expose this via the Compiler/LOADER dynamic var
{:name "baseLoader"}]} {:name "baseLoader"}]}
clojure.lang.Compiler clojure.lang.Compiler
@ -181,8 +177,8 @@
(def custom-map (def custom-map
(cond-> (cond->
(merge base-custom-map (merge base-custom-map
proxy/custom-reflect-map) proxy/custom-reflect-map)
features/hsqldb? (assoc `org.hsqldb.dbinfo.DatabaseInformationFull features/hsqldb? (assoc `org.hsqldb.dbinfo.DatabaseInformationFull
{:methods [{:name "<init>" {:methods [{:name "<init>"
:parameterTypes ["org.hsqldb.Database"]}]} :parameterTypes ["org.hsqldb.Database"]}]}
@ -224,14 +220,11 @@
java.net.http.WebSocket$Listener java.net.http.WebSocket$Listener
java.security.cert.X509Certificate java.security.cert.X509Certificate
java.security.cert.CertificateFactory java.security.cert.CertificateFactory
java.security.Signature
javax.crypto.Cipher javax.crypto.Cipher
javax.crypto.KeyAgreement
javax.crypto.Mac javax.crypto.Mac
javax.crypto.SecretKey javax.crypto.SecretKey
javax.crypto.SecretKeyFactory javax.crypto.SecretKeyFactory
javax.crypto.spec.GCMParameterSpec javax.crypto.spec.GCMParameterSpec
javax.crypto.spec.IvParameterSpec
javax.crypto.spec.PBEKeySpec javax.crypto.spec.PBEKeySpec
javax.crypto.spec.SecretKeySpec javax.crypto.spec.SecretKeySpec
javax.net.ssl.HostnameVerifier ;; clj-http-lite javax.net.ssl.HostnameVerifier ;; clj-http-lite
@ -245,8 +238,6 @@
javax.net.ssl.TrustManagerFactory javax.net.ssl.TrustManagerFactory
javax.net.ssl.X509TrustManager javax.net.ssl.X509TrustManager
javax.net.ssl.X509ExtendedTrustManager javax.net.ssl.X509ExtendedTrustManager
javax.net.ssl.SSLSocket
javax.net.ssl.SSLSocketFactory
jdk.internal.net.http.HttpClientBuilderImpl jdk.internal.net.http.HttpClientBuilderImpl
jdk.internal.net.http.HttpClientFacade jdk.internal.net.http.HttpClientFacade
jdk.internal.net.http.HttpRequestBuilderImpl jdk.internal.net.http.HttpRequestBuilderImpl
@ -255,10 +246,6 @@
jdk.internal.net.http.websocket.BuilderImpl jdk.internal.net.http.websocket.BuilderImpl
jdk.internal.net.http.websocket.WebSocketImpl]) jdk.internal.net.http.websocket.WebSocketImpl])
(def thread-builder
(try (Class/forName "java.lang.Thread$Builder")
(catch Exception _ nil)))
(def classes (def classes
`{:all [clojure.lang.ArityException `{:all [clojure.lang.ArityException
clojure.lang.BigInt clojure.lang.BigInt
@ -283,7 +270,6 @@
java.io.FileOutputStream java.io.FileOutputStream
java.io.FileReader java.io.FileReader
java.io.FileWriter java.io.FileWriter
java.io.LineNumberReader
java.io.RandomAccessFile java.io.RandomAccessFile
java.io.InputStream java.io.InputStream
java.io.IOException java.io.IOException
@ -335,17 +321,13 @@
java.lang.ProcessBuilder$Redirect java.lang.ProcessBuilder$Redirect
java.lang.Runtime java.lang.Runtime
java.lang.RuntimeException java.lang.RuntimeException
java.lang.SecurityException
java.lang.Short java.lang.Short
java.lang.StackTraceElement java.lang.StackTraceElement
java.lang.String java.lang.String
java.lang.StringBuilder java.lang.StringBuilder
java.lang.System java.lang.System
java.lang.Throwable java.lang.Throwable
java.lang.ThreadLocal
java.lang.Thread$UncaughtExceptionHandler java.lang.Thread$UncaughtExceptionHandler
~@(when thread-builder
'[java.lang.Thread$Builder])
java.lang.UnsupportedOperationException java.lang.UnsupportedOperationException
java.lang.ref.WeakReference java.lang.ref.WeakReference
java.lang.ref.ReferenceQueue java.lang.ref.ReferenceQueue
@ -369,7 +351,6 @@
'[java.net.UnixDomainSocketAddress]) '[java.net.UnixDomainSocketAddress])
java.net.UnknownHostException java.net.UnknownHostException
java.net.URI java.net.URI
java.net.URISyntaxException
;; java.net.URL, see custom map ;; java.net.URL, see custom map
java.net.URLConnection java.net.URLConnection
java.net.URLEncoder java.net.URLEncoder
@ -383,12 +364,8 @@
java.nio.MappedByteBuffer java.nio.MappedByteBuffer
java.nio.file.OpenOption java.nio.file.OpenOption
java.nio.file.StandardOpenOption java.nio.file.StandardOpenOption
java.nio.channels.ByteChannel
java.nio.channels.Channels
java.nio.channels.FileChannel java.nio.channels.FileChannel
java.nio.channels.FileChannel$MapMode java.nio.channels.FileChannel$MapMode
java.nio.channels.ReadableByteChannel
java.nio.channels.WritableByteChannel
java.nio.channels.ServerSocketChannel java.nio.channels.ServerSocketChannel
java.nio.channels.SocketChannel java.nio.channels.SocketChannel
java.nio.charset.Charset java.nio.charset.Charset
@ -404,7 +381,6 @@
java.nio.file.FileVisitOption java.nio.file.FileVisitOption
java.nio.file.FileVisitResult java.nio.file.FileVisitResult
java.nio.file.Files java.nio.file.Files
java.nio.file.DirectoryStream$Filter
java.nio.file.LinkOption java.nio.file.LinkOption
java.nio.file.NoSuchFileException java.nio.file.NoSuchFileException
java.nio.file.Path java.nio.file.Path
@ -414,28 +390,19 @@
java.nio.file.attribute.BasicFileAttributes java.nio.file.attribute.BasicFileAttributes
java.nio.file.attribute.FileAttribute java.nio.file.attribute.FileAttribute
java.nio.file.attribute.FileTime java.nio.file.attribute.FileTime
java.nio.file.attribute.PosixFileAttributes
java.nio.file.attribute.PosixFilePermission java.nio.file.attribute.PosixFilePermission
java.nio.file.attribute.PosixFilePermissions java.nio.file.attribute.PosixFilePermissions])
java.nio.file.attribute.UserDefinedFileAttributeView])
java.security.DigestInputStream
java.security.KeyFactory
java.security.KeyPairGenerator
java.security.KeyPair
java.security.KeyStore
java.security.MessageDigest java.security.MessageDigest
java.security.DigestInputStream
java.security.Provider java.security.Provider
java.security.KeyStore
java.security.SecureRandom java.security.SecureRandom
java.security.Security java.security.Security
java.security.spec.ECGenParameterSpec
java.security.spec.PKCS8EncodedKeySpec
java.security.spec.X509EncodedKeySpec
java.sql.Date java.sql.Date
java.text.ParseException java.text.ParseException
java.text.ParsePosition java.text.ParsePosition
;; adds about 200kb, same functionality provided by java.time: ;; adds about 200kb, same functionality provided by java.time:
java.text.SimpleDateFormat java.text.SimpleDateFormat
java.text.BreakIterator
~@(when features/java-time? ~@(when features/java-time?
`[java.time.format.DateTimeFormatter `[java.time.format.DateTimeFormatter
java.time.Clock java.time.Clock
@ -470,33 +437,25 @@
java.time.temporal.TemporalAdjusters java.time.temporal.TemporalAdjusters
java.time.temporal.TemporalAmount java.time.temporal.TemporalAmount
java.time.temporal.TemporalField java.time.temporal.TemporalField
java.time.temporal.WeekFields
~(symbol "[Ljava.time.temporal.TemporalField;") ~(symbol "[Ljava.time.temporal.TemporalField;")
java.time.format.TextStyle java.time.format.TextStyle
java.time.temporal.Temporal java.time.temporal.Temporal
java.time.temporal.TemporalAccessor java.time.temporal.TemporalAccessor
java.time.temporal.TemporalAdjuster java.time.temporal.TemporalAdjuster
java.time.temporal.TemporalQuery java.time.temporal.TemporalQuery
~(symbol "[Ljava.time.temporal.TemporalQuery;") ~(symbol "[Ljava.time.temporal.TemporalQuery;")])
java.time.chrono.ChronoLocalDate
java.time.temporal.TemporalUnit
java.time.chrono.ChronoLocalDateTime
java.time.chrono.ChronoZonedDateTime
java.time.chrono.Chronology])
java.util.concurrent.atomic.AtomicInteger java.util.concurrent.atomic.AtomicInteger
java.util.concurrent.atomic.AtomicLong java.util.concurrent.atomic.AtomicLong
java.util.concurrent.atomic.AtomicReference java.util.concurrent.atomic.AtomicReference
java.util.concurrent.Callable java.util.concurrent.Callable
java.util.concurrent.CancellationException java.util.concurrent.CancellationException
java.util.concurrent.CompletionException java.util.concurrent.CompletionException
java.util.concurrent.CountDownLatch
java.util.concurrent.ExecutionException java.util.concurrent.ExecutionException
java.util.concurrent.Executor java.util.concurrent.Executor
java.util.concurrent.ExecutorService java.util.concurrent.ExecutorService
java.util.concurrent.BlockingQueue java.util.concurrent.BlockingQueue
java.util.concurrent.ArrayBlockingQueue java.util.concurrent.ArrayBlockingQueue
java.util.concurrent.LinkedBlockingQueue java.util.concurrent.LinkedBlockingQueue
java.util.concurrent.ScheduledFuture
java.util.concurrent.ScheduledThreadPoolExecutor java.util.concurrent.ScheduledThreadPoolExecutor
java.util.concurrent.Semaphore java.util.concurrent.Semaphore
java.util.concurrent.ThreadFactory java.util.concurrent.ThreadFactory
@ -512,10 +471,6 @@
java.util.concurrent.CompletableFuture java.util.concurrent.CompletableFuture
java.util.concurrent.Executors java.util.concurrent.Executors
java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit
java.util.concurrent.CompletionStage
java.util.concurrent.locks.ReentrantLock
java.util.concurrent.ThreadLocalRandom
java.util.concurrent.ConcurrentHashMap
java.util.jar.Attributes java.util.jar.Attributes
java.util.jar.Attributes$Name java.util.jar.Attributes$Name
java.util.jar.JarFile java.util.jar.JarFile
@ -526,11 +481,9 @@
java.util.jar.Manifest java.util.jar.Manifest
java.util.stream.BaseStream java.util.stream.BaseStream
java.util.stream.Stream java.util.stream.Stream
java.util.stream.IntStream
java.util.Random java.util.Random
java.util.regex.Matcher java.util.regex.Matcher
java.util.regex.Pattern java.util.regex.Pattern
java.util.regex.PatternSyntaxException
java.util.ArrayDeque java.util.ArrayDeque
java.util.ArrayList java.util.ArrayList
java.util.Collections java.util.Collections
@ -540,7 +493,6 @@
java.util.Base64$Encoder java.util.Base64$Encoder
java.util.Date java.util.Date
java.util.HashMap java.util.HashMap
java.util.HashSet
java.util.IdentityHashMap java.util.IdentityHashMap
java.util.InputMismatchException java.util.InputMismatchException
java.util.List java.util.List
@ -592,22 +544,8 @@
~(symbol "[Ljava.util.regex.Pattern;") ~(symbol "[Ljava.util.regex.Pattern;")
~(symbol "[Lclojure.core$range;")]) ~(symbol "[Lclojure.core$range;")])
~@(when features/yaml? '[org.yaml.snakeyaml.error.YAMLException]) ~@(when features/yaml? '[org.yaml.snakeyaml.error.YAMLException])
~@(when features/hsqldb? '[org.hsqldb.jdbcDriver]) ~@(when features/hsqldb? '[org.hsqldb.jdbcDriver])]
org.jsoup.Jsoup
org.jsoup.nodes.Attribute
org.jsoup.nodes.Attributes
org.jsoup.nodes.Comment
org.jsoup.nodes.DataNode
org.jsoup.nodes.Document
org.jsoup.nodes.DocumentType
org.jsoup.nodes.Element
org.jsoup.nodes.Node
org.jsoup.nodes.TextNode
org.jsoup.nodes.XmlDeclaration
org.jsoup.parser.Tag
org.jsoup.parser.Parser]
:constructors [clojure.lang.Delay :constructors [clojure.lang.Delay
clojure.lang.DynamicClassLoader
clojure.lang.LineNumberingPushbackReader clojure.lang.LineNumberingPushbackReader
java.io.EOFException] java.io.EOFException]
:methods [borkdude.graal.LockFix] ;; support for locking :methods [borkdude.graal.LockFix] ;; support for locking
@ -647,18 +585,13 @@
clojure.lang.IRef clojure.lang.IRef
clojure.lang.ISeq clojure.lang.ISeq
clojure.lang.IPersistentVector clojure.lang.IPersistentVector
clojure.lang.ITransientSet
clojure.lang.ITransientVector clojure.lang.ITransientVector
clojure.lang.Iterate clojure.lang.Iterate
clojure.lang.LispReader$Resolver clojure.lang.LispReader$Resolver
clojure.lang.LongRange
clojure.lang.Named clojure.lang.Named
clojure.lang.Keyword clojure.lang.Keyword
clojure.lang.PersistentArrayMap clojure.lang.PersistentArrayMap
clojure.lang.PersistentArrayMap$TransientArrayMap
clojure.lang.PersistentHashMap$TransientHashMap
clojure.lang.PersistentHashSet clojure.lang.PersistentHashSet
clojure.lang.PersistentHashSet$TransientHashSet
clojure.lang.PersistentList clojure.lang.PersistentList
clojure.lang.PersistentList$EmptyList clojure.lang.PersistentList$EmptyList
clojure.lang.PersistentQueue clojure.lang.PersistentQueue
@ -666,7 +599,6 @@
clojure.lang.PersistentTreeMap clojure.lang.PersistentTreeMap
clojure.lang.PersistentTreeSet clojure.lang.PersistentTreeSet
clojure.lang.PersistentVector clojure.lang.PersistentVector
clojure.lang.PersistentVector$TransientVector
clojure.lang.Range clojure.lang.Range
clojure.lang.Ratio clojure.lang.Ratio
clojure.lang.ReaderConditional clojure.lang.ReaderConditional
@ -685,14 +617,10 @@
java.lang.LinkageError java.lang.LinkageError
java.lang.ThreadDeath java.lang.ThreadDeath
java.lang.VirtualMachineError java.lang.VirtualMachineError
java.lang.NoSuchFieldException
java.sql.Timestamp java.sql.Timestamp
java.util.concurrent.TimeoutException java.util.concurrent.TimeoutException
java.util.Collection java.util.Collection
java.util.Map$Entry java.util.Map$Entry
java.util.AbstractMap
java.util.AbstractSet
java.util.AbstractList
~@(when features/xml? ['clojure.data.xml.node.Element])] ~@(when features/xml? ['clojure.data.xml.node.Element])]
:custom ~custom-map}) :custom ~custom-map})
@ -705,132 +633,86 @@
(:instance-checks classes)) (:instance-checks classes))
m (apply hash-map m (apply hash-map
(for [c classes (for [c classes
c [(list 'quote c) (cond-> `{:class ~c} c [(list 'quote c) c]]
(= 'java.lang.Class c)
(assoc :static-methods
{(list 'quote 'forName)
`(fn
([_# ^String class-name#]
(Class/forName class-name#))
([_# ^String class-name# initialize# ^java.lang.ClassLoader clazz-loader#]
(Class/forName class-name#)))}))]]
c)) c))
m (assoc m :public-class m (assoc m :public-class
(fn [v] (fn [v]
;; (prn :v v)
;; NOTE: a series of instance check, so far, is still cheaper ;; NOTE: a series of instance check, so far, is still cheaper
;; than piggybacking on defmulti or defprotocol ;; than piggybacking on defmulti or defprotocol
(let [res (cond (instance? java.lang.Process v) (cond (instance? java.lang.Process v)
java.lang.Process java.lang.Process
(instance? java.lang.ProcessHandle v) (instance? java.lang.ProcessHandle v)
java.lang.ProcessHandle java.lang.ProcessHandle
(instance? java.lang.ProcessHandle$Info v) (instance? java.lang.ProcessHandle$Info v)
java.lang.ProcessHandle$Info java.lang.ProcessHandle$Info
;; added for calling .put on .environment from ProcessBuilder ;; added for calling .put on .environment from ProcessBuilder
(instance? java.util.Map v) (instance? java.util.Map v)
java.util.Map java.util.Map
;; added for issue #239 regarding clj-http-lite ;; added for issue #239 regarding clj-http-lite
;; can potentially be removed due to fix for #1061 ;; can potentially be removed due to fix for #1061
(instance? java.io.ByteArrayOutputStream v) (instance? java.io.ByteArrayOutputStream v)
java.io.ByteArrayOutputStream java.io.ByteArrayOutputStream
(instance? java.security.MessageDigest v) (instance? java.security.MessageDigest v)
java.security.MessageDigest java.security.MessageDigest
;; streams ;; streams
(instance? java.io.InputStream v) (instance? java.io.InputStream v)
java.io.InputStream java.io.InputStream
(instance? java.io.OutputStream v) (instance? java.io.OutputStream v)
java.io.OutputStream java.io.OutputStream
;; java nio ;; java nio
(instance? java.nio.file.Path v) (instance? java.nio.file.Path v)
java.nio.file.Path java.nio.file.Path
(instance? java.nio.file.FileSystem v) (instance? java.nio.file.FileSystem v)
java.nio.file.FileSystem java.nio.file.FileSystem
(instance? java.nio.file.PathMatcher v) (instance? java.nio.file.PathMatcher v)
java.nio.file.PathMatcher java.nio.file.PathMatcher
(instance? java.util.stream.Stream v) (instance? java.util.stream.BaseStream v)
java.util.stream.Stream java.util.stream.BaseStream
(instance? java.util.stream.IntStream v) (instance? java.nio.ByteBuffer v)
java.util.stream.IntStream java.nio.ByteBuffer
(instance? java.util.stream.BaseStream v) (instance? java.nio.charset.Charset v)
java.util.stream.BaseStream java.nio.charset.Charset
(instance? java.nio.ByteBuffer v) (instance? java.nio.charset.CharsetEncoder v)
java.nio.ByteBuffer java.nio.charset.CharsetEncoder
(instance? java.nio.charset.Charset v) (instance? java.nio.CharBuffer v)
java.nio.charset.Charset java.nio.CharBuffer
(instance? java.nio.charset.CharsetEncoder v) (instance? java.nio.channels.FileChannel v)
java.nio.charset.CharsetEncoder java.nio.channels.FileChannel
(instance? java.nio.CharBuffer v) (instance? java.nio.channels.ServerSocketChannel v)
java.nio.CharBuffer java.nio.channels.ServerSocketChannel
(instance? java.nio.channels.FileChannel v) (instance? java.nio.channels.SocketChannel v)
java.nio.channels.FileChannel java.nio.channels.SocketChannel
(instance? java.nio.channels.ServerSocketChannel v) (instance? java.net.CookieStore v)
java.nio.channels.ServerSocketChannel java.net.CookieStore
(instance? java.nio.channels.SocketChannel v) ;; this makes interop on reified classes work
java.nio.channels.SocketChannel ;; see java_net_http_test/interop-test
(instance? java.net.CookieStore v) (instance? sci.impl.types.IReified v)
java.net.CookieStore (first (t/getInterfaces v))
;; this makes interop on reified classes work ;; fix for #1061
;; see java_net_http_test/interop-test (instance? java.net.URLClassLoader v)
(instance? sci.impl.types.IReified v) java.net.URLClassLoader
(first (t/getInterfaces v)) (instance? java.lang.ClassLoader v)
;; fix for #1061 java.lang.ClassLoader
(instance? java.net.URLClassLoader v) (instance? java.io.Closeable v)
java.net.URLClassLoader java.io.Closeable
(instance? java.lang.ClassLoader v) (instance? java.nio.file.attribute.BasicFileAttributes v)
java.lang.ClassLoader java.nio.file.attribute.BasicFileAttributes
(instance? java.nio.file.attribute.PosixFileAttributes v) (instance? java.util.concurrent.Future v)
java.nio.file.attribute.PosixFileAttributes java.util.concurrent.Future
(instance? java.nio.file.attribute.BasicFileAttributes v) (instance? java.util.concurrent.ScheduledExecutorService v)
java.nio.file.attribute.BasicFileAttributes java.util.concurrent.ScheduledExecutorService
(instance? java.nio.file.attribute.UserDefinedFileAttributeView v) (instance? java.util.concurrent.ExecutorService v)
java.nio.file.attribute.UserDefinedFileAttributeView java.util.concurrent.ExecutorService
(instance? java.util.concurrent.Future v) (instance? java.util.Iterator v)
java.util.concurrent.Future java.util.Iterator
(instance? java.util.concurrent.ScheduledExecutorService v) (instance? javax.crypto.SecretKey v)
java.util.concurrent.ScheduledExecutorService javax.crypto.SecretKey
(instance? java.util.concurrent.ExecutorService v) (instance? java.lang.Thread v)
java.util.concurrent.ExecutorService java.lang.Thread
(instance? java.util.Iterator v) (instance? java.security.cert.X509Certificate v)
java.util.Iterator java.security.cert.X509Certificate
(instance? javax.crypto.SecretKey v) ;; keep commas for merge friendliness
javax.crypto.SecretKey ,,,)))
(instance? javax.net.ssl.SSLSocketFactory v)
javax.net.ssl.SSLSocketFactory
(instance? javax.net.ssl.SSLSocket v)
javax.net.ssl.SSLSocket
(instance? java.lang.Thread v)
java.lang.Thread
(instance? java.util.concurrent.ThreadFactory v)
java.util.concurrent.ThreadFactory
(instance? java.security.cert.X509Certificate v)
java.security.cert.X509Certificate
(instance? java.io.Console v)
java.io.Console
(instance? java.security.KeyPairGenerator v)
java.security.KeyPairGenerator
(instance? java.security.Signature v)
java.security.Signature
(instance? java.security.Key v)
java.security.Key
(instance? java.util.Set v)
java.util.Set
(instance? java.io.Closeable v)
java.io.Closeable
(instance? java.util.Collection v)
java.util.Collection
(instance? java.lang.Throwable v)
java.lang.Throwable
(instance? org.jsoup.nodes.Element v)
org.jsoup.nodes.Element
(and thread-builder
(instance? thread-builder v))
thread-builder
(instance? java.text.BreakIterator v)
java.text.BreakIterator
;; keep commas for merge friendliness
,)]
;; (prn :res res)
res)))
m (assoc m (list 'quote 'clojure.lang.Var) 'sci.lang.Var) m (assoc m (list 'quote 'clojure.lang.Var) 'sci.lang.Var)
m (assoc m (list 'quote 'clojure.lang.Namespace) 'sci.lang.Namespace)] m (assoc m (list 'quote 'clojure.lang.Namespace) 'sci.lang.Namespace)]
m)) m))
@ -841,14 +723,6 @@
allowed to be initialized at build time." allowed to be initialized at build time."
(gen-class-map)) (gen-class-map))
#_(let [class-name (str c)]
(cond-> (Class/forName class-name)
(= "java.lang.Class" class-name)
(->> (hash-map :static-methods {'forName (fn [class-name]
(prn :class-for)
(Class/forName class-name))}
:class))))
(def class-map (def class-map
"A delay to delay initialization of java-net-http classes to run time, since GraalVM 22.1" "A delay to delay initialization of java-net-http classes to run time, since GraalVM 22.1"
(delay (persistent! (reduce (fn [acc c] (delay (persistent! (reduce (fn [acc c]
@ -882,8 +756,6 @@
Integer java.lang.Integer Integer java.lang.Integer
InterruptedException java.lang.InterruptedException InterruptedException java.lang.InterruptedException
Iterable java.lang.Iterable Iterable java.lang.Iterable
;; NOTE: in hindsight File never belonged to the default imports of Clojure,
;; but it's been here to long to remove probably
File java.io.File File java.io.File
Float java.lang.Float Float java.lang.Float
Long java.lang.Long Long java.lang.Long
@ -893,26 +765,22 @@
Number java.lang.Number Number java.lang.Number
NumberFormatException java.lang.NumberFormatException NumberFormatException java.lang.NumberFormatException
Object java.lang.Object Object java.lang.Object
Runnable java.lang.Runnable
Runtime java.lang.Runtime Runtime java.lang.Runtime
RuntimeException java.lang.RuntimeException RuntimeException java.lang.RuntimeException
Process java.lang.Process Process java.lang.Process
ProcessBuilder java.lang.ProcessBuilder ProcessBuilder java.lang.ProcessBuilder
SecurityException java.lang.SecurityException
Short java.lang.Short Short java.lang.Short
StackTraceElement java.lang.StackTraceElement StackTraceElement java.lang.StackTraceElement
String java.lang.String String java.lang.String
StringBuilder java.lang.StringBuilder StringBuilder java.lang.StringBuilder
System java.lang.System System java.lang.System
Thread java.lang.Thread Thread java.lang.Thread
ThreadLocal java.lang.ThreadLocal
Thread$UncaughtExceptionHandler java.lang.Thread$UncaughtExceptionHandler Thread$UncaughtExceptionHandler java.lang.Thread$UncaughtExceptionHandler
Throwable java.lang.Throwable Throwable java.lang.Throwable
VirtualMachineError java.lang.VirtualMachineError VirtualMachineError java.lang.VirtualMachineError
ThreadDeath java.lang.ThreadDeath ThreadDeath java.lang.ThreadDeath
UnsupportedOperationException java.lang.UnsupportedOperationException}) UnsupportedOperationException java.lang.UnsupportedOperationException
})
;; (eval (vec (keys imports)))
(defn reflection-file-entries [] (defn reflection-file-entries []
(let [entries (vec (for [c (sort (concat (:all classes) (let [entries (vec (for [c (sort (concat (:all classes)
@ -954,13 +822,13 @@
"resources/META-INF/native-image/babashka/babashka/reflect-config.json") "resources/META-INF/native-image/babashka/babashka/reflect-config.json")
(json/generate-string all-entries {:pretty true})))) (json/generate-string all-entries {:pretty true}))))
(defn public-declared-method? [^Class c ^java.lang.reflect.Method m] (defn public-declared-method? [c m]
(and (= c (.getDeclaringClass m)) (and (= c (.getDeclaringClass m))
(not (.getAnnotation m Deprecated)))) (not (.getAnnotation m Deprecated))))
(defn public-declared-method-names [^Class c] (defn public-declared-method-names [c]
(->> (.getMethods c) (->> (.getMethods c)
(keep (fn [^java.lang.reflect.Method m] (keep (fn [m]
(when (public-declared-method? c m) (when (public-declared-method? c m)
{:class c {:class c
:name (.getName m)}))) :name (.getName m)})))
@ -988,4 +856,6 @@
(public-declared-method-names java.net.URL) (public-declared-method-names java.net.URL)
(public-declared-method-names java.util.Properties) (public-declared-method-names java.util.Properties)
(all-classes)) (all-classes)
)

View file

@ -74,7 +74,7 @@
(defn split-classpath (defn split-classpath
"Returns the classpath as a seq of strings, split by the platform "Returns the classpath as a seq of strings, split by the platform
specific path separator." specific path separator."
([^String cp] (vec (when cp (.split cp path-sep))))) ([^String cp] (vec (.split cp path-sep))))
(defn get-classpath (defn get-classpath
"Returns the current classpath as set by --classpath, BABASHKA_CLASSPATH and add-classpath." "Returns the current classpath as set by --classpath, BABASHKA_CLASSPATH and add-classpath."
@ -84,8 +84,8 @@
cp))) cp)))
(defn resource (defn resource
(^URL [path] (resource path @the-url-loader)) (^URL [path] (resource @the-url-loader path))
(^URL [path loader] (^URL [loader path]
(if (str/starts-with? path "/") nil ;; non-relative paths always return nil (if (str/starts-with? path "/") nil ;; non-relative paths always return nil
(getResource loader [path] true)))) (getResource loader [path] true))))

View file

@ -17,8 +17,6 @@
(let [extra-opts '%s (let [extra-opts '%s
sym `%s sym `%s
the-var (requiring-resolve sym) the-var (requiring-resolve sym)
_ (when-not the-var
(throw (ex-info (str \"Could not resolve sym to a function: \" sym) {:babashka/exit 1})))
the-var-meta (meta the-var) the-var-meta (meta the-var)
ns (:ns (meta the-var)) ns (:ns (meta the-var))
ns-meta (meta ns) ns-meta (meta ns)

View file

@ -3,6 +3,7 @@
(:refer-clojure :exclude [future read+string clojure-version with-precision (:refer-clojure :exclude [future read+string clojure-version with-precision
send-via send send-off sync into-array]) send-via send send-off sync into-array])
(:require [babashka.impl.common :as common] (:require [babashka.impl.common :as common]
[borkdude.graal.locking :as locking]
[clojure.core :as c] [clojure.core :as c]
[clojure.string :as str] [clojure.string :as str]
[sci.core :as sci] [sci.core :as sci]
@ -11,6 +12,18 @@
[sci.impl.utils :refer [clojure-core-ns]] [sci.impl.utils :refer [clojure-core-ns]]
[sci.impl.vars :as vars])) [sci.impl.vars :as vars]))
(defn locking* [form bindings v f & args]
(apply @#'locking/locking form bindings v f args))
(defn time*
"Evaluates expr and prints the time it took. Returns the value of
expr."
[_ _ expr]
`(let [start# (. System (nanoTime))
ret# ~expr]
(prn (str "Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs"))
ret#))
(defn core-dynamic-var (defn core-dynamic-var
([sym] (core-dynamic-var sym nil)) ([sym] (core-dynamic-var sym nil))
([sym init-val] (sci/new-dynamic-var sym init-val {:ns clojure-core-ns}))) ([sym init-val] (sci/new-dynamic-var sym init-val {:ns clojure-core-ns})))
@ -23,7 +36,6 @@
(def math-context (core-dynamic-var '*math-context*)) (def math-context (core-dynamic-var '*math-context*))
(def compile-path (core-dynamic-var '*compile-path* *compile-path*)) (def compile-path (core-dynamic-var '*compile-path* *compile-path*))
(def compiler-options (core-dynamic-var '*compiler-options*)) (def compiler-options (core-dynamic-var '*compiler-options*))
(def repl (core-dynamic-var '*repl* true)) ;; set to true, basically just a dummy for now
(defn read+string (defn read+string
"Added for compatibility. Must be used with "Added for compatibility. Must be used with
@ -52,7 +64,7 @@
The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN, The rounding mode is one of CEILING, FLOOR, HALF_UP, HALF_DOWN,
HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP." HALF_EVEN, UP, DOWN and UNNECESSARY; it defaults to HALF_UP."
[precision & exprs] [precision & exprs]
(let [[body rm] (if (= :rounding (first exprs)) (let [[body rm] (if (= (first exprs) :rounding)
[(next (next exprs)) [(next (next exprs))
`((. java.math.RoundingMode ~(second exprs)))] `((. java.math.RoundingMode ~(second exprs)))]
[exprs nil])] [exprs nil])]
@ -118,7 +130,7 @@
:static true} :static true}
([aseq] ([aseq]
(try (clojure.lang.RT/seqToTypedArray (seq aseq)) (try (clojure.lang.RT/seqToTypedArray (seq aseq))
(catch Throwable _ (catch IllegalArgumentException _
(clojure.lang.RT/seqToTypedArray Object (seq aseq))))) (clojure.lang.RT/seqToTypedArray Object (seq aseq)))))
([type aseq] ([type aseq]
(clojure.lang.RT/seqToTypedArray type (seq aseq)))) (clojure.lang.RT/seqToTypedArray type (seq aseq))))
@ -144,9 +156,11 @@
'file-seq (copy-core-var file-seq) 'file-seq (copy-core-var file-seq)
'promise (copy-core-var promise) 'promise (copy-core-var promise)
'deliver (copy-core-var deliver) 'deliver (copy-core-var deliver)
'locking (macrofy 'locking locking*)
'shutdown-agents (copy-core-var shutdown-agents) 'shutdown-agents (copy-core-var shutdown-agents)
'slurp (copy-core-var slurp) 'slurp (copy-core-var slurp)
'spit (copy-core-var spit) 'spit (copy-core-var spit)
'time (macrofy 'time time*)
'Throwable->map (copy-core-var Throwable->map) 'Throwable->map (copy-core-var Throwable->map)
'tap> (copy-core-var tap>) 'tap> (copy-core-var tap>)
'add-tap (copy-core-var add-tap) 'add-tap (copy-core-var add-tap)
@ -163,7 +177,6 @@
'*math-context* math-context '*math-context* math-context
'*compiler-options* compiler-options '*compiler-options* compiler-options
'*compile-path* compile-path '*compile-path* compile-path
'*source-path* sci/file
'with-precision (sci/copy-var with-precision clojure-core-ns) 'with-precision (sci/copy-var with-precision clojure-core-ns)
'-with-precision (sci/copy-var -with-precision clojure-core-ns) '-with-precision (sci/copy-var -with-precision clojure-core-ns)
;; STM ;; STM
@ -174,8 +187,6 @@
'sync (sci/copy-var sync clojure-core-ns) 'sync (sci/copy-var sync clojure-core-ns)
'ref (sci/copy-var ref clojure-core-ns) 'ref (sci/copy-var ref clojure-core-ns)
'ref-set (sci/copy-var ref-set clojure-core-ns) 'ref-set (sci/copy-var ref-set clojure-core-ns)
'ensure (sci/copy-var ensure clojure-core-ns)
;; end STM
'update-vals (sci/copy-var update-vals clojure-core-ns) 'update-vals (sci/copy-var update-vals clojure-core-ns)
'update-keys (sci/copy-var update-keys clojure-core-ns) 'update-keys (sci/copy-var update-keys clojure-core-ns)
'parse-boolean (sci/copy-var parse-boolean clojure-core-ns) 'parse-boolean (sci/copy-var parse-boolean clojure-core-ns)
@ -193,15 +204,5 @@
'print-dup (sci/copy-var print-dup clojure-core-ns) 'print-dup (sci/copy-var print-dup clojure-core-ns)
'PrintWriter-on (sci/copy-var PrintWriter-on clojure-core-ns) 'PrintWriter-on (sci/copy-var PrintWriter-on clojure-core-ns)
'set-agent-send-executor! (sci/copy-var set-agent-send-executor! clojure-core-ns) 'set-agent-send-executor! (sci/copy-var set-agent-send-executor! clojure-core-ns)
'set-agent-send-off-executor! (sci/copy-var set-agent-send-off-executor! clojure-core-ns) 'set-agent-send-off-executor! (sci/copy-var set-agent-send-off-executor! clojure-core-ns)}
;; 1.12
'splitv-at (sci/copy-var splitv-at clojure-core-ns)
'stream-transduce! (sci/copy-var stream-transduce! clojure-core-ns)
'partitionv (sci/copy-var partitionv clojure-core-ns)
'stream-into! (sci/copy-var stream-into! clojure-core-ns)
'stream-reduce! (sci/copy-var stream-reduce! clojure-core-ns)
'stream-seq! (sci/copy-var stream-seq! clojure-core-ns)
'partitionv-all (sci/copy-var partitionv-all clojure-core-ns)
'*repl* repl
}
) )

View file

@ -2,39 +2,11 @@
{:no-doc true} {:no-doc true}
(:require [clojure.core.async :as async] (:require [clojure.core.async :as async]
[clojure.core.async.impl.protocols :as protocols] [clojure.core.async.impl.protocols :as protocols]
[clojure.core.async.impl.dispatch :as dispatch]
[sci.core :as sci :refer [copy-var]] [sci.core :as sci :refer [copy-var]]
[sci.impl.copy-vars :refer [macrofy]] [sci.impl.copy-vars :refer [macrofy]]
[sci.impl.vars :as vars]) [sci.impl.vars :as vars]))
(:import [java.util.concurrent Executors ExecutorService ThreadFactory]))
(set! *warn-on-reflection* true) (def ^java.util.concurrent.Executor executor @#'async/thread-macro-executor)
#_(def ^java.util.concurrent.Executor executor @#'async/thread-macro-executor)
(def executor-for
"Given a workload tag, returns an ExecutorService instance and memoizes the result. By
default, core.async will defer to a user factory (if provided via sys prop) or construct
a specialized ExecutorService instance for each tag :io, :compute, and :mixed. When
given the tag :core-async-dispatch it will default to the executor service for :io."
(memoize
(fn ^ExecutorService [workload]
(let [sysprop-factory nil #_(when-let [esf (System/getProperty "clojure.core.async.executor-factory")]
(requiring-resolve (symbol esf)))
sp-exec (and sysprop-factory (sysprop-factory workload))]
(or sp-exec
(if (= workload :core-async-dispatch)
(executor-for :io)
(@#'dispatch/create-default-executor workload)))))))
(alter-var-root #'dispatch/executor-for (constantly executor-for))
#_#_(defn exec
[^Runnable r workload]
(prn :r r :w workload)
(let [^ExecutorService e (executor-for workload)]
(.execute e r)))
(alter-var-root #'dispatch/exec (constantly exec))
(def ^java.util.concurrent.Executor virtual-executor (def ^java.util.concurrent.Executor virtual-executor
(try (eval '(java.util.concurrent.Executors/newVirtualThreadPerTaskExecutor)) (try (eval '(java.util.concurrent.Executors/newVirtualThreadPerTaskExecutor))
@ -43,25 +15,20 @@
(defn thread-call (defn thread-call
"Executes f in another thread, returning immediately to the calling "Executes f in another thread, returning immediately to the calling
thread. Returns a channel which will receive the result of calling thread. Returns a channel which will receive the result of calling
f when completed, then close. workload is a keyword that describes f when completed, then close."
the work performed by f, where: [f]
(let [c (async/chan 1)]
:io - may do blocking I/O but must not do extended computation (let [binds (vars/get-thread-binding-frame)]
:compute - must not ever block (.execute executor
:mixed - anything else (default) (fn []
(vars/reset-thread-binding-frame binds)
when workload not supplied, defaults to :mixed" (try
([f] (thread-call f :mixed)) (let [ret (f)]
([f workload] (when-not (nil? ret)
(let [c (async/chan 1) (async/>!! c ret)))
returning-to-chan (fn [bf] (finally
#(try (async/close! c))))))
(when-some [ret (bf)] c))
(async/>!! c ret))
(finally (async/close! c))))
f (vars/binding-conveyor-fn f)]
(-> f #_bound-fn* returning-to-chan (dispatch/exec workload))
c)))
(defn -vthread-call (defn -vthread-call
"Executes f in another virtual thread, returning immediately to the calling "Executes f in another virtual thread, returning immediately to the calling
@ -69,23 +36,21 @@
f when completed, then close." f when completed, then close."
[f] [f]
(let [c (async/chan 1)] (let [c (async/chan 1)]
(let [returning-to-chan (fn [bf] (let [binds (vars/get-thread-binding-frame)]
#(try
(when-some [ret (bf)]
(async/>!! c ret))
(finally (async/close! c))))
f (vars/binding-conveyor-fn f)]
(.execute virtual-executor (.execute virtual-executor
(-> f returning-to-chan))) (fn []
(vars/reset-thread-binding-frame binds)
(try
(let [ret (f)]
(when-not (nil? ret)
(async/>!! c ret)))
(finally
(async/close! c))))))
c)) c))
(defn thread (defn thread
[_ _ & body] [_ _ & body]
`(~'clojure.core.async/thread-call (fn [] ~@body) :mixed)) `(~'clojure.core.async/thread-call (fn [] ~@body)))
(defn io-thread
[_ _ & body]
`(~'clojure.core.async/thread-call (fn [] ~@body) :io))
(defn -vthread (defn -vthread
[_ _ & body] [_ _ & body]
@ -107,7 +72,7 @@
(if virtual-executor (if virtual-executor
(let [chan (async/chan nil)] (let [chan (async/chan nil)]
(.execute virtual-executor (fn [] (.execute virtual-executor (fn []
(Thread/sleep (long ms)) (Thread/sleep ms)
(async/close! chan))) (async/close! chan)))
chan) chan)
(async/timeout ms))) (async/timeout ms)))
@ -161,7 +126,6 @@
'take! (copy-var async/take! core-async-namespace) 'take! (copy-var async/take! core-async-namespace)
'tap (copy-var async/tap core-async-namespace) 'tap (copy-var async/tap core-async-namespace)
'thread (macrofy 'thread thread core-async-namespace) 'thread (macrofy 'thread thread core-async-namespace)
'io-thread (macrofy 'io-thread io-thread core-async-namespace)
'thread-call (copy-var thread-call core-async-namespace) 'thread-call (copy-var thread-call core-async-namespace)
'-vthread-call (copy-var -vthread-call core-async-namespace) '-vthread-call (copy-var -vthread-call core-async-namespace)
'timeout (copy-var timeout core-async-namespace) 'timeout (copy-var timeout core-async-namespace)
@ -193,4 +157,3 @@
(def async-protocols-namespace (def async-protocols-namespace
{:obj async-protocols-ns {:obj async-protocols-ns
'ReadPort (copy-var protocols/ReadPort async-protocols-ns)}) 'ReadPort (copy-var protocols/ReadPort async-protocols-ns)})
;; trigger CI

View file

@ -1,6 +0,0 @@
(ns babashka.impl.clojure.java.process
(:require [clojure.java.process]
[sci.core :as sci]))
(def cjp (sci/create-ns 'clojure.java.process nil))
(def cjp-namespace (sci/copy-ns clojure.java.process cjp))

View file

@ -55,13 +55,6 @@ by default when a new command-line REPL is started."} repl-requires
'[[clojure.repl :refer (source apropos pst dir doc find-doc)] '[[clojure.repl :refer (source apropos pst dir doc find-doc)]
[clojure.pprint :refer (pp pprint)]]) [clojure.pprint :refer (pp pprint)]])
(defmacro with-read-known
"Evaluates body with *read-eval* set to a \"known\" value,
i.e. substituting true for :unknown if necessary."
[& body]
`(binding [*read-eval* (if (= :unknown *read-eval*) true *read-eval*)]
~@body))
(defn repl (defn repl
"Generic, reusable, read-eval-print loop. By default, reads from *in*, "Generic, reusable, read-eval-print loop. By default, reads from *in*,
writes to *out*, and prints exception summaries to *err*. If you use the writes to *out*, and prints exception summaries to *err*. If you use the
@ -118,9 +111,8 @@ by default when a new command-line REPL is started."} repl-requires
:file "<repl>" :file "<repl>"
:type :sci/error) e))))))) :type :sci/error) e)))))))
(catch Throwable e (catch Throwable e
(let [e' (ex-cause e)] (caught e)
(caught e) (set! *e e))))]
(set! *e e')))))]
(with-bindings (with-bindings
(try (try
(init) (init)

View file

@ -1,7 +0,0 @@
(ns babashka.impl.clojure.reflect
(:require [clojure.reflect]
[sci.core :as sci]))
(def rns (sci/create-ns 'clojure.reflect))
(def reflect-namespace {'reflect (sci/copy-var clojure.reflect/reflect rns)})

View file

@ -660,12 +660,14 @@
;;; DEFINING FIXTURES ;;; DEFINING FIXTURES
(def ^:private ns->fixtures (atom {}))
(defn- add-ns-meta (defn- add-ns-meta
"Adds elements in coll to the current namespace metadata as the "Adds elements in coll to the current namespace metadata as the
value of key." value of key."
{:added "1.1"} {:added "1.1"}
[key coll] [key coll]
(alter-meta! @sci/ns assoc key coll)) (swap! ns->fixtures assoc-in [(sci-namespaces/sci-ns-name @sci/ns) key] coll))
(defmulti use-fixtures (defmulti use-fixtures
"Wrap test runs in a fixture function to perform setup and "Wrap test runs in a fixture function to perform setup and
@ -675,10 +677,10 @@
(fn [fixture-type & args] fixture-type)) (fn [fixture-type & args] fixture-type))
(defmethod use-fixtures :each [fixture-type & args] (defmethod use-fixtures :each [fixture-type & args]
(add-ns-meta :clojure.test/each-fixtures args)) (add-ns-meta ::each-fixtures args))
(defmethod use-fixtures :once [fixture-type & args] (defmethod use-fixtures :once [fixture-type & args]
(add-ns-meta :clojure.test/once-fixtures args)) (add-ns-meta ::once-fixtures args))
(defn- default-fixture (defn- default-fixture
"The default, empty, fixture function. Just calls its argument." "The default, empty, fixture function. Just calls its argument."
@ -729,8 +731,10 @@
[vars] [vars]
(doseq [[ns vars] (group-by (comp :ns meta) vars) (doseq [[ns vars] (group-by (comp :ns meta) vars)
:when ns] :when ns]
(let [once-fixture-fn (join-fixtures (:clojure.test/once-fixtures (meta ns))) (let [ns-name (sci-namespaces/sci-ns-name ns)
each-fixture-fn (join-fixtures (:clojure.test/each-fixtures (meta ns)))] fixtures (get @ns->fixtures ns-name)
once-fixture-fn (join-fixtures (::once-fixtures fixtures))
each-fixture-fn (join-fixtures (::each-fixtures fixtures))]
(once-fixture-fn (once-fixture-fn
(fn [] (fn []
(doseq [v vars] (doseq [v vars]

View file

@ -1,7 +1,6 @@
(ns babashka.impl.clojure.tools.reader (ns babashka.impl.clojure.tools.reader
(:refer-clojure :exclude [read read-string]) (:refer-clojure :exclude [read])
(:require (:require
[clojure.tools.reader.reader-types :as rt]
[edamame.core :as e] [edamame.core :as e]
[sci.core :as sci] [sci.core :as sci]
[sci.ctx-store :as ctx] [sci.ctx-store :as ctx]
@ -17,15 +16,6 @@
:location? seq? :location? seq?
:end-location false})) :end-location false}))
(def default-data-reader-fn (sci/new-dynamic-var '*default-data-reader-fn* nil {:ns rns}))
(def alias-map (sci/new-dynamic-var '*alias-map* nil {:ns rns}))
(defn resolve-tag [sym]
;; https://github.com/clojure/tools.reader/blob/ff18b1b872398a99e3e2941a0ed9abc0c2dec151/src/main/clojure/clojure/tools/reader.clj#L858
(or (default-data-readers sym)
(when-let [f @default-data-reader-fn]
(f sym))))
;; Added for compatibility with tools.namespace ;; Added for compatibility with tools.namespace
(defn read (defn read
"Reads the first object from an IPushbackReader or a java.io.PushbackReader. "Reads the first object from an IPushbackReader or a java.io.PushbackReader.
@ -49,17 +39,7 @@
([{eof :eof :as opts :or {eof :eofthrow}} reader] ([{eof :eof :as opts :or {eof :eofthrow}} reader]
(let [opts (assoc default-opts (let [opts (assoc default-opts
:read-cond (:read-cond opts) :read-cond (:read-cond opts)
:features (:features opts) :features (:features opts))
:readers (fn [sym]
(resolve-tag sym))
:auto-resolve (fn [alias]
(if (= :current alias)
(symbol (str @sci/ns))
(or (when-let [alias-map @alias-map]
(@alias-map alias))
(sci/eval-form (ctx/get-ctx)
(list 'get '(ns-aliases *ns*)
(list 'quote alias)))))))
v (e/parse-next reader opts)] v (e/parse-next reader opts)]
(if (identical? ::e/eof v) (if (identical? ::e/eof v)
(if (identical? :eofthrow eof) (if (identical? :eofthrow eof)
@ -74,18 +54,8 @@
sentinel) sentinel)
v)))) v))))
(defn read-string
([s] (read-string nil s))
([opts s]
(when (and s (not (identical? s "")))
(read opts (rt/string-push-back-reader s)))))
(defn resolve-symbol [sym] (defn resolve-symbol [sym]
(p/fully-qualify (ctx/get-ctx) sym)) (p/fully-qualify (ctx/get-ctx) sym))
(def reader-namespace (def reader-namespace {'read (sci/copy-var read rns)
{'read (sci/copy-var read rns) 'resolve-symbol (sci/copy-var resolve-symbol rns)})
'read-string (sci/copy-var read-string rns)
'resolve-symbol (sci/copy-var resolve-symbol rns)
'*default-data-reader-fn* default-data-reader-fn
'*alias-map* alias-map})

View file

@ -3,10 +3,7 @@
[clojure.tools.reader.reader-types :as rt] [clojure.tools.reader.reader-types :as rt]
[sci.core :as sci])) [sci.core :as sci]))
(def tr-edn-ns (sci/create-ns 'clojure.tools.reader.edn)) (def edn-namespace {'read-string (sci/copy-var edn/read-string (sci/create-ns 'clojure.tools.reader.edn))})
(def edn-namespace {'read-string (sci/copy-var edn/read-string tr-edn-ns)
'read (sci/copy-var edn/read tr-edn-ns)})
(def rtns (sci/create-ns 'clojure.tools.reader.reader-types)) (def rtns (sci/create-ns 'clojure.tools.reader.reader-types))
@ -17,5 +14,4 @@
'read-char (sci/copy-var rt/read-char rtns) 'read-char (sci/copy-var rt/read-char rtns)
'unread (sci/copy-var rt/unread rtns) 'unread (sci/copy-var rt/unread rtns)
'source-logging-push-back-reader (sci/copy-var rt/source-logging-push-back-reader rtns) 'source-logging-push-back-reader (sci/copy-var rt/source-logging-push-back-reader rtns)
'source-logging-reader? (sci/copy-var rt/source-logging-reader? rtns) 'source-logging-reader? (sci/copy-var rt/source-logging-reader? rtns)})
'string-push-back-reader (sci/copy-var rt/string-push-back-reader rtns)})

View file

@ -76,14 +76,7 @@
;; paths are added manually above ;; paths are added manually above
;; extra-paths are added as :paths in tasks ;; extra-paths are added as :paths in tasks
:paths :tasks :raw :file :deps-root :paths :tasks :raw :file :deps-root
:min-bb-version) :min-bb-version)]
;; associate deps-root to avoid cache conflict between different
;; bb.edns with relative local/roots by the same name NOTE:
;; deps-root is nil when bb.edn isn't used, so clashes may still
;; happen with dynamic add-deps, but at least we don't invoke
;; clojure CLI's java process each time we call a script from a
;; different directory.
deps-map (assoc deps-map :deps-root (str deps-root))]
(binding [*print-namespace-maps* false] (binding [*print-namespace-maps* false]
(let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults] (let [deps-map (assoc-in deps-map [:aliases :org.babashka/defaults]
{:replace-paths [] ;; babashka sets paths manually {:replace-paths [] ;; babashka sets paths manually

View file

@ -1,13 +1,11 @@
(ns babashka.impl.http-client (ns babashka.impl.http-client
(:require (:require
[babashka.http-client] [babashka.http-client]
[babashka.http-client.interceptors]
[babashka.http-client.websocket] [babashka.http-client.websocket]
[sci.core :as sci])) [sci.core :as sci]))
(def hns (sci/create-ns 'babashka.http-client)) (def hns (sci/create-ns 'babashka.http-client))
(def wns (sci/create-ns 'babashka.http-client.websocket)) (def wns (sci/create-ns 'babashka.http-client.websocket))
(def ins (sci/create-ns 'babashka.http-client.interceptors))
(def http-client-namespace (def http-client-namespace
(sci/copy-ns babashka.http-client hns)) (sci/copy-ns babashka.http-client hns))
@ -15,5 +13,3 @@
(def http-client-websocket-namespace (def http-client-websocket-namespace
(sci/copy-ns babashka.http-client.websocket wns)) (sci/copy-ns babashka.http-client.websocket wns))
(def http-client-interceptors-namespace
(sci/copy-ns babashka.http-client.interceptors ins))

View file

@ -1,18 +1,11 @@
(ns babashka.impl.nrepl-server (ns babashka.impl.nrepl-server
{:no-doc true} {:no-doc true}
(:require (:require
[babashka.impl.classpath :as cp]
[babashka.impl.clojure.core :as core-extras] [babashka.impl.clojure.core :as core-extras]
[babashka.impl.common :as common] [babashka.impl.common :as common]
[babashka.nrepl.impl.server :refer [process-msg]]
[babashka.nrepl.server :as server] [babashka.nrepl.server :as server]
[sci.core :as sci])) [sci.core :as sci]))
(defmethod process-msg :classpath [rf result m]
(rf result {:response {"status" ["done"]
"classpath" (cp/split-classpath (cp/get-classpath))}
:response-for (:msg m)}))
(defn start-server! (defn start-server!
([] ([]
(start-server! nil)) (start-server! nil))

View file

@ -2,8 +2,7 @@
{:no-doc true} {:no-doc true}
(:require [clojure.pprint :as pprint] (:require [clojure.pprint :as pprint]
[sci.core :as sci] [sci.core :as sci]
[sci.pprint] [sci.pprint]))
[babashka.impl.clojure.core.async]))
(defonce patched? (volatile! false)) (defonce patched? (volatile! false))

View file

@ -14,11 +14,11 @@
edn/read-string) edn/read-string)
deps (:deps deps) deps (:deps deps)
deps (assoc deps deps (assoc deps
'babashka/fs {:mvn/version "0.5.25"} 'babashka/fs {:mvn/version "0.4.19"}
'babashka/babashka.curl {:mvn/version "0.1.2"} 'babashka/babashka.curl {:mvn/version "0.1.2"}
'babashka/babashka.core {:git/url "https://github.com/babashka/babashka.core" 'babashka/babashka.core {:git/url "https://github.com/babashka/babashka.core"
:git/sha "52a6037bd4b632bffffb04394fb4efd0cdab6b1e"} :git/sha "52a6037bd4b632bffffb04394fb4efd0cdab6b1e"}
'babashka/process {:mvn/version "0.6.23"}) 'babashka/process {:mvn/version "0.5.21"})
deps (dissoc deps deps (dissoc deps
'borkdude/sci 'borkdude/sci
'org.babashka/sci 'org.babashka/sci

View file

@ -28,10 +28,6 @@
(binding [process/*defaults* @defaults] (binding [process/*defaults* @defaults]
(apply process/shell args))) (apply process/shell args)))
(defn exec [& args]
(binding [process/*defaults* @defaults]
(apply process/exec args)))
(def process-namespace (def process-namespace
{'parse-args (copy-var process/parse-args tns) {'parse-args (copy-var process/parse-args tns)
'process* (copy-var process/process* tns) 'process* (copy-var process/process* tns)
@ -46,6 +42,6 @@
'*defaults* defaults '*defaults* defaults
'destroy (copy-var process/destroy tns) 'destroy (copy-var process/destroy tns)
'destroy-tree (copy-var process/destroy-tree tns) 'destroy-tree (copy-var process/destroy-tree tns)
'exec (copy-var exec tns) 'exec (copy-var process/exec tns)
'shell (copy-var shell tns) 'shell (copy-var shell tns)
'alive? (copy-var process/alive? tns)}) 'alive? (copy-var process/alive? tns)})

View file

@ -79,18 +79,6 @@
(handle [sig] (handle [sig]
((method-or-bust methods 'handle) this sig))) ((method-or-bust methods 'handle) this sig)))
["java.io.InputStream" #{}]
(proxy [java.io.InputStream] []
(available [] ((method-or-bust methods 'available) this))
(close [] ((method-or-bust methods 'close) this))
(read
([]
((method-or-bust methods 'read) this))
([bs]
((method-or-bust methods 'read) this bs))
([bs off len]
((method-or-bust methods 'read) this bs off len))))
["java.io.PipedInputStream" #{}] ["java.io.PipedInputStream" #{}]
(proxy [java.io.PipedInputStream] [] (proxy [java.io.PipedInputStream] []
(available [] ((method-or-bust methods 'available) this)) (available [] ((method-or-bust methods 'available) this))
@ -137,11 +125,6 @@
([x y z] ([x y z]
((method-or-bust methods 'checkServerTrusted) this x y z))) ((method-or-bust methods 'checkServerTrusted) this x y z)))
(getAcceptedIssuers [] ((method-or-bust methods 'getAcceptedIssuers) this))) (getAcceptedIssuers [] ((method-or-bust methods 'getAcceptedIssuers) this)))
["java.lang.ThreadLocal" #{}]
(proxy [java.lang.ThreadLocal] []
(initialValue []
((method-or-bust methods 'initialValue) this)))
, ;; keep this for merge friendliness , ;; keep this for merge friendliness
))) )))
@ -154,9 +137,7 @@
{:methods [{:name "connectFailed"} {:methods [{:name "connectFailed"}
{:name "select"}]} {:name "select"}]}
(class-sym (class (proxy-fn {:class javax.net.ssl.HostnameVerifier}))) (class-sym (class (proxy-fn {:class javax.net.ssl.HostnameVerifier})))
{:methods [{:name "verify"}]} {:methods [{:name "verify"}]}})
(class-sym (class (proxy-fn {:class java.lang.ThreadLocal})))
{:methods [{:name "get"}]}})
;;; Scratch ;;; Scratch

View file

@ -187,4 +187,5 @@
sun.misc.SignalHandler sun.misc.SignalHandler
{handle [[this signal]]} {handle [[this signal]]}
})) }))

View file

@ -43,19 +43,9 @@
"Inspired by skip-if-eol from clojure.main." "Inspired by skip-if-eol from clojure.main."
[s] [s]
(let [c (r/read-char s)] (let [c (r/read-char s)]
(when-not (= \newline c ) (when-not (= c \newline)
(r/unread s c)))) (r/unread s c))))
(defn repl-read [sci-ctx in-stream _request-prompt request-exit]
(if (nil? (r/peek-char in-stream))
request-exit
(let [v (parser/parse-next sci-ctx in-stream)]
(skip-if-eol in-stream)
(if (or (identical? :repl/quit v)
(identical? :repl/exit v))
request-exit
v))))
(defn repl (defn repl
"REPL with predefined hooks for attachable socket server." "REPL with predefined hooks for attachable socket server."
([sci-ctx] (repl sci-ctx nil)) ([sci-ctx] (repl sci-ctx nil))
@ -78,8 +68,15 @@
(sio/println)) (sio/println))
(eval-form sci-ctx `(apply require (quote ~m/repl-requires))))) (eval-form sci-ctx `(apply require (quote ~m/repl-requires)))))
:read (or read :read (or read
(fn [request-prompt request-exit] (fn [_request-prompt request-exit]
(repl-read sci-ctx in request-prompt request-exit))) (if (nil? (r/peek-char in))
request-exit
(let [v (parser/parse-next sci-ctx in)]
(skip-if-eol in)
(if (or (identical? :repl/quit v)
(identical? :repl/exit v))
request-exit
v)))))
:eval (or eval :eval (or eval
(fn [expr] (fn [expr]
(sci/with-bindings {sci/file "<repl>" (sci/with-bindings {sci/file "<repl>"

View file

@ -1,7 +1,6 @@
(ns babashka.impl.server (ns babashka.impl.server
(:require [babashka.impl.clojure.core.server :as server] (:require [babashka.impl.clojure.core.server :as server]
[babashka.impl.common :as common] [babashka.impl.common :as common]
[babashka.impl.repl :as repl]
[babashka.impl.socket-repl :as socket-repl] [babashka.impl.socket-repl :as socket-repl]
[sci.core :as sci])) [sci.core :as sci]))
@ -18,14 +17,9 @@
(fn [& args] (fn [& args]
(apply server/start-server (common/ctx) args))) (apply server/start-server (common/ctx) args)))
(def repl-read
(fn [& args]
(apply repl/repl-read (common/ctx) @sci/in args)))
(def clojure-core-server-namespace (def clojure-core-server-namespace
{'repl (sci/copy-var socket-repl/repl sns) {'repl (sci/copy-var socket-repl/repl sns)
'prepl (sci/copy-var prepl sns) 'prepl (sci/copy-var prepl sns)
'io-prepl (sci/copy-var io-prepl sns) 'io-prepl (sci/copy-var io-prepl sns)
'start-server (sci/copy-var start-server sns) 'start-server (sci/copy-var start-server sns)
'stop-server (sci/copy-var server/stop-server sns) 'stop-server (sci/copy-var server/stop-server sns)})
'repl-read (sci/copy-var repl-read sns)})

View file

@ -6,7 +6,7 @@
[babashka.deps :as bdeps] [babashka.deps :as bdeps]
[babashka.fs :as fs] [babashka.fs :as fs]
[babashka.impl.bencode :refer [bencode-namespace]] [babashka.impl.bencode :refer [bencode-namespace]]
[babashka.impl.cheshire :refer [cheshire-core-namespace cheshire-factory-namespace]] [babashka.impl.cheshire :refer [cheshire-core-namespace]]
[babashka.impl.classes :as classes :refer [classes-namespace]] [babashka.impl.classes :as classes :refer [classes-namespace]]
[babashka.impl.classpath :as cp :refer [classpath-namespace]] [babashka.impl.classpath :as cp :refer [classpath-namespace]]
[babashka.impl.cli :as cli] [babashka.impl.cli :as cli]
@ -16,11 +16,9 @@
[babashka.impl.clojure.instant :as instant] [babashka.impl.clojure.instant :as instant]
[babashka.impl.clojure.java.browse :refer [browse-namespace]] [babashka.impl.clojure.java.browse :refer [browse-namespace]]
[babashka.impl.clojure.java.io :refer [io-namespace]] [babashka.impl.clojure.java.io :refer [io-namespace]]
[babashka.impl.clojure.java.process :refer [cjp-namespace]]
[babashka.impl.clojure.java.shell :refer [shell-namespace]] [babashka.impl.clojure.java.shell :refer [shell-namespace]]
[babashka.impl.clojure.main :as clojure-main :refer [demunge]] [babashka.impl.clojure.main :as clojure-main :refer [demunge]]
[babashka.impl.clojure.math :refer [math-namespace]] [babashka.impl.clojure.math :refer [math-namespace]]
[babashka.impl.clojure.reflect :refer [reflect-namespace]]
[babashka.impl.clojure.stacktrace :refer [stacktrace-namespace]] [babashka.impl.clojure.stacktrace :refer [stacktrace-namespace]]
[babashka.impl.clojure.tools.reader :refer [reader-namespace]] [babashka.impl.clojure.tools.reader :refer [reader-namespace]]
[babashka.impl.clojure.tools.reader-types :refer [edn-namespace [babashka.impl.clojure.tools.reader-types :refer [edn-namespace
@ -36,9 +34,7 @@
[babashka.impl.error-handler :refer [error-handler]] [babashka.impl.error-handler :refer [error-handler]]
[babashka.impl.features :as features] [babashka.impl.features :as features]
[babashka.impl.fs :refer [fs-namespace]] [babashka.impl.fs :refer [fs-namespace]]
[babashka.impl.http-client :refer [http-client-namespace [babashka.impl.http-client :refer [http-client-namespace http-client-websocket-namespace]]
http-client-websocket-namespace
http-client-interceptors-namespace]]
[babashka.impl.nrepl-server :refer [nrepl-server-namespace]] [babashka.impl.nrepl-server :refer [nrepl-server-namespace]]
[babashka.impl.pods :as pods] [babashka.impl.pods :as pods]
[babashka.impl.pprint :refer [pprint-namespace]] [babashka.impl.pprint :refer [pprint-namespace]]
@ -110,8 +106,6 @@
(def version common/version) (def version common/version)
(def build-commit-sha (or (System/getenv "BABASHKA_SHA") ""))
(defn parse-version [version] (defn parse-version [version]
(mapv #(Integer/parseInt %) (mapv #(Integer/parseInt %)
(-> version (-> version
@ -144,7 +138,7 @@
(binding [*out* *err*] (binding [*out* *err*]
(apply println msgs))) (apply println msgs)))
(defn print-help [] (defn print-help [_ctx _command-line-args]
(println (str "Babashka v" version)) (println (str "Babashka v" version))
(println " (println "
Usage: bb [svm-opts] [global-opts] [eval opts] [cmdline args] Usage: bb [svm-opts] [global-opts] [eval opts] [cmdline args]
@ -220,7 +214,8 @@ Tooling:
File names take precedence over subcommand names. File names take precedence over subcommand names.
Remaining arguments are bound to *command-line-args*. Remaining arguments are bound to *command-line-args*.
Use -- to separate script command line args from bb command line args. Use -- to separate script command line args from bb command line args.
When no eval opts or subcommand is provided, the implicit subcommand is repl.")) When no eval opts or subcommand is provided, the implicit subcommand is repl.")
[nil 0])
(defn print-doc [ctx command-line-args] (defn print-doc [ctx command-line-args]
(let [arg (first command-line-args) (let [arg (first command-line-args)
@ -263,7 +258,6 @@ Use bb run --help to show this help output.
(format (format
(str/trim " (str/trim "
{:babashka/version \"%s\" {:babashka/version \"%s\"
:git/sha \"%s\"
:feature/csv %s :feature/csv %s
:feature/java-nio %s :feature/java-nio %s
:feature/java-time %s :feature/java-time %s
@ -284,7 +278,6 @@ Use bb run --help to show this help output.
:feature/logging %s :feature/logging %s
:feature/priority-map %s}") :feature/priority-map %s}")
version version
build-commit-sha
features/csv? features/csv?
features/java-nio? features/java-nio?
features/java-time? features/java-time?
@ -333,20 +326,20 @@ Use bb run --help to show this help output.
(def aliases (def aliases
(cond-> (cond->
'{str clojure.string '{str clojure.string
set clojure.set set clojure.set
tools.cli clojure.tools.cli tools.cli clojure.tools.cli
edn clojure.edn edn clojure.edn
wait babashka.wait wait babashka.wait
signal babashka.signal signal babashka.signal
shell clojure.java.shell shell clojure.java.shell
io clojure.java.io io clojure.java.io
json cheshire.core json cheshire.core
curl babashka.curl curl babashka.curl
fs babashka.fs fs babashka.fs
bencode bencode.core bencode bencode.core
deps babashka.deps deps babashka.deps
async clojure.core.async} async clojure.core.async}
features/xml? (assoc 'xml 'clojure.data.xml) features/xml? (assoc 'xml 'clojure.data.xml)
features/yaml? (assoc 'yaml 'clj-yaml.core) features/yaml? (assoc 'yaml 'clj-yaml.core)
features/jdbc? (assoc 'jdbc 'next.jdbc) features/jdbc? (assoc 'jdbc 'next.jdbc)
@ -366,79 +359,73 @@ Use bb run --help to show this help output.
(def namespaces (def namespaces
(cond-> (cond->
{'user {'*input* (reify {'user {'*input* (reify
sci-types/Eval sci-types/Eval
(eval [_ _ctx _bindings] (eval [_ _ctx _bindings]
(force @input-var)))} (force @input-var)))}
'clojure.core core-extras 'clojure.core core-extras
'clojure.tools.cli tools-cli-namespace 'clojure.tools.cli tools-cli-namespace
'clojure.java.shell shell-namespace 'clojure.java.shell shell-namespace
'babashka.core bbcore/core-namespace 'babashka.core bbcore/core-namespace
'babashka.nrepl.server nrepl-server-namespace 'babashka.nrepl.server nrepl-server-namespace
'babashka.wait wait-namespace 'babashka.wait wait-namespace
'babashka.signal signal-ns 'babashka.signal signal-ns
'clojure.java.io io-namespace 'clojure.java.io io-namespace
'cheshire.core cheshire-core-namespace 'cheshire.core cheshire-core-namespace
'cheshire.factory cheshire-factory-namespace 'clojure.data data/data-namespace
'clojure.data data/data-namespace 'clojure.instant instant/instant-namespace
'clojure.instant instant/instant-namespace 'clojure.stacktrace stacktrace-namespace
'clojure.stacktrace stacktrace-namespace 'clojure.zip zip-namespace
'clojure.zip zip-namespace 'clojure.main {:obj clojure-main-ns
'clojure.main {:obj clojure-main-ns 'demunge (sci/copy-var demunge clojure-main-ns)
'demunge (sci/copy-var demunge clojure-main-ns) 'repl-requires (sci/copy-var clojure-main/repl-requires clojure-main-ns)
'repl-requires (sci/copy-var clojure-main/repl-requires clojure-main-ns) 'repl (sci/new-var 'repl
'repl (sci/new-var 'repl (fn [& opts]
(fn [& opts] (let [opts (apply hash-map opts)]
(let [opts (apply hash-map opts)] (repl/start-repl! (common/ctx) opts))) {:ns clojure-main-ns})
(repl/start-repl! (common/ctx) opts))) {:ns clojure-main-ns}) 'with-bindings (sci/copy-var clojure-main/with-bindings clojure-main-ns)
'with-bindings (sci/copy-var clojure-main/with-bindings clojure-main-ns) 'repl-caught (sci/copy-var repl/repl-caught clojure-main-ns)
'repl-caught (sci/copy-var repl/repl-caught clojure-main-ns) 'main main-var}
'with-read-known (sci/copy-var clojure-main/with-read-known clojure-main-ns) 'clojure.test t/clojure-test-namespace
'main main-var} 'clojure.math math-namespace
'clojure.test t/clojure-test-namespace 'babashka.classpath classpath-namespace
'clojure.math math-namespace 'babashka.classes classes-namespace
'clojure.java.process cjp-namespace 'clojure.pprint pprint-namespace
'babashka.classpath classpath-namespace 'babashka.curl curl-namespace
'babashka.classes classes-namespace 'babashka.fs fs-namespace
'clojure.pprint pprint-namespace 'babashka.pods pods/pods-namespace
'babashka.curl curl-namespace 'bencode.core bencode-namespace
'babashka.fs fs-namespace 'clojure.java.browse browse-namespace
'babashka.pods pods/pods-namespace 'clojure.datafy datafy-namespace
'bencode.core bencode-namespace 'clojure.core.protocols protocols-namespace
'clojure.java.browse browse-namespace 'babashka.process process-namespace
'clojure.datafy datafy-namespace 'clojure.core.server clojure-core-server-namespace
'clojure.core.protocols protocols-namespace 'babashka.deps deps-namespace
'babashka.process process-namespace 'babashka.tasks tasks-namespace
'clojure.core.server clojure-core-server-namespace 'clojure.tools.reader.edn edn-namespace
'babashka.deps deps-namespace 'clojure.tools.reader.reader-types reader-types-namespace
'babashka.tasks tasks-namespace 'clojure.tools.reader reader-namespace
'clojure.tools.reader.edn edn-namespace 'clojure.core.async async-namespace
'clojure.tools.reader.reader-types reader-types-namespace 'clojure.core.async.impl.protocols async-protocols-namespace
'clojure.tools.reader reader-namespace 'rewrite-clj.node rewrite/node-namespace
'clojure.core.async async-namespace 'rewrite-clj.paredit rewrite/paredit-namespace
'clojure.core.async.impl.protocols async-protocols-namespace 'rewrite-clj.parser rewrite/parser-namespace
'clojure.reflect reflect-namespace 'rewrite-clj.zip rewrite/zip-namespace
'rewrite-clj.node rewrite/node-namespace 'rewrite-clj.zip.subedit rewrite/subedit-namespace
'rewrite-clj.paredit rewrite/paredit-namespace 'clojure.core.rrb-vector (if features/rrb-vector?
'rewrite-clj.parser rewrite/parser-namespace @(resolve 'babashka.impl.rrb-vector/rrb-vector-namespace)
'rewrite-clj.zip rewrite/zip-namespace {'catvec (sci/copy-var catvec
'rewrite-clj.zip.subedit rewrite/subedit-namespace (sci/create-ns 'clojure.core.rrb-vector))})
'clojure.core.rrb-vector (if features/rrb-vector? 'edamame.core edamame-namespace
@(resolve 'babashka.impl.rrb-vector/rrb-vector-namespace) 'sci.core sci-core-namespace
{'catvec (sci/copy-var catvec 'babashka.cli cli/cli-namespace
(sci/create-ns 'clojure.core.rrb-vector))}) 'babashka.http-client http-client-namespace
'edamame.core edamame-namespace 'babashka.http-client.websocket http-client-websocket-namespace}
'sci.core sci-core-namespace
'babashka.cli cli/cli-namespace
'babashka.http-client http-client-namespace
'babashka.http-client.websocket http-client-websocket-namespace
'babashka.http-client.interceptors http-client-interceptors-namespace}
features/xml? (assoc 'clojure.data.xml @(resolve 'babashka.impl.xml/xml-namespace) features/xml? (assoc 'clojure.data.xml @(resolve 'babashka.impl.xml/xml-namespace)
'clojure.data.xml.event @(resolve 'babashka.impl.xml/xml-event-namespace) 'clojure.data.xml.event @(resolve 'babashka.impl.xml/xml-event-namespace)
'clojure.data.xml.tree @(resolve 'babashka.impl.xml/xml-tree-namespace)) 'clojure.data.xml.tree @(resolve 'babashka.impl.xml/xml-tree-namespace))
features/yaml? (assoc 'clj-yaml.core @(resolve 'babashka.impl.yaml/yaml-namespace) features/yaml? (assoc 'clj-yaml.core @(resolve 'babashka.impl.yaml/yaml-namespace)
'flatland.ordered.map @(resolve 'babashka.impl.ordered/ordered-map-ns) 'flatland.ordered.map @(resolve 'babashka.impl.ordered/ordered-map-ns))
'flatland.ordered.set @(resolve 'babashka.impl.ordered/ordered-set-ns))
features/jdbc? (assoc 'next.jdbc @(resolve 'babashka.impl.jdbc/njdbc-namespace) features/jdbc? (assoc 'next.jdbc @(resolve 'babashka.impl.jdbc/njdbc-namespace)
'next.jdbc.sql @(resolve 'babashka.impl.jdbc/next-sql-namespace) 'next.jdbc.sql @(resolve 'babashka.impl.jdbc/next-sql-namespace)
'next.jdbc.result-set @(resolve 'babashka.impl.jdbc/result-set-namespace)) 'next.jdbc.result-set @(resolve 'babashka.impl.jdbc/result-set-namespace))
@ -470,7 +457,7 @@ Use bb run --help to show this help output.
@(resolve 'babashka.impl.clojure.test.check/test-check-namespace) @(resolve 'babashka.impl.clojure.test.check/test-check-namespace)
;; it's better to load this from source by adding the clojure.test.check dependency ;; it's better to load this from source by adding the clojure.test.check dependency
#_#_'clojure.test.check.clojure-test #_#_'clojure.test.check.clojure-test
@(resolve 'babashka.impl.clojure.test.check/test-check-clojure-test-namespace)) @(resolve 'babashka.impl.clojure.test.check/test-check-clojure-test-namespace))
features/spec-alpha? (-> (assoc ;; spec features/spec-alpha? (-> (assoc ;; spec
'clojure.spec.alpha @(resolve 'babashka.impl.spec/spec-namespace) 'clojure.spec.alpha @(resolve 'babashka.impl.spec/spec-namespace)
'clojure.spec.gen.alpha @(resolve 'babashka.impl.spec/gen-namespace) 'clojure.spec.gen.alpha @(resolve 'babashka.impl.spec/gen-namespace)
@ -486,8 +473,6 @@ Use bb run --help to show this help output.
'selmer.validator 'selmer.validator
@(resolve 'babashka.impl.selmer/selmer-validator-namespace)) @(resolve 'babashka.impl.selmer/selmer-validator-namespace))
features/logging? (assoc 'taoensso.timbre @(resolve 'babashka.impl.logging/timbre-namespace) features/logging? (assoc 'taoensso.timbre @(resolve 'babashka.impl.logging/timbre-namespace)
'taoensso.timbre.appenders.core @(resolve 'babashka.impl.logging/timbre-appenders-namespace)
'taoensso.encore @(resolve 'babashka.impl.logging/encore-namespace)
'clojure.tools.logging 'clojure.tools.logging
@(resolve 'babashka.impl.logging/tools-logging-namespace) @(resolve 'babashka.impl.logging/tools-logging-namespace)
'clojure.tools.logging.impl 'clojure.tools.logging.impl
@ -499,8 +484,7 @@ Use bb run --help to show this help output.
(def edn-readers (cond-> {} (def edn-readers (cond-> {}
features/yaml? features/yaml?
(assoc 'ordered/map @(resolve 'flatland.ordered.map/ordered-map) (assoc 'ordered/map @(resolve 'flatland.ordered.map/ordered-map))
'ordered/set @(resolve 'flatland.ordered.set/ordered-set))
features/xml? features/xml?
(assoc 'xml/ns @(resolve 'clojure.data.xml.name/uri-symbol) (assoc 'xml/ns @(resolve 'clojure.data.xml.name/uri-symbol)
'xml/element @(resolve 'clojure.data.xml.node/tagged-element)))) 'xml/element @(resolve 'clojure.data.xml.node/tagged-element))))
@ -624,7 +608,7 @@ Use bb run --help to show this help output.
:uberjar (first options)))) :uberjar (first options))))
("--repl") ("--repl")
(let [options (next options)] (let [options (next options)]
(recur options (recur (next options)
(assoc opts-map (assoc opts-map
:repl true))) :repl true)))
("--socket-repl") ("--socket-repl")
@ -733,37 +717,32 @@ Use bb run --help to show this help output.
(defn parse-file-opt (defn parse-file-opt
[options opts-map] [options opts-map]
(let [opt (first options)] (let [opt (first options)]
(if (and opt (and (fs/exists? opt) (if (and opt (fs/exists? opt))
(not (fs/directory? opt)))) (let [opts (assoc opts-map
[nil (assoc opts-map (if (str/ends-with? opt ".jar")
(if (str/ends-with? opt ".jar") :jar :file) opt
:jar :file) opt :command-line-args (next options))]
:command-line-args (next options))] opts)
[options opts-map]))) opts-map)))
(defn parse-opts (defn parse-opts
([options] (parse-opts options nil)) ([options] (parse-opts options nil))
([options opts-map] ([options opts-map]
(let [opt (first options) (let [opt (first options)
task-map (:tasks @common/bb-edn) tasks (into #{} (map str) (keys (:tasks @common/bb-edn)))]
tasks (into #{} (map str) (keys task-map))]
(when-let [commands (seq (filter (fn [task]
(and (command? task)
(not (:override-builtin (get task-map (symbol task))))))
tasks))]
(binding [*out* *err*]
(println "[babashka] WARNING: task(s)" (str/join ", " (map #(format "'%s'" %) commands)) "override built-in command(s). Use :override-builtin true to disable warning.")))
(if-not opt opts-map (if-not opt opts-map
;; FILE > TASK > SUBCOMMAND ;; FILE > TASK > SUBCOMMAND
(cond (cond
(and (not (or (:file opts-map) (.isFile (io/file opt))
(:jar opts-map))) (if (or (:file opts-map) (:jar opts-map))
(.isFile (io/file opt))) opts-map ; we've already parsed the file opt
(parse-file-opt options opts-map) (parse-file-opt options opts-map))
(contains? tasks opt) (contains? tasks opt)
(assoc opts-map (assoc opts-map
:run opt :run opt
:command-line-args (next options)) :command-line-args (next options))
(command? opt) (command? opt)
(recur (cons (str "--" opt) (next options)) opts-map) (recur (cons (str "--" opt) (next options)) opts-map)
@ -843,12 +822,13 @@ Use bb run --help to show this help output.
sci/print-length @sci/print-length sci/print-length @sci/print-length
;; when adding vars here, also add them to repl.clj and nrepl_server.clj ;; when adding vars here, also add them to repl.clj and nrepl_server.clj
] ]
(let [{:keys [:shell-in :edn-in :shell-out :edn-out (let [{version-opt :version
:file :command-line-args :keys [:shell-in :edn-in :shell-out :edn-out
:help :file :command-line-args
:expressions :stream? :init :expressions :stream? :init
:repl :socket-repl :nrepl :repl :socket-repl :nrepl
:debug :classpath :force? :debug :classpath :force?
:main :uberscript :main :uberscript :describe?
:jar :uberjar :clojure :jar :uberjar :clojure
:doc :run :list-tasks :doc :run :list-tasks
:print-deps :prepare] :print-deps :prepare]
@ -893,10 +873,10 @@ Use bb run --help to show this help output.
(let [loader @cp/the-url-loader] (let [loader @cp/the-url-loader]
(or (or
(when ;; ignore built-in namespaces when uberscripting, unless with :reload (when ;; ignore built-in namespaces when uberscripting, unless with :reload
(and uberscript (and uberscript
(not reload) (not reload)
(or (contains? namespaces namespace) (or (contains? namespaces namespace)
(contains? sci-namespaces/namespaces namespace))) (contains? sci-namespaces/namespaces namespace)))
"") "")
;; pod namespaces go before namespaces from source, ;; pod namespaces go before namespaces from source,
;; unless reload is used ;; unless reload is used
@ -922,7 +902,7 @@ Use bb run --help to show this help output.
res))) res)))
(let [rps (cp/resource-paths namespace) (let [rps (cp/resource-paths namespace)
rps (mapv #(str "src/babashka/" %) rps)] rps (mapv #(str "src/babashka/" %) rps)]
(when-let [url (some io/resource rps)] (when-let [url (some #(io/resource %) rps)]
(let [source (slurp url)] (let [source (slurp url)]
{:file (str url) {:file (str url)
:source source}))) :source source})))
@ -1025,9 +1005,13 @@ Use bb run --help to show this help output.
exit-code exit-code
(or exit-code (or exit-code
(second (second
(cond doc (print-doc sci-ctx command-line-args) (cond version-opt
repl (sci/binding [core/command-line-args command-line-args] [(print-version) 0]
[(repl/start-repl! sci-ctx) 0]) help (print-help sci-ctx command-line-args)
doc (print-doc sci-ctx command-line-args)
describe?
[(print-describe) 0]
repl [(repl/start-repl! sci-ctx) 0]
nrepl [(start-nrepl! nrepl) 0] nrepl [(start-nrepl! nrepl) 0]
uberjar [nil 0] uberjar [nil 0]
list-tasks [(tasks/list-tasks sci-ctx) 0] list-tasks [(tasks/list-tasks sci-ctx) 0]
@ -1075,8 +1059,7 @@ Use bb run --help to show this help output.
clojure [nil (if-let [proc (bdeps/clojure command-line-args)] clojure [nil (if-let [proc (bdeps/clojure command-line-args)]
(-> @proc :exit) (-> @proc :exit)
0)] 0)]
:else (sci/binding [core/command-line-args command-line-args] :else [(repl/start-repl! sci-ctx) 0]))
[(repl/start-repl! sci-ctx) 0])))
1)] 1)]
(flush) (flush)
(when uberscript (when uberscript
@ -1114,15 +1097,6 @@ Use bb run --help to show this help output.
(uberjar/run uber-params)))))) (uberjar/run uber-params))))))
exit-code)))) exit-code))))
(defn exec-without-deps [cli-opts]
(let [{version-opt :version
:keys [help describe?]} cli-opts]
(cond
version-opt (print-version)
help (print-help)
describe? (print-describe)))
0)
(defn satisfies-min-version? [min-version] (defn satisfies-min-version? [min-version]
(let [[major-current minor-current patch-current] version-data (let [[major-current minor-current patch-current] version-data
[major-min minor-min patch-min] (parse-version min-version)] [major-min minor-min patch-min] (parse-version min-version)]
@ -1133,7 +1107,7 @@ Use bb run --help to show this help output.
(>= patch-current patch-min))))))) (>= patch-current patch-min)))))))
(defn read-bb-edn [string] (defn read-bb-edn [string]
(try (edn/read-string {:default tagged-literal :eof nil} string) (try (edn/read-string {:default tagged-literal} string)
(catch java.lang.RuntimeException e (catch java.lang.RuntimeException e
(if (re-find #"No dispatch macro for: \"" (.getMessage e)) (if (re-find #"No dispatch macro for: \"" (.getMessage e))
(throw (ex-info "Invalid regex literal found in EDN config, use re-pattern instead" {})) (throw (ex-info "Invalid regex literal found in EDN config, use re-pattern instead" {}))
@ -1141,60 +1115,20 @@ Use bb run --help to show this help output.
(println "Error during loading bb.edn:")) (println "Error during loading bb.edn:"))
(throw e)))))) (throw e))))))
(defn binary-invoked-as-jar []
(and (= "executable" (System/getProperty "org.graalvm.nativeimage.kind"))
(when-let [bin (-> (java.lang.ProcessHandle/current)
.info
.command
(.orElse nil))]
(let [fn (fs/file-name bin)]
(if (= "bb" fn)
false
(if (and (fs/windows?)
(= "bb.exe" fn))
false
(when (try (with-open [_ (java.util.zip.ZipFile. (fs/file bin))])
true
(catch Exception _ false))
bin)))))))
(defn resolve-symbolic-link [f]
(if (and f (fs/exists? f))
(try
(str (fs/real-path f))
(catch Exception _
f))
f))
(defn deps-not-needed [opts]
(let [fast-path-opts [:version :help :describe?]]
(some #(contains? opts %) fast-path-opts)))
(defn main [& args] (defn main [& args]
(let [bin-jar (binary-invoked-as-jar) (let [[args opts] (parse-global-opts args)
args (if bin-jar {:keys [jar file config merge-deps] :as opts}
(list* "--jar" bin-jar "--" args)
args)
[args opts] (parse-global-opts args)
[args {:keys [config merge-deps debug] :as opts}]
(if-not (or (:file opts) (if-not (or (:file opts)
(:jar opts)) (:jar opts))
(parse-file-opt args opts) (parse-file-opt args opts)
[args opts]) opts)
{:keys [jar file]} opts abs-path #(-> % io/file .getAbsolutePath)
abs-path resolve-symbolic-link
config (cond config (cond
config (if (fs/exists? config) (abs-path config) config (when (fs/exists? config) (abs-path config))
(when debug jar (some-> [jar] cp/new-loader (cp/resource "META-INF/bb.edn") .toString)
(binding [*out* *err*]
(println "[babashka] WARNING: config file does not exist:" config))
nil))
jar (let [jar (resolve-symbolic-link jar)]
(some->> [jar] cp/new-loader (cp/resource "META-INF/bb.edn") .toString))
:else (if (and file (fs/exists? file)) :else (if (and file (fs/exists? file))
;; file relative to bb.edn ;; file relative to bb.edn
(let [file (abs-path file) ;; follow symlink (let [rel-bb-edn (fs/file (fs/parent file) "bb.edn")]
rel-bb-edn (fs/file (fs/parent file) "bb.edn")]
(if (fs/exists? rel-bb-edn) (if (fs/exists? rel-bb-edn)
(abs-path rel-bb-edn) (abs-path rel-bb-edn)
;; fall back to local bb.edn ;; fall back to local bb.edn
@ -1219,6 +1153,7 @@ Use bb run --help to show this help output.
edn)] edn)]
(vreset! common/bb-edn edn))) (vreset! common/bb-edn edn)))
opts (parse-opts args opts) opts (parse-opts args opts)
;; _ (.println System/err (str bb-edn))
min-bb-version (:min-bb-version bb-edn)] min-bb-version (:min-bb-version bb-edn)]
(System/setProperty "java.class.path" "") (System/setProperty "java.class.path" "")
(when min-bb-version (when min-bb-version
@ -1226,9 +1161,7 @@ Use bb run --help to show this help output.
(binding [*out* *err*] (binding [*out* *err*]
(println (str "WARNING: this project requires babashka " (println (str "WARNING: this project requires babashka "
min-bb-version " or newer, but you have: " version))))) min-bb-version " or newer, but you have: " version)))))
(if (deps-not-needed opts) (exec opts)))
(exec-without-deps opts)
(exec opts))))
(def musl? (def musl?
"Captured at compile time, to know if we are running inside a "Captured at compile time, to know if we are running inside a

View file

@ -1,6 +1,6 @@
(ns my.main-main (ns my.main-main
(:require [my.impl :as impl]) (:require [my.impl :as impl])
(:require [my.impl2])) (:require [my.impl2 :as impl2]))
(defn -main [& args] (defn -main [& args]
(prn (impl/impl-fn args))) (impl/impl-fn args))

View file

@ -1,22 +0,0 @@
(ns bytechannel-and-related-classes
(:require [clojure.java.io :as io])
(:import (java.nio.file OpenOption
StandardOpenOption)
(java.nio.channels ByteChannel
FileChannel
ReadableByteChannel
WritableByteChannel
Channels)))
(when (and (let [ch (-> (.getBytes "Hello")
(java.io.ByteArrayInputStream.)
(Channels/newChannel))]
(instance? ReadableByteChannel ch))
(let [ch (-> (java.io.ByteArrayOutputStream.)
(Channels/newChannel))]
(instance? WritableByteChannel ch))
(with-open [ch (FileChannel/open (-> (io/file "README.md")
(.toPath))
(into-array OpenOption [StandardOpenOption/READ]))]
(instance? ByteChannel ch)))
(println :success))

View file

@ -1 +0,0 @@
42

View file

@ -187,34 +187,4 @@
net.cgrand/xforms {:git-url "https://github.com/cgrand/xforms", net.cgrand/xforms {:git-url "https://github.com/cgrand/xforms",
:git-sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6", :git-sha "550dbc150a79c6ecc148d8a7e260e10bc36321c6",
:test-namespaces [net.cgrand.xforms-test], :test-namespaces [net.cgrand.xforms-test],
:test-paths ["test"]} :test-paths ["test"]}}
prismatic/plumbing {:git-url "https://github.com/plumatic/plumbing",
:git-sha "424bc704f2db422de34269c139a5494314b3a43b",
:test-namespaces [plumbing.core-test],
:test-paths ["test"]}
org.clj-commons/hickory {:git-url "https://github.com/clj-commons/hickory"
:git-sha "9385b6708ef35f161732d8464b3a3aa57dd79f30"
:test-paths ["test/cljc"]
:test-namespaces [hickory.test.core
hickory.test.convert
hickory.test.hiccup-utils
hickory.test.render
hickory.test.select
hickory.test.zip]}
cheshire/cheshire {:git-url "https://github.com/dakrone/cheshire", :test-namespaces [cheshire.test.core], :manually-added true}
com.potetm/fusebox {:git-url "https://github.com/potetm/fusebox"
:git-sha "ac6d6a0a69510b009b3c1bb2247cd110fd9f7246"
:test-paths ["test"]
:test-namespaces [#_com.potetm.fusebox.bulkhead-test
com.potetm.fusebox.bulwark-test
com.potetm.fusebox.circuit-breaker-test
com.potetm.fusebox.fallback-test
com.potetm.fusebox.memoize-test
#_com.potetm.fusebox.rate-limit-test
com.potetm.fusebox.registry-test
com.potetm.fusebox.retry-test
#_com.potetm.fusebox.timeout-test]}
net.sekao/odoyle-rules {:git-url "https://github.com/oakes/odoyle-rules"
:git-sha "0b1d825ec45a998c4d3481dfb292e08ce6a47f0b"
:test-paths ["test"]
:test-namespaces [odoyle.rules-test]}}

View file

@ -1,793 +0,0 @@
(ns cheshire.test.core
(:require [clojure.test :refer [deftest testing is are]]
[clojure.java.io :as io]
[clojure.string :as str]
[cheshire.core :as json]
;; BB-TEST-PATCH: bb does not include cheshire.exact
#_[cheshire.exact :as json-exact]
;; BB-TEST-PATCH: bb does not include cheshire.gen
#_[cheshire.generate :as gen]
[cheshire.factory :as fact]
;; BB-TEST-PATCH: bb does not include cheshire.parse
#_[cheshire.parse :as parse])
(:import ;; BB-TEST-PATCH: tests adjusted to check for general Exception instead of specific jackson exceptions
#_(com.fasterxml.jackson.core JsonGenerationException
JsonParseException)
#_(com.fasterxml.jackson.core.exc StreamConstraintsException)
(java.io StringReader StringWriter
BufferedReader BufferedWriter
IOException)
;; BB-TEST-PATCH: bb does not support creating java.sql.Timestamps
#_(java.sql Timestamp)
(java.util Date UUID)))
(defn- str-of-len
([len]
(str-of-len len "x"))
([len val]
(apply str (repeat len val))))
(defn- nested-map [depth]
(reduce (fn [acc n] {(str n) acc})
{"0" "foo"}
(range 1 depth)))
(defn- encode-stream->str [obj opts]
(let [sw (StringWriter.)
bw (BufferedWriter. sw)]
(json/generate-stream obj bw opts)
(.toString sw)))
(def test-obj {"int" 3 "long" (long -2147483647) "boolean" true
"LongObj" (Long/parseLong "2147483647") "double" 1.23
"nil" nil "string" "string" "vec" [1 2 3] "map" {"a" "b"}
"list" (list "a" "b") "short" (short 21) "byte" (byte 3)})
(deftest t-ratio
(let [n 1/2]
(is (= (double n) (:num (json/decode (json/encode {:num n}) true))))))
(deftest t-long-wrap-around
(is (= 2147483648 (json/decode (json/encode 2147483648)))))
(deftest t-bigint
(let [n 9223372036854775808]
(is (= n (:num (json/decode (json/encode {:num n}) true))))))
(deftest t-biginteger
(let [n (BigInteger. "42")]
(is (= n (:num (json/decode (json/encode {:num n}) true))))))
(deftest t-bigdecimal
(let [n (BigDecimal. "42.5")]
(is (= (.doubleValue n) (:num (json/decode (json/encode {:num n}) true))))
;; BB-TEST-PATCH:
#_(binding [parse/*use-bigdecimals?* true]
(is (= n (:num (json/decode (json/encode {:num n}) true)))))))
(deftest test-string-round-trip
(is (= test-obj (json/decode (json/encode test-obj)))))
(deftest test-generate-accepts-float
(is (= "3.14" (json/encode 3.14))))
(deftest test-keyword-encode
(is (= {"key" "val"}
(json/decode (json/encode {:key "val"})))))
(deftest test-generate-set
(is (= {"set" ["a" "b"]}
(json/decode (json/encode {"set" #{"a" "b"}})))))
(deftest test-generate-empty-set
(is (= {"set" []}
(json/decode (json/encode {"set" #{}})))))
(deftest test-generate-empty-array
(is (= {"array" []}
(json/decode (json/encode {"array" []})))))
(deftest test-key-coercion
(is (= {"foo" "bar" "1" "bat" "2" "bang" "3" "biz"}
(json/decode
(json/encode
{:foo "bar" 1 "bat" (long 2) "bang" (bigint 3) "biz"})))))
(deftest test-keywords
(is (= {:foo "bar" :bat 1}
(json/decode (json/encode {:foo "bar" :bat 1}) true))))
(deftest test-symbols
(is (= {"foo" "clojure.core/map"}
(json/decode (json/encode {"foo" 'clojure.core/map})))))
(deftest test-accepts-java-map
(is (= {"foo" 1}
(json/decode
(json/encode (doto (java.util.HashMap.) (.put "foo" 1)))))))
(deftest test-accepts-java-list
(is (= [1 2 3]
(json/decode (json/encode (doto (java.util.ArrayList. 3)
(.add 1)
(.add 2)
(.add 3)))))))
(deftest test-accepts-java-set
(is (= {"set" [1 2 3]}
(json/decode (json/encode {"set" (doto (java.util.HashSet. 3)
(.add 1)
(.add 2)
(.add 3))})))))
(deftest test-accepts-empty-java-set
(is (= {"set" []}
(json/decode (json/encode {"set" (java.util.HashSet. 3)})))))
(deftest test-nil
(is (nil? (json/decode nil true))))
(deftest test-parsed-seq
(let [br (BufferedReader. (StringReader. "1\n2\n3\n"))]
(is (= (list 1 2 3) (json/parsed-seq br)))))
;; BB-TEST-PATCH: bb does not support smile
#_(deftest test-smile-round-trip
(is (= test-obj (json/parse-smile (json/generate-smile test-obj)))))
(def bin-obj {"byte-array" (byte-array (map byte [1 2 3]))})
;; BB-TEST-PATCH: bb does not support smile/cbor
#_(deftest test-round-trip-binary
(doseq [[p g] {json/parse-string json/generate-string
json/parse-smile json/generate-smile
json/parse-cbor json/generate-cbor}]
(is (let [roundtripped (p (g bin-obj))]
;; test value equality
(is (= (->> bin-obj (get "byte-array") seq)
(->> roundtripped (get "byte-array") seq)))))))
;; BB-TEST-PATCH: bb does not support smile
#_(deftest test-smile-factory
(binding [fact/*smile-factory* (fact/make-smile-factory {})]
(is (= {"a" 1} (-> {:a 1}
json/generate-smile
json/parse-smile)))))
;; BB-TEST-PATCH: bb does not support smile/cbor
#_(deftest test-smile-duplicate-detection
(let [smile-data (byte-array [0x3a 0x29 0x0a 0x01 ;; smile header
0xFa ;; object start
0x80 0x61 ;; key a
0xC2 ;; value 1
0x80 0x61 ;; key a (again)
0xC4 ;; value 2
0xFB ;; object end
])]
(binding [fact/*smile-factory* (fact/make-smile-factory {:strict-duplicate-detection false})]
(is (= {"a" 2} (json/parse-smile smile-data))))
(binding [fact/*smile-factory* (fact/make-smile-factory {:strict-duplicate-detection true})]
(is (thrown? JsonParseException (json/parse-smile smile-data))))))
;; BB-TEST-PATCH: bb does not support cbor
#_(deftest test-cbor-factory
(binding [fact/*cbor-factory* (fact/make-cbor-factory {})]
(is (= {"a" 1} (-> {:a 1}
json/generate-cbor
json/parse-cbor)))))
;; BB-TEST-PATCH: bb does not support cbor
#_(deftest test-cbor-duplicate-detection
(let [cbor-data (byte-array [0xbf ;; object begin
0x61 0x61 ;; key a
0x01 ;; value 1
0x61 0x61 ;; key a (again)
0x02 ;; value 2
0xff ;; object end
])]
(binding [fact/*cbor-factory* (fact/make-cbor-factory {:strict-duplicate-detection false})]
(is (= {"a" 2} (json/parse-cbor cbor-data))))
(binding [fact/*cbor-factory* (fact/make-cbor-factory {:strict-duplicate-detection true})]
(is (thrown? JsonParseException (json/parse-cbor cbor-data))))))
(deftest test-aliases
(is (= {"foo" "bar" "1" "bat" "2" "bang" "3" "biz"}
(json/decode
(json/encode
{:foo "bar" 1 "bat" (long 2) "bang" (bigint 3) "biz"})))))
(deftest test-date
(is (= {"foo" "1970-01-01T00:00:00Z"}
(json/decode (json/encode {:foo (Date. (long 0))}))))
(is (= {"foo" "1970-01-01"}
(json/decode (json/encode {:foo (Date. (long 0))}
{:date-format "yyyy-MM-dd"})))
"encode with given date format"))
;; BB-TEST-PATCH: bb does not support creating java.sql.Timestamps
#_(deftest test-sql-timestamp
(is (= {"foo" "1970-01-01T00:00:00Z"}
(json/decode (json/encode {:foo (Timestamp. (long 0))}))))
(is (= {"foo" "1970-01-01"}
(json/decode (json/encode {:foo (Timestamp. (long 0))}
{:date-format "yyyy-MM-dd"})))
"encode with given date format"))
(deftest test-uuid
(let [id (UUID/randomUUID)
id-str (str id)]
(is (= {"foo" id-str} (json/decode (json/encode {:foo id}))))))
(deftest test-char-literal
(is (= "{\"foo\":\"a\"}" (json/encode {:foo \a}))))
(deftest test-streams
(testing "parse-stream"
(are [parsed parse parsee] (= parsed
(parse (BufferedReader. (StringReader. parsee))))
{"foo" "bar"} json/parse-stream "{\"foo\":\"bar\"}\n"
{"foo" "bar"} json/parse-stream-strict "{\"foo\":\"bar\"}\n")
(are [parsed parse parsee] (= parsed
(with-open [rdr (StringReader. parsee)]
(parse rdr true)))
{(keyword "foo baz") "bar"} json/parse-stream "{\"foo baz\":\"bar\"}\n"
{(keyword "foo baz") "bar"} json/parse-stream-strict "{\"foo baz\":\"bar\"}\n"))
(testing "generate-stream"
(let [sw (StringWriter.)
bw (BufferedWriter. sw)]
(json/generate-stream {"foo" "bar"} bw)
(is (= "{\"foo\":\"bar\"}" (.toString sw))))))
;; BB-TEST-PATCH: bb does not include with-writer
#_(deftest serial-writing
(is (= "[\"foo\",\"bar\"]"
(.toString
(json/with-writer [(StringWriter.) nil]
(json/write [] :start)
(json/write "foo")
(json/write "bar")
(json/write [] :end)))))
(is (= "[1,[2,3],4]"
(.toString
(json/with-writer [(StringWriter.) nil]
(json/write [1 [2]] :start-inner)
(json/write 3)
(json/write [] :end)
(json/write 4)
(json/write [] :end)))))
(is (= "{\"a\":1,\"b\":2,\"c\":3}"
(.toString
(json/with-writer [(StringWriter.) nil]
(json/write {:a 1} :start)
(json/write {:b 2} :bare)
(json/write {:c 3} :end)))))
(is (= (str "[\"start\",\"continue\",[\"implicitly-nested\"],"
"[\"explicitly-nested\"],\"flatten\",\"end\"]")
(.toString
(json/with-writer [(StringWriter.) nil]
(json/write ["start"] :start)
(json/write "continue")
(json/write ["implicitly-nested"])
(json/write ["explicitly-nested"] :all)
(json/write ["flatten"] :bare)
(json/write ["end"] :end)))))
(is (= "{\"head\":\"head info\",\"data\":[1,2,3],\"tail\":\"tail info\"}"
(.toString
(json/with-writer [(StringWriter.) nil]
(json/write {:head "head info" :data []} :start-inner)
(json/write 1)
(json/write 2)
(json/write 3)
(json/write [] :end)
(json/write {:tail "tail info"} :end))))))
;; BB-TEST-PATCH: modified so that json files could be found
(deftest test-multiple-objs-in-file
(is (= {"one" 1, "foo" "bar"}
(first (json/parsed-seq (io/reader (io/resource "cheshire/test/multi.json"))))))
(is (= {"two" 2, "foo" "bar"}
(second (json/parsed-seq (io/reader (io/resource "cheshire/test/multi.json"))))))
(with-open [r (io/reader (io/resource "cheshire/test/multi.json"))]
(is (= [{"one" 1, "foo" "bar"} {"two" 2, "foo" "bar"}]
(json/parsed-seq r)))))
(deftest test-jsondotorg-pass1
(let [;; BB-TEST-PATCH: modified so that json files could be found
string (slurp (io/resource "cheshire/test/pass1.json"))
decoded-json (json/decode string)
encoded-json (json/encode decoded-json)
re-decoded-json (json/decode encoded-json)]
(is (= decoded-json re-decoded-json))))
(deftest test-namespaced-keywords
(is (= "{\"foo\":\"user/bar\"}"
(json/encode {:foo :user/bar})))
(is (= {:foo/bar "baz/eggplant"}
(json/decode (json/encode {:foo/bar :baz/eggplant}) true))))
(deftest test-array-coerce-fn
(is (= {"set" #{"a" "b"} "array" ["a" "b"] "map" {"a" 1}}
(json/decode
(json/encode {"set" #{"a" "b"} "array" ["a" "b"] "map" {"a" 1}}) false
(fn [field-name] (if (= "set" field-name) #{} []))))))
(deftest t-symbol-encoding-for-non-resolvable-symbols
(is (= "{\"bar\":\"clojure.core/pam\",\"foo\":\"clojure.core/map\"}"
(json/encode (sorted-map :foo 'clojure.core/map :bar 'clojure.core/pam))))
(is (= "{\"bar\":\"clojure.core/pam\",\"foo\":\"foo.bar/baz\"}"
(json/encode (sorted-map :foo 'foo.bar/baz :bar 'clojure.core/pam)))))
(deftest t-bindable-factories-auto-close-source
(binding [fact/*json-factory* (fact/make-json-factory
{:auto-close-source false})]
(let [br (BufferedReader. (StringReader. "123"))]
(is (= 123 (json/parse-stream br)))
(is (= -1 (.read br)))))
(binding [fact/*json-factory* (fact/make-json-factory
{:auto-close-source true})]
(let [br (BufferedReader. (StringReader. "123"))]
(is (= 123 (json/parse-stream br)))
(is (thrown? IOException (.read br))))))
(deftest t-bindable-factories-allow-comments
(let [s "{\"a\": /* comment */ 1, // comment\n \"b\": 2}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-comments true})]
(is (= {"a" 1 "b" 2} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-comments false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s))))))
(deftest t-bindable-factories-allow-unquoted-field-names
(let [s "{a: 1, b: 2}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-unquoted-field-names true})]
(is (= {"a" 1 "b" 2} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-unquoted-field-names false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s))))))
(deftest t-bindable-factories-allow-single-quotes
(doseq [s ["{'a': \"one\", 'b': \"two\"}"
"{\"a\": 'one', \"b\": 'two'}"
"{'a': 'one', 'b': 'two'}"]]
(testing s
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-single-quotes true})]
(is (= {"a" "one" "b" "two"} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-single-quotes false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s)))))))
(deftest t-bindable-factories-allow-unquoted-control-chars
(let [s "{\"a\": \"one\ntwo\"}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-unquoted-control-chars true})]
(is (= {"a" "one\ntwo"} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-unquoted-control-chars false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s))))))
(deftest t-bindable-factories-allow-backslash-escaping-any-char
(let [s "{\"a\": 00000000001}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-numeric-leading-zeros true})]
(is (= {"a" 1} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-numeric-leading-zeros false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s))))))
(deftest t-bindable-factories-allow-numeric-leading-zeros
(let [s "{\"a\": \"\\o\\n\\e\"}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-backslash-escaping true})]
(is (= {"a" "o\ne"} (json/decode s))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-backslash-escaping false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s))))))
(deftest t-bindable-factories-non-numeric-numbers
(let [s "{\"foo\":NaN}"]
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-non-numeric-numbers true})]
(is (= (type Double/NaN)
(type (:foo (json/decode s true))))))
(binding [fact/*json-factory* (fact/make-json-factory
{:allow-non-numeric-numbers false})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_JsonParseException Exception (json/decode s true))))))
(deftest t-bindable-factories-optimization-opts
(let [s "{\"a\": \"foo\"}"]
(doseq [opts [{:intern-field-names true}
{:intern-field-names false}
{:canonicalize-field-names true}
{:canonicalize-field-names false}]]
(binding [fact/*json-factory* (fact/make-json-factory opts)]
(is (= {"a" "foo"} (json/decode s)))))))
(deftest t-bindable-factories-escape-non-ascii
;; includes testing legacy fn opt of same name can override factory
(let [edn {:foo "It costs £100"}
expected-esc "{\"foo\":\"It costs \\u00A3100\"}"
expected-no-esc "{\"foo\":\"It costs £100\"}"
opt-esc {:escape-non-ascii true}
opt-no-esc {:escape-non-ascii false}]
(testing "default factory"
(doseq [[fn-opts expected]
[[{} expected-no-esc]
[opt-esc expected-esc]
[opt-no-esc expected-no-esc]]]
(testing fn-opts
(is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts))))))
(testing (str "factory: " opt-esc)
(binding [fact/*json-factory* (fact/make-json-factory opt-esc)]
(doseq [[fn-opts expected]
[[{} expected-esc]
[opt-esc expected-esc]
[opt-no-esc expected-no-esc]]]
(testing (str "fn: " fn-opts)
(is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts)))))))
(testing (str "factory: " opt-no-esc)
(binding [fact/*json-factory* (fact/make-json-factory opt-no-esc)]
(doseq [[fn-opts expected]
[[{} expected-no-esc]
[opt-esc expected-esc]
[opt-no-esc expected-no-esc]]]
(testing (str "fn: " fn-opts)
(is (= expected (json/encode edn fn-opts) (encode-stream->str edn fn-opts)))))))))
(deftest t-bindable-factories-quoteless
(binding [fact/*json-factory* (fact/make-json-factory
{:quote-field-names true})]
(is (= "{\"a\":\"foo\"}" (json/encode {:a "foo"}))))
(binding [fact/*json-factory* (fact/make-json-factory
{:quote-field-names false})]
(is (= "{a:\"foo\"}" (json/encode {:a "foo"})))))
(deftest t-bindable-factories-strict-duplicate-detection
(binding [fact/*json-factory* (fact/make-json-factory
{:strict-duplicate-detection true})]
;; BB-TEST-PATCH: Generalized exception check
(is (thrown? #_ JsonParseException Exception
(json/decode "{\"a\": 1, \"b\": 2, \"a\": 3}"))))
(binding [fact/*json-factory* (fact/make-json-factory
{:strict-duplicate-detection false})]
(is (= {"a" 3 "b" 2}
(json/decode "{\"a\": 1, \"b\": 2, \"a\": 3}")))))
(deftest t-bindable-factories-max-input-document-length
(let [edn {"a" (apply str (repeat 10000 "x"))}
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-document-length (count sample-data)})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
;; as per Jackson docs, limit is inexact, so dividing input length by 2 should do the trick
{:max-input-document-length (/ (count sample-data) 2)})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)document length .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-max-input-token-count
;; A token is a single unit of input, such as a number, a string, an object start or end, or an array start or end.
(let [edn {"1" 2 "3" 4}
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-token-count 6})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-token-count 5})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)token count .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-max-input-name-length
(let [k "somekey"
edn {k 1}
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-name-length (count k)})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-name-length (dec (count k))})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)name .* exceeds"
(json/decode sample-data)))))
(let [default-limit (:max-input-name-length fact/default-factory-options)]
(let [k (str-of-len default-limit)
edn {k 1}
sample-data (json/encode edn)]
(is (= edn (json/decode sample-data))))
(let [k (str-of-len (inc default-limit))
sample-data (json/encode {k 1})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)name .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-input-nesting-depth
(let [edn (nested-map 100)
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-nesting-depth 100})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-nesting-depth 99})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)nesting depth .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-max-input-number-length
(let [num 123456789
edn {"foo" num}
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-number-length (-> num str count)})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-number-length (-> num str count dec)})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)number value length .* exceeds"
(json/decode sample-data)))))
(let [default-limit (:max-input-number-length fact/default-factory-options)]
(let [num (bigint (str-of-len default-limit 2))
edn {"foo" num}
sample-data (json/encode edn)]
(is (= edn (json/decode sample-data))))
(let [num (bigint (str-of-len (inc default-limit) 2))
sample-data (json/encode {"foo" num})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)number value length .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-max-input-string-length
(let [big-string (str-of-len 40000000)
edn {"big-string" big-string}
sample-data (json/encode edn)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-string-length (count big-string)})]
(is (= edn (json/decode sample-data))))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-input-string-length (dec (count big-string))})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)string value length .* exceeds"
(json/decode sample-data)))))
(let [default-limit (:max-input-string-length fact/default-factory-options)]
(let [big-string (str-of-len default-limit)
edn {"big-string" big-string}
sample-data (json/encode edn)]
(is (= edn (json/decode sample-data))))
(let [big-string (str-of-len (inc default-limit))
sample-data (json/encode {"big-string" big-string})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)string value length .* exceeds"
(json/decode sample-data))))))
(deftest t-bindable-factories-max-output-nesting-depth
(let [edn (nested-map 100)]
(binding [fact/*json-factory* (fact/make-json-factory
{:max-output-nesting-depth 100})]
(is (.contains (json/encode edn) "\"99\"")))
(binding [fact/*json-factory* (fact/make-json-factory
{:max-output-nesting-depth 99})]
(is (thrown-with-msg?
;; BB-TEST-PATCH: Generalized exception check
#_StreamConstraintsException Exception #"(?i)nesting depth .* exceeds"
(json/encode edn))))))
(deftest t-persistent-queue
(let [q (conj clojure.lang.PersistentQueue/EMPTY 1 2 3)]
(is (= q (json/decode (json/encode q))))))
(deftest t-pretty-print
(is (= (str/join (System/lineSeparator)
["{"
" \"bar\" : [ {"
" \"baz\" : 2"
" }, \"quux\", [ 1, 2, 3 ] ],"
" \"foo\" : 1"
"}"])
(json/encode (sorted-map :foo 1 :bar [{:baz 2} :quux [1 2 3]])
{:pretty true}))))
(deftest t-pretty-print-custom-linebreak
(is (= (str/join "foo"
["{"
" \"bar\" : [ {"
" \"baz\" : 2"
" }, \"quux\", [ 1, 2, 3 ] ],"
" \"foo\" : 1"
"}"])
(json/encode (sorted-map :foo 1 :bar [{:baz 2} :quux [1 2 3]])
{:pretty {:line-break "foo"}}))))
(deftest t-pretty-print-illegal-argument
; just expecting this not to throw
(json/encode {:foo "bar"}
{:pretty []})
(json/encode {:foo "bar"}
{:pretty nil}))
(deftest t-custom-pretty-print-with-defaults
(let [test-obj (sorted-map :foo 1 :bar {:baz [{:ulu "mulu"} {:moot "foo"} 3]} :quux :blub)
pretty-str-default (json/encode test-obj {:pretty true})
pretty-str-custom (json/encode test-obj {:pretty {}})]
(is (= pretty-str-default pretty-str-custom))
(when-not (= pretty-str-default pretty-str-custom)
; print for easy comparison
(println "; default pretty print")
(println pretty-str-default)
(println "; custom pretty print with default options")
(println pretty-str-custom))))
(deftest t-custom-pretty-print-with-non-defaults
(let [test-obj (sorted-map :foo 1 :bar {:baz [{:ulu "mulu"} {:moot "foo"} 3]} :quux :blub)
test-opts {:pretty {:indentation 4
:indent-arrays? false
:before-array-values ""
:after-array-values ""
:object-field-value-separator ": "}}
expected (str/join (System/lineSeparator)
["{"
" \"bar\": {"
" \"baz\": [{"
" \"ulu\": \"mulu\""
" }, {"
" \"moot\": \"foo\""
" }, 3]"
" },"
" \"foo\": 1,"
" \"quux\": \"blub\""
"}"])
pretty-str (json/encode test-obj test-opts)]
; just to be easy on the eyes in case of error
(when-not (= expected pretty-str)
(println "; pretty print with options - actual")
(println pretty-str)
(println "; pretty print with options - expected")
(println expected))
(is (= expected pretty-str))))
(deftest t-custom-pretty-print-with-noident-objects
(let [test-obj [{:foo 1 :bar 2} {:foo 3 :bar 4}]
test-opts {:pretty {:indent-objects? false}}
expected (str "[ { \"foo\" : 1, \"bar\" : 2 }, "
"{ \"foo\" : 3, \"bar\" : 4 } ]")
pretty-str (json/encode test-obj test-opts)]
; just to be easy on the eyes in case of error
(when-not (= expected pretty-str)
(println "; pretty print with options - actual")
(println pretty-str)
(println "; pretty print with options - expected")
(println expected))
(is (= expected pretty-str))))
(deftest t-custom-keyword-fn
(is (= {:FOO "bar"} (json/decode "{\"foo\": \"bar\"}"
(fn [k] (keyword (.toUpperCase k))))))
(is (= {"foo" "bar"} (json/decode "{\"foo\": \"bar\"}" nil)))
(is (= {"foo" "bar"} (json/decode "{\"foo\": \"bar\"}" false)))
(is (= {:foo "bar"} (json/decode "{\"foo\": \"bar\"}" true))))
(deftest t-custom-encode-key-fn
(is (= "{\"FOO\":\"bar\"}"
(json/encode {:foo :bar}
{:key-fn (fn [k] (.toUpperCase (name k)))}))))
;; BB-TEST-PATCH: bb does nto include cheshire.generate ns
#_(deftest test-add-remove-encoder
(gen/remove-encoder java.net.URL)
(gen/add-encoder java.net.URL gen/encode-str)
(is (= "\"http://foo.com\""
(json/encode (java.net.URL. "http://foo.com"))))
(gen/remove-encoder java.net.URL)
(is (thrown? JsonGenerationException
(json/encode (java.net.URL. "http://foo.com")))))
#_(defprotocol TestP
(foo [this] "foo method"))
#_(defrecord TestR [state])
#_(extend TestR
TestP
{:foo (constantly "bar")})
#_(deftest t-custom-protocol-encoder
(let [rec (TestR. :quux)]
(is (= {:state "quux"} (json/decode (json/encode rec) true)))
(gen/add-encoder cheshire.test.core.TestR
(fn [obj jg]
(.writeString jg (foo obj))))
(is (= "bar" (json/decode (json/encode rec))))
(gen/remove-encoder cheshire.test.core.TestR)
(is (= {:state "quux"} (json/decode (json/encode rec) true)))))
#_(defprotocol CTestP
(thing [this] "thing method"))
#_(defrecord CTestR [state])
#_(extend CTestR
CTestP
{:thing (constantly "thing")})
#_(deftest t-custom-helpers
(let [thing (CTestR. :state)
remove #(gen/remove-encoder CTestR)]
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-nil nil jg)))
(is (= nil (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-str "foo" jg)))
(is (= "foo" (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-number 5 jg)))
(is (= 5 (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-long 4 jg)))
(is (= 4 (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-int 3 jg)))
(is (= 3 (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-ratio 1/2 jg)))
(is (= 0.5 (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-seq [:foo :bar] jg)))
(is (= ["foo" "bar"] (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-date (Date. (long 0)) jg)))
(binding [gen/*date-format* "yyyy-MM-dd'T'HH:mm:ss'Z'"]
(is (= "1970-01-01T00:00:00Z" (json/decode (json/encode thing) true))))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-bool true jg)))
(is (= true (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-named :foo jg)))
(is (= "foo" (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-map {:foo "bar"} jg)))
(is (= {:foo "bar"} (json/decode (json/encode thing) true)))
(remove)
(gen/add-encoder CTestR (fn [_obj jg] (gen/encode-symbol 'foo jg)))
(is (= "foo" (json/decode (json/encode thing) true)))
(remove)))
(deftest t-float-encoding
(is (= "{\"foo\":0.01}" (json/encode {:foo (float 0.01)}))))
(deftest t-non-const-bools
(is (= {:a 1} (json/decode "{\"a\": 1}" (Boolean. true)))))
;; BB-TEST-PATCH: bb does not include cheshire.exact ns
#_(deftest t-invalid-json
(let [invalid-json-message "Invalid JSON, expected exactly one parseable object but multiple objects were found"]
(are [x y] (= x (try
y
(catch Exception e
(.getMessage e))))
invalid-json-message (json-exact/decode "{\"foo\": 1}asdf")
invalid-json-message (json-exact/decode "{\"foo\": 123}null")
invalid-json-message (json-exact/decode "\"hello\" : 123}")
{"foo" 1} (json/decode "{\"foo\": 1}")
invalid-json-message (json-exact/decode-strict "{\"foo\": 1}asdf")
invalid-json-message (json-exact/decode-strict "{\"foo\": 123}null")
invalid-json-message (json-exact/decode-strict "\"hello\" : 123}")
{"foo" 1} (json/decode-strict "{\"foo\": 1}"))))

View file

@ -1,2 +0,0 @@
{"one":1,"foo":"bar"}
{"two":2,"foo":"bar"}

View file

@ -1,58 +0,0 @@
[
"JSON Test Pattern pass1",
{"object with 1 member":["array with 1 element"]},
{},
[],
-42,
true,
false,
null,
{
"integer": 1234567890,
"real": -9876.543210,
"e": 0.123456789e-12,
"E": 1.234567890E+34,
"": 23456789012E66,
"zero": 0,
"one": 1,
"space": " ",
"quote": "\"",
"backslash": "\\",
"controls": "\b\f\n\r\t",
"slash": "/ & \/",
"alpha": "abcdefghijklmnopqrstuvwyz",
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
"digit": "0123456789",
"0123456789": "digit",
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
"true": true,
"false": false,
"null": null,
"array":[ ],
"object":{ },
"address": "50 St. James Street",
"url": "http://www.JSON.org/",
"comment": "// /* <!-- --",
"# -- --> */": " ",
" s p a c e d " :[1,2 , 3
,
4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
"quotes": "&#34; \u0022 %22 0x22 034 &#x22;",
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
: "A key can be any string"
},
0.5 ,98.6
,
99.44
,
1066,
1e1,
0.1e1,
1e-1,
1e00,2e+00,2e-00
,"rosebud"]

View file

@ -341,7 +341,7 @@
(is (= ::response r)))) (is (= ::response r))))
(try (get "https://httpbin.org/gzip" {:timeout 1000}) (try (get "https://httpbin.org/gzip" {:timeout 1000})
(catch Exception _ (catch java.net.http.HttpTimeoutException _
(doseq [v (vals (ns-publics *ns*))] (doseq [v (vals (ns-publics *ns*))]
(when (:integration (meta v)) (when (:integration (meta v))
(println "Removing test from" v "because httpbin is slow.") (println "Removing test from" v "because httpbin is slow.")

View file

@ -1,6 +1,5 @@
(ns httpkit.client-test (ns httpkit.client-test
(:require [cheshire.core :as json] (:require [cheshire.core :as json]
[clojure.string :as str]
[clojure.test :refer [deftest is testing #_*report-counters*]] [clojure.test :refer [deftest is testing #_*report-counters*]]
[org.httpkit.client :as client])) [org.httpkit.client :as client]))
@ -17,14 +16,12 @@
(deftest get-test (deftest get-test
(is (= 200 (:status @(client/get "https://postman-echo.com/get")))) (is (= 200 (:status @(client/get "https://postman-echo.com/get"))))
(is (str/includes? (is (= "https://postman-echo.com/get"
(-> @(client/get "https://postman-echo.com/get" (-> @(client/get "https://postman-echo.com/get"
{:headers {"Accept" "application/json"}}) {:headers {"Accept" "application/json"}})
:body :body
(json/parse-string true) (json/parse-string true)
:url) :url)))
"postman-echo.com/get"))
;; BB-TEST-PATCH: postman started responding with http:// instead of https://
(testing "query params" (testing "query params"
(is (= {:foo1 "bar1", :foo2 "bar2"} (is (= {:foo1 "bar1", :foo2 "bar2"}
(-> @(client/get "https://postman-echo.com/get" {:query-params {"foo1" "bar1" "foo2" "bar2"}}) (-> @(client/get "https://postman-echo.com/get" {:query-params {"foo1" "bar1" "foo2" "bar2"}})

View file

@ -1,77 +1,67 @@
(ns rewrite-clj.node.coercer-test (ns rewrite-clj.node.coercer-test
(:require [clojure.test :refer [deftest testing is are]] (:require [clojure.test :refer [deftest testing is are]]
[rewrite-clj.node :as node] [rewrite-clj.node :as node]
[rewrite-clj.node.protocols :as protocols]
[rewrite-clj.node.regex :as regex]
[rewrite-clj.parser :as p])) [rewrite-clj.parser :as p]))
(deftest t-sexpr->node->sexpr-roundtrip (deftest t-sexpr->node->sexpr-roundtrip
(testing "simple cases roundtrip" (testing "simple cases roundtrip"
(are [?sexpr expected-tag expected-type] (are [?sexpr expected-tag ]
(let [n (node/coerce ?sexpr)] (let [n (node/coerce ?sexpr)]
(is (node/node? n)) (is (node/node? n))
(is (= ?sexpr (node/sexpr n))) (is (= ?sexpr (node/sexpr n)))
(is (string? (node/string n))) (is (string? (node/string n)))
(is (= expected-tag (node/tag n)) "tag") (is (= expected-tag (node/tag n)) "tag")
#_(is (= expected-type (protocols/node-type n)) "node-type")
(is (not (meta n))) (is (not (meta n)))
(if (seq? ?sexpr) (is (= (type ?sexpr) (type (node/sexpr n)))))
(is (seq? (node/sexpr n)))
(is (= (type (node/sexpr n)) (type ?sexpr) ))))
;; numbers ;; numbers
;; note that we do have an integer-node, but rewrite-clj never parses to it ;; note that we do have an integer-node, but rewrite-clj never parses to it
;; so we never coerce to it either ;; so we never coerce to it either
3 :token :token 3 :token ;;:token
3N :token :token 3N :token ;;:token
3.14 :token :token 3.14 :token ;;:token
3.14M :token :token 3.14M :token ;;:token
3e14 :token :token 3e14 :token ;;:token
;; ratios are not valid in cljs ;; ratios are not valid in cljs
#?@(:clj [3/4 :token :token]) #?@(:clj [3/4 :token ;;:token
]
)
;; symbol/keyword/string/... ;; symbol/keyword/string/...
'symbol :token :symbol 'symbol :token ;;:symbol
'namespace/symbol :token :symbol 'namespace/symbol :token ;;:symbol
:keyword :token :keyword :keyword :token ;;:keyword
:1.5.1 :token :keyword :1.5.1 :token ;;:keyword
::keyword :token :keyword ::keyword :token ;;:keyword
::1.5.1 :token :keyword ::1.5.1 :token ;;:keyword
:namespace/keyword :token :keyword :namespace/keyword :token ;;:keyword
"" :token :string "" :token ;;:string
"hello, over there!" :token :string "hello, over there!" :token ;;:string
"multi\nline" :token :string "multi\nline" :multi-line ;;:string
" " :token :string " " :token ;;:string
"\n" :token :string "\n" :multi-line ;;:string
"\n\n" :token :string "\n\n" :multi-line ;;:string
"," :token :string "," :token ;;:string
"inner\"quote" :token :string
"\\s+" :token :string
;; seqs ;; seqs
[] :vector :seq [] :vector ;;:seq
[1 2 3] :vector :seq [1 2 3] :vector ;;:seq
() :list :seq () :list ;;:seq
'() :list :seq '() :list ;;:seq
(list 1 2 3) :list :seq (list 1 2 3) :list ;;:seq
#{} :set :seq #{} :set ;;:seq
#{1 2 3} :set :seq #{1 2 3} :set ;;:seq
(cons 1 [2 3]) :list :seq
(lazy-seq [1 2 3]) :list :seq
;; date ;; date
#inst "2014-11-26T00:05:23" :token :token)) #inst "2014-11-26T00:05:23" :token ;; :token
(testing "multi-line string newline variants are preserved" ))
(testing "multi-line string newline variants are normalized"
(let [s "hey\nyou\rover\r\nthere" (let [s "hey\nyou\rover\r\nthere"
n (node/coerce s)] n (node/coerce s)]
(is (= s (node/sexpr n))))) (is (= "hey\nyou\nover\nthere" (node/sexpr n))))))
(testing "coerce string roundtrip"
(is (= "\"hey \\\" man\"" (-> "hey \" man" node/coerce node/string))))
(testing "coerce string equals parsed string"
(is (= (p/parse-string "\"hello\"") (node/coerce "hello")))))
(deftest (deftest
t-quoted-list-reader-location-metadata-elided t-quoted-list-reader-location-metadata-elided
@ -91,7 +81,7 @@
(let [n (node/coerce ?sexpr)] (let [n (node/coerce ?sexpr)]
(is (node/node? n)) (is (node/node? n))
(is (= :map (node/tag n))) (is (= :map (node/tag n)))
#_(is (= :seq (protocols/node-type n))) ;; (is (= :seq protocols/node-type n))
(is (string? (node/string n))) (is (string? (node/string n)))
(is (= ?sexpr (node/sexpr n))) (is (= ?sexpr (node/sexpr n)))
;; we do not restore to original map (hash-map or array-map), ;; we do not restore to original map (hash-map or array-map),
@ -104,16 +94,27 @@
(array-map) (array-map)
(array-map :d 4 :e 5))) (array-map :d 4 :e 5)))
(deftest t-namespaced-maps-coerce-to-maps
(are [?sexpr]
(let [n (node/coerce ?sexpr)]
(is (node/node? n))
(is (= :map (node/tag n)))
;; (is (= :seq (protocols/node-type n)))
(is (string? (node/string n)))
(is (= ?sexpr (node/sexpr n)))
(is (map? (node/sexpr n))))
#:prefix {:a 1 :b 2}
#::{:c 3 :d 4}
#::p{:e 5 :f 6}))
(deftest t-sexpr->node->sexpr-roundtrip-for-regex (deftest t-sexpr->node->sexpr-roundtrip-for-regex
(are [?in] (are [?in]
(let [n (node/coerce ?in)] (let [n (node/coerce ?in)]
(is (node/node? n)) (is (node/node? n))
(is (= :regex (node/tag n))) (is (= :regex (node/tag n)))
#_(is (= :regex (protocols/node-type n))) ;; (is (= :regex (protocols/node-type n)))
(is (string? (node/string n))) (is (string? (node/string n)))
(is (= (list 're-pattern (regex/pattern-string-for-regex ?in)) #_(is (= (list 're-pattern (regex/pattern-string-for-regex ?in))
(node/sexpr n)))) (node/sexpr n))))
#"abc" #"abc"
#"a\nb\nc" #"a\nb\nc"
@ -126,7 +127,7 @@
(let [n (node/coerce #'identity)] (let [n (node/coerce #'identity)]
(is (node/node? n)) (is (node/node? n))
(is (= :var (node/tag n))) (is (= :var (node/tag n)))
(is (= :reader (protocols/node-type n))) #_(is (= :reader (protocols/node-type n)))
(is (= '(var #?(:clj clojure.core/identity :cljs cljs.core/identity)) (node/sexpr n))))) (is (= '(var #?(:clj clojure.core/identity :cljs cljs.core/identity)) (node/sexpr n)))))
(deftest t-nil (deftest t-nil
@ -152,30 +153,31 @@
(deftest t-nodes-coerce-to-themselves (deftest t-nodes-coerce-to-themselves
(testing "parsed nodes" (testing "parsed nodes"
;; lean on the parser to create node structures ;; lean on the parser to create node structures
(are [?s ?tag ?type] (are [?s ?tag #_?type]
(let [n (p/parse-string ?s)] (let [n (p/parse-string ?s)]
(is (= n (node/coerce n))) (is (= n (node/coerce n)))
(is (= ?tag (node/tag n))) (is (= ?tag (node/tag n)))
#_(is (= ?type (protocols/node-type n)))) #_(is (= ?type (protocols/node-type n))))
";; comment" :comment :comment ";; comment" :comment ;;:comment
"#! comment" :comment :comment "#! comment" :comment ;;:comment
"#(+ 1 %)" :fn :fn "#(+ 1 %)" :fn ;;:fn
":my-kw" :token :keyword ":my-kw" :token ;;:keyword
"^:m1 [1 2 3]" :meta :meta "^:m1 [1 2 3]" :meta ;;:meta
"#:p1{:a 1 :b 2}" :namespaced-map :namespaced-map "#:p1{:a 1 :b 2}" :namespaced-map ;;:namespaced-map
"'a" :quote :quote "'a" :quote ;;:quote
"#'var" :var :reader "#'var" :var ;;:reader
"#=eval" :eval :reader "#=eval" :eval ;;:reader
"@deref" :deref :deref "@deref" :deref ;;:deref
"#mymacro 44" :reader-macro :reader-macro "#mymacro 44" :reader-macro ;;:reader-macro
"#\"regex\"" :regex :regex "#\"regex\"" :regex ;;:regex
"[1 2 3]" :vector :seq "[1 2 3]" :vector ;;:seq
"42" :token :token "42" :token ;;:token
"sym" :token :symbol "sym" :token ;;:symbol
"#_ 99" :uneval :uneval "#_ 99" :uneval ;;:uneval
" " :whitespace :whitespace " " :whitespace ;;:whitespace
"," :comma :comma "," :comma ;;:comma
"\n" :newline :newline)) "\n" :newline ;;:newline
))
(testing "parsed forms nodes" (testing "parsed forms nodes"
(let [n (p/parse-string-all "(def a 1)")] (let [n (p/parse-string-all "(def a 1)")]
(is (= n (node/coerce n))) (is (= n (node/coerce n)))

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
42

View file

@ -1,111 +0,0 @@
(ns proxy-inputstream-outputstream
(:import (java.io InputStream OutputStream)
(java.nio ByteBuffer)))
;;
;; Accept a ByteBuffer and return an InputStream that reads data from
;; the given buffer.
;;
(defn buffer->input-stream ^InputStream [^ByteBuffer buffer]
(proxy [InputStream] []
(read
([]
(if (.hasRemaining buffer)
(-> (.get buffer)
(bit-and 0xff))
-1))
([b]
(.read this b 0 (alength b)))
([b off len]
(if (.hasRemaining buffer)
(let [len (min (alength b)
(.remaining buffer))]
(.get buffer b off len)
len)
-1)))))
;;
;; Accept a ByteBuffer and return an OutputStream that writes into the
;; buffer.
;;
(defn buffer->output-stream ^OutputStream [^ByteBuffer buffer]
(proxy [OutputStream] []
(write
([v]
(if (bytes? v)
(.put buffer ^bytes v)
(.put buffer (-> (Integer. v) (.byteValue)))))
([v off len]
(.put buffer ^bytes v 0 (alength v))))))
;;
;; Tests:
;;
(defn read-byte-by-byte-test []
(let [in (-> (.getBytes "Hello")
(ByteBuffer/wrap)
(buffer->input-stream))]
(and (= (.read in) (int \H))
(= (.read in) (int \e))
(= (.read in) (int \l))
(= (.read in) (int \l))
(= (.read in) (int \o))
(= (.read in) -1))))
(defn read-byte-array []
(let [in (-> (.getBytes "Hello")
(ByteBuffer/wrap)
(buffer->input-stream))
buffer (byte-array 10)
len (.read in buffer)]
(and (= len 5)
(= (String. buffer 0 len) "Hello"))))
(defn read-all []
(let [in (-> (.getBytes "Hello")
(ByteBuffer/wrap)
(buffer->input-stream))
data (.readAllBytes in)]
(= (String. data) "Hello")))
(defn write-byte-by-byte []
(let [buffer (ByteBuffer/allocate 10)
out (buffer->output-stream buffer)]
(.write out (int \H))
(.write out (int \e))
(.write out (int \l))
(.write out (int \l))
(.write out (int \o))
(= (String. (.array buffer)
0
(.position buffer))
"Hello")))
(defn write-byte-array []
(let [buffer (ByteBuffer/allocate 10)
out (buffer->output-stream buffer)]
(.write out (.getBytes "Hello"))
(= (String. (.array buffer)
0
(.position buffer))
"Hello")))
;;
;; Run all tests:
;;
(when (and (read-byte-by-byte-test)
(read-byte-array)
(read-all)
(write-byte-by-byte)
(write-byte-array))
(println ":success"))

View file

@ -1 +0,0 @@
(prn *command-line-args*)

View file

@ -1 +0,0 @@
adjacent_bb/medley.bb

View file

@ -42,11 +42,3 @@
[(async/go [(async/go
(async/<! (async/timeout 100)) (async/<! (async/timeout 100))
10)])))))"))))) 10)])))))")))))
(deftest timeout-test
(is (nil? (edn/read-string (test-utils/bb nil "
(first (async/<!!
(async/go
(async/alts!
[(async/go
(async/<! (async/timeout (int 100))))]))))")))))

View file

@ -320,7 +320,7 @@
(testing "call to run in missing dir gives 'cannot run program' message" (testing "call to run in missing dir gives 'cannot run program' message"
(test-utils/with-config (test-utils/with-config
(pr-str '{:tasks {foo (clojure {:dir "../missingdir"} "-M" "-r")}}) (pr-str '{:tasks {foo (clojure {:dir "../missingdir"} "-M" "-r")}})
;; check rough text of error message, specific message about missing directory is OS-dependent ; check rough text of error message, specific message about missing directory is OS-dependent
(is (thrown-with-msg? Exception #"Cannot run program .* \(in directory \"\.\.[/\\]missingdir\"\)" (is (thrown-with-msg? Exception #"Cannot run program .* \(in directory \"\.\.[/\\]missingdir\"\)"
(bb "run" "foo")))))) (bb "run" "foo"))))))
@ -387,7 +387,7 @@ even more stuff here\"
(try (try
(spit "uberjar" "#!/usr/bin/env bb\n(+ 1 2 3)") (spit "uberjar" "#!/usr/bin/env bb\n(+ 1 2 3)")
(vreset! common/bb-edn '{:tasks {uberjar (+ 1 2 3)}}) (vreset! common/bb-edn '{:tasks {uberjar (+ 1 2 3)}})
(is (= {:file "uberjar", :command-line-args '("--version")} (second (main/parse-opts ["uberjar" "--version"])))) (is (= "uberjar" (:file (main/parse-opts ["uberjar"]))))
(finally (fs/delete "uberjar")))))) (finally (fs/delete "uberjar"))))))
(deftest min-bb-version-test (deftest min-bb-version-test
@ -409,7 +409,7 @@ even more stuff here\"
entries (cp/split-classpath out) entries (cp/split-classpath out)
entry (first entries)] entry (first entries)]
(is (= 1 (count entries))) (is (= 1 (count entries)))
(is (= (fs/real-path (fs/parent config)) (fs/real-path (fs/parent entry)))) (is (= (fs/parent config) (fs/parent entry)))
(is (str/ends-with? entry "src")))))) (is (str/ends-with? entry "src"))))))
(deftest without-deps-test (deftest without-deps-test
@ -513,7 +513,7 @@ even more stuff here\"
(testing "default deps-root path is same as bb.edn" (testing "default deps-root path is same as bb.edn"
(let [out (bb "--config" config "cp") (let [out (bb "--config" config "cp")
entries (cp/split-classpath out)] entries (cp/split-classpath out)]
(is (= (fs/real-path(fs/parent f)) (fs/real-path (fs/parent (first entries))))))) (is (= (fs/parent f) (fs/parent (first entries))))))
(spit config (spit config
'{:paths ["src"] '{:paths ["src"]
:deps {local/dep {:local/root "local-dep"}} :deps {local/dep {:local/root "local-dep"}}
@ -523,27 +523,11 @@ even more stuff here\"
_ (spit (str (fs/file root "deps.edn")) {}) _ (spit (str (fs/file root "deps.edn")) {})
out (bb "--config" config "cp") out (bb "--config" config "cp")
entries (cp/split-classpath out)] entries (cp/split-classpath out)]
(is (= (fs/real-path (fs/parent f)) (fs/real-path (fs/parent (first entries)))))))))) (is (= (fs/parent f) (fs/parent (first entries)))))))))
(deftest adjacent-bb-edn-test (deftest adjacent-bb-edn-test
(is (= {1 {:id 1}} (bb "test-resources/adjacent_bb/medley.bb"))) (is (= {1 {:id 1}} (bb "test-resources/adjacent_bb/medley.bb")))
(is (= {1 {:id 1}} (bb "-f" "test-resources/adjacent_bb/medley.bb"))) (is (= {1 {:id 1}} (bb "-f" "test-resources/adjacent_bb/medley.bb"))))
(testing "symlink"
(is (= {1 {:id 1}} (bb (str (fs/file "test-resources" "symlink-adjacent-bb")))))))
; symlinks that resolve in the /proc fs cause fs/real-path to throw when figuring out bb.edn path (issue #1700)
(deftest redirection-test
(testing "main doesn't throw when input file symlink resolves to 'not real' file"
(when (and test-utils/native? (not test-utils/windows?))
(is (str/starts-with? (test-utils/bb "(println \"hi\")" "/dev/stdin") "hi")))))
(deftest non-existing-tasks-in-run-gives-exit-code-1 (deftest non-existing-tasks-in-run-gives-exit-code-1
(is (thrown? Exception (bb "-Sdeps" "{:tasks {foo {:task (run (quote bar))}}}" "foo")))) (is (thrown? Exception (bb "-Sdeps" "{:tasks {foo {:task (run (quote bar))}}}" "foo"))))
(deftest empty-bb-edn-test
(is (= 6 (bb "-Sdeps" "" "-e" "(+ 1 2 3)"))))
(deftest warning-on-override-task
(when-not test-utils/native?
(binding [*out* *err*]
(is (str/includes? (with-out-str (bb "-Sdeps" "{:tasks {run {:task 1}}}" "run")) "'run' override")))))

View file

@ -11,8 +11,7 @@
(-> line str/trimr (-> line str/trimr
;; take into account JDK14+ and native image differences ;; take into account JDK14+ and native image differences
(str/replace "class clojure.lang" "clojure.lang") (str/replace "class clojure.lang" "clojure.lang")
(str/replace #" \(.*\)$" "") (str/replace #" \(.*\)$" "")))
(str/replace #"--\d\d\d\d" "")))
(defmacro multiline-equals [s1 s2] (defmacro multiline-equals [s1 s2]
`(let [lines-s1# (str/split-lines ~s1) `(let [lines-s1# (str/split-lines ~s1)
@ -93,7 +92,7 @@ clojure.core// - <built-in>
foo - foo.clj:1:10")))) foo - foo.clj:1:10"))))
(deftest static-call-test (deftest static-call-test
#_(let [output (try (tu/bb nil "-e" "File/x") (let [output (try (tu/bb nil "-e" "File/x")
(catch Exception e (ex-message e)))] (catch Exception e (ex-message e)))]
(is (str/includes? (tu/normalize output) (is (str/includes? (tu/normalize output)
"----- Error -------------------------------------------------------------------- "----- Error --------------------------------------------------------------------
@ -106,11 +105,11 @@ Location: <expr>:1:1
^--- No matching field found: x for class java.io.File ^--- No matching field found: x for class java.io.File
----- Stack trace -------------------------------------------------------------- ----- Stack trace --------------------------------------------------------------
user - <expr>:1:1"))) user - <expr>:1:1"))
(let [output (try (tu/bb nil "-e" "(File/x)") (let [output (try (tu/bb nil "-e" "(File/x)")
(catch Exception e (ex-message e)))] (catch Exception e (ex-message e)))]
(is (str/includes? (tu/normalize output) (is (str/includes? (tu/normalize output)
"----- Error -------------------------------------------------------------------- "----- Error --------------------------------------------------------------------
Type: java.lang.IllegalArgumentException Type: java.lang.IllegalArgumentException
Message: No matching method x found taking 0 args Message: No matching method x found taking 0 args
Location: <expr>:1:1 Location: <expr>:1:1
@ -120,7 +119,7 @@ Location: <expr>:1:1
^--- No matching method x found taking 0 args ^--- No matching method x found taking 0 args
----- Stack trace -------------------------------------------------------------- ----- Stack trace --------------------------------------------------------------
user - <expr>:1:1")))) user - <expr>:1:1")))))
(deftest error-while-macroexpanding-test (deftest error-while-macroexpanding-test

View file

@ -11,8 +11,6 @@
(deftest exec-test (deftest exec-test
(is (= {:foo 1} (edn/read-string (bb "-x" "prn" "--foo" "1")))) (is (= {:foo 1} (edn/read-string (bb "-x" "prn" "--foo" "1"))))
(is (thrown? Exception (bb "-x" "json/generate-string" "--foo" "1"))) (is (thrown? Exception (bb "-x" "json/generate-string" "--foo" "1")))
(is (thrown-with-msg? Exception #"Could not resolve sym to a function: clojure.core/generate-string"
(bb "-x" "clojure.core/generate-string" "--foo" "1")))
(is (= {:foo 1} (cheshire/parse-string (is (= {:foo 1} (cheshire/parse-string
(edn/read-string (edn/read-string
(bb "--prn" "-x" "cheshire.core/generate-string" "--foo" "1")) true)))) (bb "--prn" "-x" "cheshire.core/generate-string" "--foo" "1")) true))))

View file

@ -1,18 +0,0 @@
(ns babashka.impl.clojure.main-test
(:require [babashka.test-utils :as tu]
[clojure.edn :as edn]
[clojure.test :as t :refer [deftest is testing]]))
(def bb
(comp edn/read-string tu/bb))
(deftest with-read-known-test
(testing ":unknown gets set to true"
(is (true? (bb nil (pr-str '(binding [*read-eval* :unknown]
(clojure.main/with-read-known *read-eval*)))))))
(testing "other values don't change"
(t/are [read-eval-value]
(= read-eval-value
(bb nil (str "(binding [*read-eval* " read-eval-value "]"
" (clojure.main/with-read-known *read-eval*))")))
false true 5)))

View file

@ -1,16 +1,14 @@
(ns babashka.impl.nrepl-server-test (ns babashka.impl.nrepl-server-test
(:require (:require
[babashka.fs :as fs]
[babashka.impl.nrepl-server :refer [start-server!]] [babashka.impl.nrepl-server :refer [start-server!]]
[babashka.main :as main]
[babashka.nrepl.server :refer [parse-opt stop-server!]] [babashka.nrepl.server :refer [parse-opt stop-server!]]
[babashka.main :as main]
[babashka.test-utils :as tu] [babashka.test-utils :as tu]
[babashka.wait :as wait] [babashka.wait :as wait]
[bencode.core :as bencode] [bencode.core :as bencode]
[clojure.test :as t :refer [deftest is testing]] [clojure.test :as t :refer [deftest is testing]]
[sci.core :as sci] [sci.core :as sci]
[sci.ctx-store :as ctx-store] [sci.ctx-store :as ctx-store])
[babashka.impl.classpath :as cp])
(:import (:import
[java.lang ProcessBuilder$Redirect])) [java.lang ProcessBuilder$Redirect]))
@ -33,9 +31,6 @@
res) res)
res (if-let [status (:sessions res)] res (if-let [status (:sessions res)]
(assoc res :sessions (mapv bytes->str status)) (assoc res :sessions (mapv bytes->str status))
res)
res (if-let [cp (:classpath res)]
(assoc res :classpath (mapv bytes->str cp))
res)] res)]
res)) res))
@ -67,11 +62,9 @@
(let [msg (read-reply in session @id) (let [msg (read-reply in session @id)
id (:id msg) id (:id msg)
versions (:versions msg) versions (:versions msg)
babashka-version (bytes->str (get versions "babashka")) babashka-version (bytes->str (get versions "babashka"))]
ops (:ops msg)]
(is (= 1 id)) (is (= 1 id))
(is (= main/version babashka-version)) (is (= main/version babashka-version))))
(is (contains? ops "classpath"))))
(testing "eval" (testing "eval"
(bencode/write-bencode os {"op" "eval" "code" "(+ 1 2 3)" "session" session "id" (new-id!)}) (bencode/write-bencode os {"op" "eval" "code" "(+ 1 2 3)" "session" session "id" (new-id!)})
(let [msg (read-reply in session @id) (let [msg (read-reply in session @id)
@ -196,19 +189,7 @@
(bencode/write-bencode os {"op" "eval" "code" "(set! *unchecked-math* true)" (bencode/write-bencode os {"op" "eval" "code" "(set! *unchecked-math* true)"
"session" session "id" (new-id!)}) "session" session "id" (new-id!)})
(let [reply (read-reply in session @id)] (let [reply (read-reply in session @id)]
(is (= "true" (:value reply))))) (is (= "true" (:value reply))))))))
(testing "classpath op"
(bencode/write-bencode os {"op" "eval" "code" "(babashka.classpath/add-classpath \"test-resources/babashka/src_for_classpath_test\")"
"session" session "id" (new-id!)})
(read-reply in session @id)
(bencode/write-bencode os {"op" "classpath"
"session" session "id" (new-id!)})
(let [reply (read-reply in session @id)
cp (:classpath reply)]
(is (every? string? cp))
(is (pos? (count cp)))
;; dev-resources doesn't exist
(is (pos? (count (filter fs/exists? cp)))))))))
(deftest ^:skip-windows nrepl-server-test (deftest ^:skip-windows nrepl-server-test
(let [proc-state (atom nil) (let [proc-state (atom nil)
@ -240,4 +221,5 @@
;;;; Scratch ;;;; Scratch
(comment) (comment
)

View file

@ -26,15 +26,15 @@
(sci/with-in-str (str expr "\n:repl/quit") (sci/with-in-str (str expr "\n:repl/quit")
(repl!)))) expected))) (repl!)))) expected)))
(defmacro assert-repl-error [expr expected] (defn assert-repl-error [expr expected]
`(is (str/includes? (is (str/includes?
(tu/normalize (tu/normalize
(let [sw# (java.io.StringWriter.)] (let [sw (java.io.StringWriter.)]
(sci/binding [sci/out (java.io.StringWriter.) (sci/binding [sci/out (java.io.StringWriter.)
sci/err sw#] sci/err sw]
(sci/with-in-str (str ~expr "\n:repl/quit") (sci/with-in-str (str expr "\n:repl/quit")
(repl!))) (repl!)))
(str sw#))) ~expected))) (str sw))) expected)))
(deftest repl-test (deftest repl-test
(assert-repl "1" "1") (assert-repl "1" "1")
@ -52,9 +52,7 @@
(assert-repl-error "(+ 1 nil)" "NullPointerException") (assert-repl-error "(+ 1 nil)" "NullPointerException")
(assert-repl-error "(/ 1 0) (pst 1)" "Divide by zero\n\tclojure.lang.Numbers") (assert-repl-error "(/ 1 0) (pst 1)" "Divide by zero\n\tclojure.lang.Numbers")
(assert-repl-error "(partition (range 5) 3)" (assert-repl-error "(partition (range 5) 3)"
"Don't know how to create ISeq from: java.lang.Long") "Don't know how to create ISeq from: java.lang.Long"))
(assert-repl "(throw (ex-info \"foo\" {:a (+ 1 2 3)})) (ex-data *e)"
"{:a 6}"))
;;;; Scratch ;;;; Scratch

View file

@ -1,20 +0,0 @@
(ns babashka.impl.server-test
(:require [babashka.test-utils :as tu]
[clojure.edn :as edn]
[clojure.test :as t :refer [deftest is testing]]))
(def bb
(comp edn/read-string tu/bb))
(deftest repl-read-test
(testing "arbitrary values can be read"
(t/are [input result]
(= result (bb input "(let [request-exit (Object.)]
(loop [acc []]
(let [v (clojure.core.server/repl-read nil request-exit)]
(if (= v request-exit)
acc
(recur (conj acc v))))))"))
"abc" '[abc]
"123 456" [123 456]
"(nil ns/symbol (true))\n (+ 1 2 3)" '[(nil ns/symbol (true)) (+ 1 2 3)])))

View file

@ -18,20 +18,11 @@
(bb nil (pr-str '(do (bb nil (pr-str '(do
(def t (Thread. (fn []))) (def t (Thread. (fn [])))
(def vt (Thread/startVirtualThread (fn []))) (def vt (Thread/startVirtualThread (fn [])))
[(.isVirtual t) (.isVirtual vt)]))))) [(.isVirtual t) (.isVirtual vt)]))))))
(is (bb nil (pr-str '(instance?
java.util.concurrent.Executor
(java.util.concurrent.Executors/newThreadPerTaskExecutor (-> (Thread/ofVirtual) (.name "fusebox-thread-" 1) (.factory))))))))
(deftest domain-sockets-test (deftest domain-sockets-test
(is (= :success (bb nil (slurp "test-resources/domain_sockets.bb"))))) (is (= :success (bb nil (slurp "test-resources/domain_sockets.bb")))))
(deftest byte-channels-test
(is (= :success (bb nil (slurp "test-resources/bytechannel_and_related_classes.bb")))))
(deftest proxy-inputstream-outputstream-test
(is (= :success (bb nil (slurp "test-resources/proxy_inputstream_outputstream.bb")))))
(deftest map-entry-create-test (deftest map-entry-create-test
(is (true? (bb nil "(= (first {1 2}) (is (true? (bb nil "(= (first {1 2})
(clojure.lang.MapEntry. 1 2) (clojure.lang.MapEntry. 1 2)
@ -50,219 +41,3 @@
(def cert (x509-certificate (io/file \"test-resources/certificate.crt\"))) (def cert (x509-certificate (io/file \"test-resources/certificate.crt\")))
(some? (.getSubjectX500Principal cert)) (some? (.getSubjectX500Principal cert))
")))) "))))
(deftest ECDH-test
(is (true? (bb nil "
(import
'[java.security KeyPairGenerator MessageDigest]
'[java.security.spec ECGenParameterSpec]
'[javax.crypto KeyAgreement]
'[javax.crypto.spec SecretKeySpec])
(def keypair-algo \"EC\")
(def keypair-curve \"secp256r1\")
(def key-agreement-algo \"ECDH\") ; Elliptic Curve Diffie-Hellman
(def key-digest-algo \"SHA-256\")
(def key-encryption-algo \"AES\")
(defn keypair
\"Generates a new key pair with the given alias, using the keypair-algo and keypair-curve\"
[]
(let [keygen (KeyPairGenerator/getInstance keypair-algo)]
(.initialize keygen (ECGenParameterSpec. keypair-curve))
(.generateKeyPair keygen)))
(defn symmetric-key
\"Generates a symmetric key using Elliptic Curve Diffie-Hellman based on a given local private and a remote public key\"
[private-key public-key]
; Derive shared secret
(let [shared-secret
(let [key-agreement (KeyAgreement/getInstance key-agreement-algo)]
(.init key-agreement private-key)
(.doPhase key-agreement public-key true)
(.generateSecret key-agreement))
symmetric-key
(let [message-digest (MessageDigest/getInstance key-digest-algo)
hash-bytes (.digest message-digest shared-secret)
key-bytes (byte-array (subvec (vec hash-bytes) 0 32))] ; extracts the first 256 bits for AES key
(SecretKeySpec. key-bytes key-encryption-algo))]
symmetric-key))
(let [[kp1 kp2] [(keypair) (keypair)]
[private public] [(.getPrivate kp1) (.getPublic kp2)]
symmetric (symmetric-key private public)]
(some? (.getAlgorithm symmetric)))
"))))
(deftest IntStream-test
(is (pos? (bb nil "(.count (.codePoints \"woof🐕\"))"))))
(deftest Thread-sleep-test
(is (bb nil "(Thread/sleep (int 1))
(Thread/sleep (java.time.Duration/ofMillis 1))
true")))
(deftest SSL-test
(is (= :user/success
(bb nil "(try (.createSocket (javax.net.ssl.SSLSocketFactory/getDefault) \"localhost\" 4444) (catch java.net.ConnectException e ::success))")))
(is (bb nil " (.startHandshake (.createSocket (javax.net.ssl.SSLSocketFactory/getDefault) \"clojure.org\" 443)) ::success")))
(deftest jio-line-number-reader-test
(is (= 2 (bb nil "(def rdr (java.io.LineNumberReader. (java.io.StringReader. \"foo\nbar\")))
(binding [*in* rdr] (read-line) (read-line)) (.getLineNumber rdr)"))))
(deftest FI-coercion
(is (true? (bb nil "(= [1 3] (into [] (doto (java.util.ArrayList. [1 2 3]) (.removeIf even?))))")))
(is (true? (bb nil "(= \"abcabc\" (.computeIfAbsent (java.util.HashMap.) \"abc\" #(str % %)))")))
(is (true? (bb nil "(= '(\\9) (-> \"a9-\" seq .stream (.filter Character/isDigit) stream-seq!))")))
(is (true? (bb nil "(require (quote [clojure.java.io :as jio])) (import [java.io File] [java.nio.file Path Files DirectoryStream$Filter]) (pos? (count (seq (Files/newDirectoryStream (.toPath (jio/file \".\"))
#(-> ^Path % .toFile .isDirectory)))))")))
(is (true? (bb nil "(import [java.util Collection] [java.util.stream Stream] [java.util.function Predicate])
(= '(100 100 100 100 100) (->> (Stream/generate (constantly 100)) stream-seq! (take 5)))")))
(is (true? (bb nil "(import [java.util Collection] [java.util.stream Stream] [java.util.function Predicate])
(= '(1 2 3 4 5 6 7 8 9 10) (->> (Stream/iterate 1 inc) stream-seq! (take 10)))"))))
(deftest regression-test
(is (true? (bb nil "(let [x \"f\"] (String/.startsWith \"foo\" x))"))))
(deftest clojure-1_12-interop-test
(is (= [1 2 3] (bb nil "(map Integer/parseInt [\"1\" \"2\" \"3\"])")))
(is (= [1 2 3] (bb nil "(map String/.length [\"1\" \"22\" \"333\"])")))
(is (= ["1" "22" "333"] (bb nil "(map String/new [\"1\" \"22\" \"333\"])")))
(is (= 3 (bb nil "(String/.length \"123\")")))
(is (= "123" (bb nil "(String/new \"123\")"))))
(deftest clojure-1_12-array-test
(is (true? (bb nil "(instance? Class long/1)"))))
(deftest keygen-test
(is (true?
(bb nil
'(do (ns keygen
(:import [java.security KeyPairGenerator Signature]))
(defn generate-key-pair
"Generates a public/private key pair."
[]
(let [keygen (KeyPairGenerator/getInstance "RSA")]
(.initialize keygen 2048)
(.generateKeyPair keygen)))
(defn create-signature
"Signs the given message using the private key."
[private-key message]
(let [signature (Signature/getInstance "SHA256withRSA")]
(.initSign signature private-key)
(.update signature (.getBytes message "UTF-8"))
(.sign signature)))
(defn verify-signature
"Verifies the given signed data using the public key."
[public-key message signed-data]
(let [signature (Signature/getInstance "SHA256withRSA")]
(.initVerify signature public-key)
(.update signature (.getBytes message "UTF-8"))
(.verify signature signed-data)))
(let [key-pair (generate-key-pair)
private-key (.getPrivate key-pair)
public-key (.getPublic key-pair)
message "This is a secret message"
signed-data (create-signature private-key message)]
(verify-signature public-key message signed-data))))))
(is (true?
(bb nil '(do (import
'[java.security KeyPairGenerator]
'[java.security.spec ECGenParameterSpec])
(def keypair-algo "EC")
(def keypair-curve "secp256r1")
(defn keypair
"Generates a new key pair with the given alias, using the keypair-algo and keypair-curve"
[]
(let [keygen (KeyPairGenerator/getInstance keypair-algo)]
(.initialize keygen (ECGenParameterSpec. keypair-curve))
(.generateKeyPair keygen)))
(let [kp (keypair)
pk (.getPublic kp)]
(bytes? (.getEncoded pk))))))))
;; RT iter test
(deftest clojure-RT-iter-test
(is (= (iterator-seq (.iterator [1 2 3]))
(bb nil '(do (ns test
(:import [clojure.lang RT]))
(iterator-seq (clojure.lang.RT/iter [1 2 3])))))))
(deftest posix-file-attributes
(when-not test-utils/windows?
(is (= 'java.util.HashSet
(bb nil
'(do
(import
[java.nio.file Files LinkOption Path]
[java.nio.file.attribute PosixFileAttributes])
(-> (Files/readAttributes (Path/of "test-resources/posix-file-attributes.txt"
(into-array String []))
PosixFileAttributes
^"[Ljava.nio.file.LinkOption;"
(into-array LinkOption []))
.permissions
type)))))))
(deftest extended-attributes
(is (true?
(bb nil
'(do
(import
[java.nio.file Files LinkOption Path]
[java.nio.file.attribute UserDefinedFileAttributeView])
(instance? UserDefinedFileAttributeView
(Files/getFileAttributeView (Path/of "test-resources/extended-attributes.txt"
(into-array String []))
UserDefinedFileAttributeView
^"[Ljava.nio.file.LinkOption;"
(into-array LinkOption []))))))))
;; exercise a sampling of the superclass resolutions from the :public-class fn in
;; babashka.impl.classes/gen-class-map
(deftest public-class-resolutions
(testing "Charset"
(is (= "UTF-8" (bb nil "(.displayName (java.nio.charset.Charset/forName \"UTF-8\"))"))))
(testing "InputStream"
(is (zero? (bb nil "(with-open [is (java.io.InputStream/nullInputStream)]
(.available is))"))))
(testing "Throwable"
; compare output from ex-message to calling .getMessage
(let [return-throwable "(try (yaml/parse-string \"abc: def: ghi\") (catch Exception e e))"]
(is (= (bb nil (str "(ex-message " return-throwable ")"))
(bb nil (str "(.getMessage " return-throwable ")"))))))
(testing "jsoup Element"
(is (= "form" (bb nil "(.tagName (first (.getElementsByTag (org.jsoup.Jsoup/parseBodyFragment \"<form></form>\") \"form\")))")))))
(deftest cached-thread-pool
(is (= 3 (bb nil "(import '(java.util.concurrent Executors ExecutorService))
(let [fut (.submit ^ExecutorService (Executors/newCachedThreadPool) ^Callable (fn [] 3))]
(.get fut))")))
(is (nil? (bb nil "(import '(java.util.concurrent Executors ExecutorService))
(let [fut (.submit ^ExecutorService (Executors/newCachedThreadPool) ^Runnable (fn [] 3))]
(.get fut))"))))
(deftest break-iterator-test
(is (= 1 (bb nil "(ns dude
(:import [java.text BreakIterator]))
(defn count-characters
[^String text]
(let [it (BreakIterator/getCharacterInstance)]
(.setText it text)
(loop [count 0]
(if (= (.next it) BreakIterator/DONE)
count
(recur (inc count))))))
(prn
(count-characters \"🇨🇦\"))"))))

View file

@ -44,7 +44,7 @@
(deftest logging-test (deftest logging-test
(let [res (tu/bb nil (pr-str program))] (let [res (tu/bb nil (pr-str program))]
(is (= 8 (count (re-seq #"\[dude:.\]" res)))) (is (= 17 (count (re-seq #"\[dude:.\]" res))))
(is (= 6 (count (re-seq #"DEBUG" res)))) (is (= 6 (count (re-seq #"DEBUG" res))))
(is (= 11 (count (re-seq #"INFO" res))))) (is (= 11 (count (re-seq #"INFO" res)))))
(testing "println appender works with with-out-str" (testing "println appender works with with-out-str"
@ -110,11 +110,3 @@
(is (= 3 (count (re-seq #"\"test warn\"" res))))) (is (= 3 (count (re-seq #"\"test warn\"" res)))))
(testing "lists are printed readably" (testing "lists are printed readably"
(is (= 2 (count (re-seq #"\(\\a \\b\)" res))))))) (is (= 2 (count (re-seq #"\(\\a \\b\)" res)))))))
(deftest timbre-log!-test
(is (str/includes? (tu/bb nil
(pr-str '(do (require '[taoensso.timbre :as timbre])
(defn log-wrapper [& args]
(timbre/log! :info :p args))
(log-wrapper "hallo"))))
"hallo")))

View file

@ -1,7 +1,6 @@
(ns babashka.main-test (ns babashka.main-test
{:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [working?]}}}} {:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [working?]}}}}
(:require (:require
[babashka.fs :as fs]
[babashka.main :as main] [babashka.main :as main]
[babashka.test-utils :as test-utils] [babashka.test-utils :as test-utils]
[clojure.edn :as edn] [clojure.edn :as edn]
@ -10,7 +9,6 @@
[clojure.string :as str] [clojure.string :as str]
[clojure.test :as test :refer [deftest is testing]] [clojure.test :as test :refer [deftest is testing]]
[flatland.ordered.map :refer [ordered-map]] [flatland.ordered.map :refer [ordered-map]]
[flatland.ordered.set :refer [ordered-set]]
[sci.core :as sci])) [sci.core :as sci]))
(defn bb [input & args] (defn bb [input & args]
@ -68,18 +66,10 @@
(is (= {:force? true :repl true} (parse-opts ["--force" "repl"]))) (is (= {:force? true :repl true} (parse-opts ["--force" "repl"])))
(is (= {:force? true :clojure true :command-line-args '("-M" "-r")} (is (= {:force? true :clojure true :command-line-args '("-M" "-r")}
(parse-opts ["--force" "clojure" "-M" "-r"]))) (parse-opts ["--force" "clojure" "-M" "-r"])))
(is (= {:command-line-args '("asdf" "fdsa")}
(main/parse-opts ["--" "asdf" "fdsa"])))
(is (= {:repl true :command-line-args '("asdf" "fdsa")}
(main/parse-opts ["repl" "--" "asdf" "fdsa"])))
(testing "file opts parsing does not mess with :command-line-args" (testing "file opts parsing does not mess with :command-line-args"
(is (= {:prn true, :expressions ["(prn :foo)"]} (is (= {:prn true, :expressions ["(prn :foo)"]}
(-> (let [[_ opts] (main/parse-file-opt ["-e" "(prn :foo)"] {})] (-> (let [opts (main/parse-file-opt ["-e" "(prn :foo)"] {})]
(main/parse-opts ["-e" "(prn :foo)"] opts))))) (main/parse-opts ["-e" "(prn :foo)"] opts)))))))
(is (= {:file "foo", :command-line-args ["README.md"]}
(main/parse-opts ["README.md"] {:file "foo"})))
(is (= ["--version"] (bb nil (fs/file "test-resources" "script_with_overlapping_opts.clj") "--version")))
(is (= ["version"] (bb nil (fs/file "test-resources" "script_with_overlapping_opts.clj") "version")))))
(deftest version-test (deftest version-test
(is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT"))) (is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT")))
@ -88,18 +78,6 @@
(is (not (main/satisfies-min-version? "300.0.0"))) (is (not (main/satisfies-min-version? "300.0.0")))
(is (not (main/satisfies-min-version? "300.0.0-SNAPSHOT")))) (is (not (main/satisfies-min-version? "300.0.0-SNAPSHOT"))))
(deftest version-opt-test
(is (str/starts-with? (test-utils/bb nil "version")
"babashka v")))
(deftest help-opt-test
(is (every? #(str/includes? (test-utils/bb nil "help") %)
["Babashka v" "Help:"])))
(deftest describe-opt-test
(is (every? (partial contains? (bb nil "describe"))
[:babashka/version :feature/yaml :feature/logging])))
(deftest print-error-test (deftest print-error-test
(is (thrown-with-msg? Exception #"java.lang.NullPointerException" (is (thrown-with-msg? Exception #"java.lang.NullPointerException"
(bb nil "(subs nil 0 0)")))) (bb nil "(subs nil 0 0)"))))
@ -492,11 +470,7 @@
(deftest command-line-args-test (deftest command-line-args-test
(is (true? (bb nil "(nil? *command-line-args*)"))) (is (true? (bb nil "(nil? *command-line-args*)")))
(is (= ["1" "2" "3"] (bb nil "*command-line-args*" "1" "2" "3"))) (is (= ["1" "2" "3"] (bb nil "*command-line-args*" "1" "2" "3"))))
(is (str/includes? (test-utils/bb "*command-line-args*" "repl" "--" "1" "2" "3")
"(\"1\" \"2\" \"3\""))
(is (str/includes? (test-utils/bb "*command-line-args*" "--" "1" "2" "3")
"(\"1\" \"2\" \"3\"")))
(deftest constructors-test (deftest constructors-test
(testing "the clojure.lang.Delay constructor works" (testing "the clojure.lang.Delay constructor works"
@ -653,8 +627,7 @@
(is (= 2 (bb nil "(set! *data-readers* {'t/tag inc}) #t/tag 1")))) (is (= 2 (bb nil "(set! *data-readers* {'t/tag inc}) #t/tag 1"))))
(deftest ordered-test (deftest ordered-test
(is (= (ordered-map :a 1 :b 2) (bb nil "(flatland.ordered.map/ordered-map :a 1 :b 2)"))) (is (= (ordered-map :a 1 :b 2) (bb nil "(flatland.ordered.map/ordered-map :a 1 :b 2)"))))
(is (= (ordered-set :a 1 :b 2) (bb nil "(flatland.ordered.set/ordered-set :a 1 :b 2)"))))
(deftest data-diff-test (deftest data-diff-test
(is (= [[nil 1] [nil 2] [1 nil 2]] (bb nil "(require '[clojure.data :as d]) (d/diff [1 1 2] [1 2 2])")))) (is (= [[nil 1] [nil 2] [1 nil 2]] (bb nil "(require '[clojure.data :as d]) (d/diff [1 1 2] [1 2 2])"))))
@ -913,14 +886,6 @@ true")))
(deftest get-watches-test (deftest get-watches-test
(is (true? (bb nil "(map? (.getWatches (doto (atom nil) (add-watch :foo (fn [k r o n])))))")))) (is (true? (bb nil "(map? (.getWatches (doto (atom nil) (add-watch :foo (fn [k r o n])))))"))))
(deftest tools-reader-test
(is (= :user/foo (bb nil "(require '[clojure.tools.reader :as r]) (r/read-string \"::foo\")")))
(is (= :clojure.tools.reader/foo (bb nil "(require '[clojure.tools.reader :as r]) (r/read-string \"::r/foo\")")))
(is (= [1 2 3] (bb nil "
(require '[clojure.tools.reader :as r])
(binding [r/*default-data-reader-fn* (fn [sym] (fn [val] [1 2 3]))]
(r/read-string \"#dude []\"))"))))
;;;; Scratch ;;;; Scratch
(comment (comment

View file

@ -153,10 +153,3 @@
(force-gc) (force-gc)
@deleted? @deleted?
"))) ")))
(deftest reify-dir-stream-filter
(is (true? (bb nil "
(defn get-dir-stream [^java.nio.file.Path dir-path glob-pattern]
(let [path (.toPath (java.io.File. dir-path))]
(java.nio.file.Files/newDirectoryStream path glob-pattern)))
(pos? (count (seq (get-dir-stream \".\" (reify java.nio.file.DirectoryStream$Filter (accept [_ path] (.isDirectory (.toFile path))))))))"))))

View file

@ -37,12 +37,8 @@
(deftest fixtures-test (deftest fixtures-test
(let [output (bb " (let [output (bb "
(require '[clojure.test :as t]) (require '[clojure.test :as t])
(defn once [f] (prn :once-before) (f) (defn once [f] (prn :once-before) (f) (prn :once-after))
(prn :once-after) (defn each [f] (prn :each-before) (f) (prn :each-after))
(prn (some? (::t/once-fixtures (meta *ns*)))))
(defn each [f] (prn :each-before) (f) (prn :each-after)
(prn (some? (::t/each-fixtures (meta *ns*)))))
(t/use-fixtures :once once) (t/use-fixtures :once once)
(t/use-fixtures :each each) (t/use-fixtures :each each)
(t/deftest foo) (t/deftest foo)
@ -52,12 +48,9 @@
:once-before :once-before
:each-before :each-before
:each-after :each-after
true
:each-before :each-before
:each-after :each-after
true :once-after")))))
:once-after
true")))))
(deftest with-test (deftest with-test
(let [output (bb " (let [output (bb "

View file

@ -2,10 +2,8 @@
(:require (:require
[babashka.fs :as fs] [babashka.fs :as fs]
[babashka.main :as main] [babashka.main :as main]
[babashka.process :refer [shell]]
[babashka.test-utils :as tu] [babashka.test-utils :as tu]
[clojure.edn :as edn] [clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as str] [clojure.string :as str]
[clojure.test :as t :refer [deftest is testing]]) [clojure.test :as t :refer [deftest is testing]])
(:import (java.io File InputStreamReader PushbackReader) (:import (java.io File InputStreamReader PushbackReader)
@ -26,13 +24,13 @@
(let [tmp-file (java.io.File/createTempFile "uber" ".jar") (let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file)] path (.getPath tmp-file)]
(.deleteOnExit tmp-file) (.deleteOnExit tmp-file)
(tu/bb nil "--classpath" "test-resources/babashka/uberjar/src" "uberjar" path "-m" "my.main-main") (tu/bb nil "--prn" "--classpath" "test-resources/babashka/uberjar/src" "uberjar" path "-m" "my.main-main")
(is (= "(\"1\" \"2\" \"3\" \"4\")\n" (is (= "(\"1\" \"2\" \"3\" \"4\")\n"
(tu/bb nil "--jar" path "1" "2" "3" "4"))) (tu/bb nil "--prn" "--jar" path "1" "2" "3" "4")))
(is (= "(\"1\" \"2\" \"3\" \"4\")\n" (is (= "(\"1\" \"2\" \"3\" \"4\")\n"
(tu/bb nil "-jar" path "1" "2" "3" "4"))) (tu/bb nil "--prn" "-jar" path "1" "2" "3" "4")))
(is (= "(\"1\" \"2\" \"3\" \"4\")\n" (is (= "(\"1\" \"2\" \"3\" \"4\")\n"
(tu/bb nil path "1" "2" "3" "4"))))) (tu/bb nil "--prn" path "1" "2" "3" "4")))))
(testing "without main, a REPL starts" (testing "without main, a REPL starts"
;; NOTE: if we choose the same tmp-file as above and doing this all in the ;; NOTE: if we choose the same tmp-file as above and doing this all in the
;; same JVM process, the below test fails because my.main-main will be the ;; same JVM process, the below test fails because my.main-main will be the
@ -51,9 +49,9 @@
;; building with no --classpath ;; building with no --classpath
(tu/bb nil "uberjar" path "-m" "my.main-main") (tu/bb nil "uberjar" path "-m" "my.main-main")
;; running ;; running
(is (= "(\"42\")\n" (tu/bb nil "--jar" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil "--prn" "--jar" path "-m" "my.main-main" "42")))
(is (= "(\"42\")\n" (tu/bb nil "--classpath" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil "--prn" "--classpath" path "-m" "my.main-main" "42")))
(is (= "(\"42\")\n" (tu/bb nil path "42")))))) (is (= "(\"42\")\n" (tu/bb nil "--prn" path "42"))))))
(testing "ignore empty entries on classpath" (testing "ignore empty entries on classpath"
(let [tmp-file (java.io.File/createTempFile "uber" ".jar") (let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file) path (.getPath tmp-file)
@ -80,15 +78,3 @@
(is (= #{:pods} (-> bb-edn keys set))) (is (= #{:pods} (-> bb-edn keys set)))
(is (= (:pods config) (:pods bb-edn)))) (is (= (:pods config) (:pods bb-edn))))
(is (str/includes? (tu/bb nil "--prn" "--jar" path) "3"))))))) (is (str/includes? (tu/bb nil "--prn" "--jar" path) "3")))))))
(deftest uberjar-as-binary-test
(when tu/native?
(let [tmp-file (java.io.File/createTempFile "uber" ".jar")
path (.getPath tmp-file)
bin-file (if (fs/windows?) "my-binary.exe" "my-binary")]
(.deleteOnExit tmp-file)
(.deleteOnExit (io/file bin-file))
(tu/bb nil "--classpath" "test-resources/babashka/uberjar/src" "uberjar" path "-m" "my.main-main")
(shell {:out bin-file} "cat" "./bb" path)
(.setExecutable (io/file bin-file) true)
(is (str/includes? (:out (shell {:out :string} (str (io/file "." bin-file)) "1 2 3 4")) "1 2 3 4")))))

View file

@ -1,7 +1,7 @@
(ns babashka.xml-test (ns babashka.xml-test
(:require [babashka.test-utils :as test-utils] (:require [babashka.test-utils :as test-utils]
[clojure.string :as str] [clojure.string :as str]
[clojure.test :refer [deftest is]])) [clojure.test :refer [deftest is testing]]))
(def simple-xml-str "<a><b>data</b></a>") (def simple-xml-str "<a><b>data</b></a>")
@ -15,22 +15,3 @@
(deftest xml-data-readers-test (deftest xml-data-readers-test
(is (str/includes? (test-utils/bb nil round-trip-prog) simple-xml-str))) (is (str/includes? (test-utils/bb nil round-trip-prog) simple-xml-str)))
(deftest virtual-threads-bug-test
(is (str/starts-with? (test-utils/bb nil "(require '[clojure.core.async]
'[clojure.data.xml])
(def go-blocks (atom []))
(dotimes [_ 100]
(swap! go-blocks conj (clojure.core.async/go (clojure.data.xml/parse
(java.io.ByteArrayInputStream.
(.getBytes \"<a></a>\" \"UTF-8\"))
:namespace-aware false
:skip-whitespace true))))
(doseq [block @go-blocks]
(clojure.core.async/<!! block))
true")
"true")))