babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
2020-09-28T05:58:34.051900Z

is there a way to package bb + the clojure script for windows users?

2020-09-28T05:59:07.052700Z

currently using cat config.edn | ./app.clj with #!/usr/bin/env bb -I

borkdude 2020-09-28T06:37:11.054900Z

@danieltanfh95 I think only macOS takes args in env. For standalone scripts it might be better to just use edn/read

2020-09-28T06:37:24.055100Z

oh

2020-09-28T06:37:49.055700Z

lemme try with my windows machine later

2020-09-28T08:01:39.056300Z

btw did anyone manage to integrate spec with babashka?

borkdude 2020-09-28T08:03:24.057100Z

@danieltanfh95 For now there is: https://github.com/borkdude/spartan.spec There are some reservations about including spec into bb, although it can work. The hesitation is because spec is alpha.

2020-09-28T08:03:48.057500Z

nice

borkdude 2020-09-28T08:04:11.058Z

You can post some feedback on that here: https://github.com/borkdude/babashka/issues/558

2020-09-28T08:04:46.058800Z

im using edn instead of command line args, it’s easier to do complex arguments with it, especially if spec is available

borkdude 2020-09-28T08:05:34.059Z

I've also done that for carve: https://github.com/borkdude/carve

👀 1
🦜 1
borkdude 2020-09-28T08:06:10.059900Z

spec will be at one point part of babashka, but only when it's out of alpha probably

borkdude 2020-09-28T08:06:45.060300Z

until then spartan.spec will be a drop-in replacement

2020-09-28T09:02:07.061700Z

Out of curiosity, I’m looking at the code of https://github.com/borkdude/cpm and wondering how it works. It says it’s piggiebacking on tools.deps, but in the code I don’t see this connection. Is this already there?

borkdude 2020-09-28T09:08:21.063100Z

@jeroenvandijk My thinking was that dependencies between packages could be done via Git deps instead of implementing dep resolution ourselves. Also it uses the classpath to discover packages. But maybe it will just be simpler if cpm will be a standalone binary with a packages repo similar to brew

borkdude 2020-09-28T09:08:34.063400Z

I now added a --global option: https://github.com/borkdude/cpm/#global

2020-09-28T09:11:23.063800Z

Cool, yeah I haven’t thought about it enough. I believe a package manager would definitely be useful to grow babashka. I’m guessing this is coming from a need to organize pods as well?

2020-09-28T09:12:31.064Z

Anyway, I also read it is work in progress. So don’t mind me, was just curious 🙂

borkdude 2020-09-28T09:12:36.064200Z

That was the initial inspiration yes

2020-09-28T09:13:41.064400Z

Nice

borkdude 2020-09-28T09:21:54.064900Z

You can now also install a SNAPSHOT babashka version using CPM: https://github.com/borkdude/cpm/#babashka

borkdude 2020-09-28T09:25:15.065200Z

which is kind of meta, since you need a SNAPSHOT version to run CPM with bb :)

🤘 1
borkdude 2020-09-28T09:30:19.065900Z

I guess I could also add a SNAPSHOT version of clj-kondo. Hmm, this could be nice for people who want to be on the latest bleeding edge ;)

borkdude 2020-09-28T09:40:25.066100Z

To package things up nicely, use babashka's --uberjar option:

$ bb -cp src:packages -m cpm.main --uberjar cpm.jar
This uberjar contains all packages from the classpath. You can then run it from anywhere on your system:
$ bb -jar cpm.jar --install clj-kondo/clj-kondo --global --verbose

2020-09-28T10:01:04.066800Z

I just noticed 🙂 Nice though!

➜  ~ bb -jar cpm.jar --install clj-kondo/clj-kondo --global --verbose
----- Error --------------------------------------------------------------------
Type:     clojure.lang.ExceptionInfo
Message:  Unable to resolve classname: java.util.zip.ZipInputStream
Location: /Users/jeroen/.gitlibs/libs/borkdude.cpm/borkdude.cpm/bf8b8e284382ee7c9fa180d6db15595b54f25bbe/src/cpm/impl/impl.clj:34:13
Phase:    analysis

2020-09-28T10:01:23.067Z

And I did this

export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {borkdude.cpm {:git/url "<https://github.com/borkdude/cpm>" :sha "bf8b8e284382ee7c9fa180d6db15595b54f25bbe"}}}' -Spath)"

borkdude 2020-09-28T10:11:21.067200Z

Yes, this is why you need the snapshot version :)

1
borkdude 2020-09-28T10:13:39.067500Z

which you can install with clojure

borkdude 2020-09-28T10:18:36.067700Z

Btw, do keep the feedback coming and do use it (maybe only for dev now), this is the only way it will improve over time

👍 1
borkdude 2020-09-28T10:51:51.068200Z

Hm, I guess cpm can also be used to install individual babashka (or clojure / whatever) scripts on the path

2020-09-28T10:51:56.068300Z

works!

clj -Sdeps '{:deps {borkdude.cpm {:git/url "<https://github.com/borkdude/cpm>" :sha "bf8b8e284382ee7c9fa180d6db15595b54f25bbe"}}}' -m cpm.main --install clj-kondo/clj-kondo --global --verbose

2020-09-28T10:55:04.069600Z

How would it work? Something like #/usr/bin/env bb + additions to babashka stdlib that can add stuff to the classpath?

borkdude 2020-09-28T10:55:43.070500Z

Well, e.g. deps.clj is a standalone script with a bb shebang. If I would package that in up a zip, then it would be no different from installing a binary

borkdude 2020-09-28T10:56:02.070900Z

It does depend on bb so maybe that would have to be added as a dependency as well

borkdude 2020-09-28T10:57:12.071400Z

bb already has a stdlib thing to add stuff to the classpath, but I don't see how that is relevant here? for some specific scripts yes

borkdude 2020-09-28T10:58:12.071800Z

So then the script would maybe add :package/depends [org.babashka/babashka] and that package will be installed as well

borkdude 2020-09-28T10:59:21.072Z

https://github.com/borkdude/cpm/issues/7

2020-09-28T11:00:00.072500Z

cool, sounds great 🙂

2020-09-28T11:00:42.073200Z

I guess a bit like how you can add binaries via ruby gems? (maybe also in python via pip, not sure)

borkdude 2020-09-28T11:01:41.073800Z

clojure -M -m cpm.main --install borkdude/deps.clj --global --verbose
will effectively do:
clojure -M -m cpm.main --install borkdude/deps.clj org.babashka/babashka --global --verbose

borkdude 2020-09-28T11:02:34.074Z

if deps.clj depends on babashka

borkdude 2020-09-28T11:02:40.074200Z

so then you will have bb on your global path as well

2020-09-28T11:03:47.075200Z

ah cool, so do i understand correctly that cpm would wrap deps + babashka? So calling cpm would allow fetching all deps and then run a main ?

borkdude 2020-09-28T11:04:33.075700Z

no. it doesn't wrap anything. it can install deps and babashka, that's all

borkdude 2020-09-28T11:04:53.076Z

after that you can run deps.clj, the script.

borkdude 2020-09-28T11:05:55.076400Z

cpm doesn't run programs, it's just a package manager that can put binaries (or scripts) on your path

borkdude 2020-09-28T11:06:20.076800Z

just like brew basically

borkdude 2020-09-28T11:06:23.077Z

but cross platform

borkdude 2020-09-28T11:06:44.077800Z

and possibly using clojure for scripting if you need to move things around after fetching the artifacts

2020-09-28T11:07:21.078400Z

ah i see. So you meant the executable could be a babashka script and because of it’s defined deps those will also be available in that shell session. I think i get it ☺️

borkdude 2020-09-28T11:07:53.078800Z

yes

borkdude 2020-09-28T11:08:25.079400Z

so if you don't have bb installed, but you install deps.clj (as a bb script, not the binary deps), then it will also make sure bb will be installed, so you can run the script

2020-09-28T11:09:18.079600Z

very cool

2020-09-28T11:09:59.080400Z

I see now that’s more ~/.cpm/path gives binary paths. I think it’s clear now 🙂

2020-09-28T11:10:07.080600Z

nice idea

borkdude 2020-09-28T11:11:33.081200Z

yes, and you can add:

# cpm
export PATH="`cat $HOME/.cpm/path 2&gt;/dev/null`:$PATH"
in your .zshenv or whatever and those executables will be available in all your shells

2020-09-28T11:15:06.082300Z

would that also pick up new binaries just after installing it via cpm? I’m guessing brew adds symlinks to /usr/local/bin for that reason

borkdude 2020-09-28T11:15:28.082800Z

yes, if you use --global it will overwrite that path file

borkdude 2020-09-28T11:15:37.083Z

you will need to reload your shell though

2020-09-28T11:15:52.083400Z

yeah i meant that part. Might not be an issue

borkdude 2020-09-28T11:15:57.083600Z

I'm not sure about working with symlinks, since I also want to support Windows

2020-09-28T11:16:16.084Z

True, probably better to wait for some feedback

borkdude 2020-09-28T11:16:26.084200Z

it's a minor issue as I see it now

borkdude 2020-09-28T11:17:07.085Z

maybe a tiny bash function could be added and that can be called post-install

borkdude 2020-09-28T11:17:20.085200Z

I'm sure there's a way to fix it

2020-09-28T11:17:26.085400Z

I agree

borkdude 2020-09-28T11:23:21.085800Z

alias cpm_path='export PATH="`cat $HOME/.cpm/path 2&gt;/dev/null`:$PATH"'
cpm_path
and then run cpm_path again post-install

2020-09-28T11:24:36.085900Z

don't typical shells have a rehashing command usually so you don't have to reload? something like this: https://superuser.com/questions/490983/how-to-rehash-executables-in-path-with-bash

2020-09-28T11:24:51.086300Z

it's not always called rehash iiuc

borkdude 2020-09-28T11:25:13.086800Z

(can be improved by first removing the old cpm_path from the path)

borkdude 2020-09-28T11:25:54.086900Z

could be but the way cpm is set up now is that the path is added via a file

borkdude 2020-09-28T11:26:01.087100Z

there are no global symlinks, etc

borkdude 2020-09-28T11:27:38.088Z

We could also make main return a bash command (using a --bash) flag so you can use source (and --powershell, etc), not sure if that's useful. Will wait with that.

2020-09-28T11:32:09.088400Z

Cool 🙂

2020-09-28T11:41:26.090400Z

If I understand correctly the current distribution method is via maven? Are you considering adding git repos? Maybe useful for being able to add (babashka) gists?

borkdude 2020-09-28T11:41:57.090900Z

can you be more specific?

2020-09-28T11:42:42.092100Z

yeah i was thinking of creating a gist and being able to call (+ install) it as an executable? From the install instructions I’m thinking it’s not possible (yet). It seems the script is currently made to download a zipfile?

borkdude 2020-09-28T11:43:42.093200Z

- cpm.edn files are currently read from the classpath. I am considering also supporting .cpm/packages/your-packages so you can git clone your package repository there. - yes, it currently only fetches zip files, I want to add tar.gz, possibly other things as well

borkdude 2020-09-28T11:44:03.093500Z

maybe it's already possible to download a gist as a zip file from github

borkdude 2020-09-28T11:44:45.093900Z

yep, there is a "Download zip" button

2020-09-28T11:48:26.095400Z

ah cool, so the current way would be to add it manually or add it via in repository dir of the cpm repo. And you are consider having personal packages

2020-09-28T11:48:42.095800Z

I’m thinking out loud 😊

borkdude 2020-09-28T11:49:14.096600Z

the current way is to have a jeroenvandijk/my-cool-gist.cpm.edn file on your classpath (either bb classpath or clojure classpath)

👌 1
borkdude 2020-09-28T11:49:54.097200Z

cpm/packages is also on the classpath because packages is in :paths in deps.edn

2020-09-28T11:55:16.097600Z

It sounds like the sky is the limit 😎

borkdude 2020-09-28T11:56:32.097800Z

😎

borkdude 2020-09-28T12:05:41.098600Z

Maybe for installing things like GraalVM we need to add some more stuff, e.g. when unzipping it, you will get a directory structure in which the binaries are not on the top level, so we need to expose a couple of paths instead of just the top level

borkdude 2020-09-28T12:06:30.099100Z

And maybe having aliases for binaries would also be nice in case of conflicts

tzzh 2020-09-28T13:01:28.103700Z

Hey, I am trying to pass a function from a pod to another client side function from a pod but that’s causing issue as it can’t be serialized

(require '[pod.tzzh.a :as a])

(a/do-something-client-side a/some-pod-fn)
and I am getting Cannot JSON encode object of class: class babashka.pods.impl$bencode__GT_vars$fn__15573$fn__15577: babashka.pods.impl$bencode__GT_vars$fn__15573$fn__15577@1142c9ef0

borkdude 2020-09-28T13:02:25.104600Z

correct, you can't pass functions through pod borders

tzzh 2020-09-28T13:03:43.105800Z

ah ok I see thanks :thumbsup: I can work around it but I would have thought that client-side functions didn’t need to serialize their args / speak to the pod

borkdude 2020-09-28T13:04:47.107Z

this example (a/do-something-client-side a/some-pod-fn) should work purely client side, if a/do-something-client-side was for example defined as (def do-something-client-side identity) but it appears like you are passing a function object back to the pod or vice versa

borkdude 2020-09-28T13:05:30.107400Z

everything that goes back to the pod or comes from the pod has to be serializable

borkdude 2020-09-28T13:05:47.107900Z

you could work around it using symbols or macros

borkdude 2020-09-28T13:06:17.108600Z

'a/some-pod-fn or (defmacro client-side [fn-sym])

tzzh 2020-09-28T13:06:53.109300Z

OK cool I will take another look thanks

borkdude 2020-09-28T13:07:08.109700Z

but I wouldn't know why you would pass back a pod function itself to the pod?

borkdude 2020-09-28T13:07:31.109900Z

more concrete example will likely help

borkdude 2020-09-28T13:07:37.110100Z

afk for an hour, will check back then

tzzh 2020-09-28T13:15:14.112700Z

OK yeah basically it’s for the aws pod I was trying to improve the pagination and lazily load pages so I have now a new namespace that exposes this client code:

(defn paginator-fn
      "Returns a fn that lazily fetches the pages for a given aws fn"
      [page-fn]
      (fn get-pages
        [input]
        (lazy-seq
          (let [page (page-fn input)]
            (if-let [next-continuation-token (:NextContinuationToken page)]
              (cons page (get-pages (assoc input :ContinuationToken next-continuation-token)))
              [page])))))
so you could do
(require '[babashka.pods])
(babashka.pods/load-pod ["./pod-tzzh-aws"])
(require '[pod.tzzh.paginator :as p])
(require '[pod.tzzh.s3 :as s3])

(let [paginator (p/paginator-fn s3/list-objects-v2)]
    (paginator {:Bucket "some-bucket"
                :Delimiter "/"
                :Prefix "some-prefix"
                :MaxKeys 50}))

borkdude 2020-09-28T13:16:34.113600Z

ah yes, then simply make that (p/paginator-fn 's3/list-objects-v2) or write p/paginator-fn as a macro so you can pass it as a symbol and expand to (p/paginator-fn* 's3/list-objects-v2)

borkdude 2020-09-28T13:17:30.113900Z

hmm, I'm not sure if I understand still

borkdude 2020-09-28T13:17:46.114200Z

is (p/paginator-fn s3/list-objects-v2) running entirely client side?

borkdude 2020-09-28T13:18:19.114500Z

yeah, that should work I think

borkdude 2020-09-28T13:19:46.115700Z

running only (p/paginator-fn s3/list-objects-v2) does that work without error?

tzzh 2020-09-28T13:20:25.116Z

no that’s the one that’s throwing an error

borkdude 2020-09-28T13:20:40.116300Z

I need to see your pod branch for more info

borkdude 2020-09-28T13:20:43.116500Z

back in an hour

borkdude 2020-09-28T13:23:29.116900Z

so if you could post me the link by then, that'll be great

borkdude 2020-09-28T13:31:54.118200Z

@thomas.ormezzano A test case: define a client side pod fn as (defn foo [f x] (f x)) and call it from bb as (foo inc 1). This should not communicate with the pod at all, and should return 2

tzzh 2020-09-28T13:35:08.119Z

OK I’ll try that, I have also pushed my branch https://github.com/tzzh/pod-tzzh-aws/pull/2

tzzh 2020-09-28T13:39:19.119500Z

clojure.lang.ExceptionInfo: Cannot JSON encode object of class: class clojure.core$inc: clojure.core$inc@112957440

tzzh 2020-09-28T13:42:43.120400Z

do I still need name when using code when describing the namespace ?

borkdude 2020-09-28T14:19:11.120800Z

@thomas.ormezzano which bb version are you using?

tzzh 2020-09-28T14:19:35.121Z

v0.2.0

borkdude 2020-09-28T14:20:26.121200Z

that should be ok

borkdude 2020-09-28T14:21:18.121600Z

can you push your branch with the foo function added?

tzzh 2020-09-28T14:24:42.121800Z

:thumbsup: done

borkdude 2020-09-28T14:40:56.122100Z

@thomas.ormezzano I added a test for this at babashka pods and it works as expected: https://github.com/babashka/babashka.pods

borkdude 2020-09-28T14:41:59.123400Z

Maybe it's a capitalization issue?

borkdude 2020-09-28T14:42:09.123800Z

bb pods expect the json to be "code"

tzzh 2020-09-28T14:42:14.124100Z

OK thanks for checking I must have messed up somewhere I’ll try to have a deeper look when I have a bit more time

borkdude 2020-09-28T14:42:30.124500Z

or wait, maybe it's an issue in JSON decoding in bb pods... I haven't tested that case

borkdude 2020-09-28T14:42:59.124800Z

neh, it's in bencode, should be the same

borkdude 2020-09-28T14:43:46.125300Z

Can you print the JSON that is generated by the go code?

borkdude 2020-09-28T14:44:09.125500Z

bencode / json

borkdude 2020-09-28T14:45:59.126800Z

hmm, you could try to run your pod using the babashka.pods library on the JVM and insert some debugging

borkdude 2020-09-28T14:46:03.127100Z

to see what is coming through

tzzh 2020-09-28T14:46:43.127700Z

ok it’s definetely the serialisation not working, basically if I have Code string “code” then it works but the other Vars get an empty string

borkdude 2020-09-28T14:47:07.128Z

aha

tzzh 2020-09-28T15:00:46.128600Z

ok fixed it now 🎉 thanks a lot for the help

borkdude 2020-09-28T15:01:13.128800Z

🎉

tzzh 2020-09-28T15:39:32.134400Z

ok so for anybody that might be using the pod I have open https://github.com/tzzh/pod-tzzh-aws/pull/2/files which would allow to have better pagination as the pages would be loaded lazily, I also want to remove the current .*-pages fn, e.g s3/list-objects-v2-pages as the pod is still very new and they wouldn’t be useful anymore with the new pagination. If anybody is using the pod and is not happy with this let me know.

👍 1
borkdude 2020-09-28T15:43:12.135300Z

I think considering the age of this project, some breakage would be ok. As a safe step you could undocument the things you want to remove and then remove it later

borkdude 2020-09-28T15:44:01.135600Z

Also keeping a CHANGELOG.md with breaking changes would help users

👍 1
richiardiandrea 2020-09-28T16:58:54.138200Z

Hi there i am a babashka newbie...I wonder what I can do to make a clojure lib working...for instance this one? http://clojuremongodb.info/ I tried to hook it up in the classpath but got an error back

borkdude 2020-09-28T17:01:02.139600Z

@richiardiandrea bb is only able to interpret a selected set of Java classes (e.g. if joda time is used in that lib, bb can't handle it) and not all Clojure constructs (notably deftype is currently missing) So currently there's no way you can run that library from source in bb.

richiardiandrea 2020-09-28T17:01:49.140700Z

oh i see, so the Java class needs to be in bb for it to work...basically any wrapper is a bit out of luck?

borkdude 2020-09-28T17:01:49.140800Z

unless you write a pod and compile that library with GraalVM to something native, that could work, but that's work, not out the box

richiardiandrea 2020-09-28T17:01:57.141Z

I see

borkdude 2020-09-28T17:02:26.141700Z

@richiardiandrea A full list of currently supported classes: https://github.com/borkdude/babashka/blob/master/src/babashka/impl/classes.clj

richiardiandrea 2020-09-28T17:05:19.142300Z

I will inspect the pod documentation, thank you Borkdude for the prompt answers

borkdude 2020-09-28T17:08:33.144Z

@richiardiandrea Sure! Shelling out to another CLI is also an often utilized technique: https://github.com/DarinDouglass/clj-psql

👍 1
borkdude 2020-09-28T17:08:59.145Z

But I do have a postgres sql pod as well: https://github.com/babashka/babashka-sql-pods/

mathpunk 2020-09-28T17:09:19.145400Z

I'm not getting quite the output that I expect --- check this out:

$ echo "hello there lets repunctuate"|bb -io '(spit "foo" (str/replace *input* " " ":"))'
$ cat foo                                                                                           
("hello:there:lets:repunctuate")

mathpunk 2020-09-28T17:09:40.145600Z

missing output flag maybe?

mathpunk 2020-09-28T17:11:19.146Z

hm, the presence or absence of the o flag has no effect on this

mathpunk 2020-09-28T17:12:29.146400Z

$ echo "hello there lets repunctuate"|bb -i '(type (str/replace *input* " " ":"))'             
java.lang.String

mathpunk 2020-09-28T17:12:44.146700Z

:thinking_face:

richiardiandrea 2020-09-28T17:13:18.146900Z

this is a good idea, in my case I would shell to either mongo or rabbitadmin 😉

borkdude 2020-09-28T17:43:36.147600Z

@mathpunk

$ echo "hello there lets repunctuate" | bb -io '(type *input*)'
clojure.lang.Cons
$ echo "hello there lets repunctuate" | bb -io '(str/replace (first *input*) " " ":")'
hello:there:lets:repunctuate
*input* is a seq of lines, unless you use --stream

mathpunk 2020-09-28T17:45:37.148500Z

huh! I guess I expected str/replace to throw an error, rather than returning something that looked a lot like it had been executed on a string

borkdude 2020-09-28T17:46:37.148800Z

yeah, I guess that function is pretty forgiving:

user=&gt; (clojure.string/replace 1 "1" "2")
"2"

mathpunk 2020-09-28T17:50:42.149100Z

just a very chill, accepting function

mathpunk 2020-09-28T17:50:49.149400Z

thanks for the help!

unbalanced 2020-09-28T20:17:01.149900Z

ran into an uberscript error. I assume this is the same issue of only certain Java classes work right now?

$ bb -cp $(clj -Spath):src -m templatus.core --uberscript templatus.clj
rlwrap: warning: Your terminal 'dumb' is not fully functional, expect some problems.

warnings can be silenced by the --no-warnings (-n) option
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  Unable to resolve classname: java.util.regex.Matcher
Location: clostache/parser.clj:1:1

----- Context ------------------------------------------------------------------
1: (ns clostache.parser
   ^--- Unable to resolve classname: java.util.regex.Matcher
2:   "A parser for mustache templates."
3:   (:use [clojure.string :only (split)]
4:         [clojure.core.incubator :only (seqable?)])
5:   (:require [<http://clojure.java.io|clojure.java.io> :as io]
6:             [clojure.string  :as str])

borkdude 2020-09-28T20:24:49.150300Z

@goomba which bb version is this

unbalanced 2020-09-28T20:27:35.150500Z

good question

unbalanced 2020-09-28T20:27:59.151100Z

$ bb --version
babashka v0.2.0

borkdude 2020-09-28T20:32:26.151400Z

Are you trying to make an uberscript for non-bb usage?

borkdude 2020-09-28T20:48:14.151600Z

@goomba?

borkdude 2020-09-28T20:56:20.152400Z

The next error you will hit using this project is:

Message:  Could not resolve symbol: clojure.lang.Reflector/invokeConstructor
Location: clojure/core/incubator.clj:73:4
73:   (clojure.lang.Reflector/invokeConstructor
       ^--- Could not resolve symbol: clojure.lang.Reflector/invokeConstructor
74:    (clojure.lang.RT/classForName class-name)
So maybe forking the project and using bb reader conditionals may work

borkdude 2020-09-28T21:00:11.153Z

@goomba if you're looking for a templating library, this one works with bb: https://github.com/weavejester/comb

borkdude 2020-09-28T21:01:23.153900Z

if your goal was to simply create an uberscript that you can run with clojure on the JVM: I can likely improve the uberscript feature by just ignoring classes in namespace forms

unbalanced 2020-09-28T22:03:30.154600Z

@borkdude thanks for the feedback. The Babashka runtime is the goal or I could just run it with clj. I l'll look into comb, thank you for the feedback!