Issue
read-attributes is a clojure-friendly version of read-attributes*.
But... while read-attributes will accept a class for attributes arg, read-attributes* will fail if this is done.
Repro
Setup:
(require '[babashka.fs :as fs])
(spit "foo" "foo")
I can get the basic file attributes with read-file-attributes* via class, like so:
(fs/read-attributes* "foo" java.nio.file.attribute.BasicFileAttributes)
;; => #object[sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes 0x7f082a4b "sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes@7f082a4b"]
The equivalent via string attributes:
(fs/read-attributes* "foo" "basic:*")
;; => {"lastAccessTime" #object[java.nio.file.attribute.FileTime 0x815f84b "2026-04-13T15:15:36.252890688Z"], "lastModifiedTime" #object[java.nio.file.attribute.FileTime 0x72ee0f3d "2026-04-13T15:15:36.252890688Z"], "size" 3, "creationTime" #object[java.nio.file.attribute.FileTime 0x335df4df "2026-04-13T15:15:36.252890688Z"], "isSymbolicLink" false, "isRegularFile" true, "fileKey" #object[sun.nio.fs.UnixFileKey 0x2434f0ef "(dev=802,ino=20868808)"], "isOther" false, "isDirectory" false}
(notice the return value changes to map when fetching via string, this is an underlying JDK API thing).
Now when I move to read-attributes, I can use a string attribute:
(fs/read-attributes "foo" "basic:*")
;; => {:creationTime
;; #object[java.nio.file.attribute.FileTime 0x4e91e01e "2026-04-13T15:15:36.252890688Z"],
;; :isSymbolicLink false,
;; :isOther false,
;; :lastAccessTime
;; #object[java.nio.file.attribute.FileTime 0x592c0ff5 "2026-04-13T15:15:36.252890688Z"],
;; :isRegularFile true,
;; :size 3,
;; :lastModifiedTime
;; #object[java.nio.file.attribute.FileTime 0x6bd67295 "2026-04-13T15:15:36.252890688Z"],
;; :fileKey #object[sun.nio.fs.UnixFileKey 0xa637dac "(dev=802,ino=20868808)"],
;; :isDirectory false}
But... when I try read-attributes with a class attribute, it fails:
(fs/read-attributes "foo" java.nio.file.attribute.BasicFileAttributes)
;; => Execution error (IllegalArgumentException) at babashka.fs/read-attributes (fs.cljc:917).
;; Don't know how to create ISeq from: sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes
Observation
Neither read-attributes nor read-attributes* mentions supported types for attributes args, but the implementation supports both string and class variants.
I guess that most folks would pass in a string attribute? It seems the more clojure-friendly option.
As for the differing return values, would a bb fs user ever prefer/need the class variant that the class attribute returns over the map that basic:* returns?
Option 0: Do nothing
Assume folks will be using string attributes.
Pros:
Cons:
Option 1: Document read-attributes and read-attributes* accept string attributes arg
Leave the class attributes args as an undocumented/unsupported feature.
Pros:
- documents common/recommended use case
Option 2: Document attributes arg types and returns for read-attributes* and read-attributes
For read-attributes this would mean documenting that we only suport a string attributes arg.
For read-attributes* this would mean documenting string and class attributes arg. And their effect on return value type.
Pros:
- describes implementations
Cons:
- more to read/understand for users
Option 3: Support class attributes arg for read-attributes
Pros:
- Symmetry
read-attributes* and read-attributes
Cons:
- I don't think this would be easy, as I don't see JDK support for conversion.
Proposal
If we assume that bb fs users would prefer to specify attributes as a string and have no real need for a class version of attributes (over the map variant), then I think Option 1: doc string attributes arg only makes sense.
What do you think?
Issue
read-attributesis a clojure-friendly version ofread-attributes*.But... while
read-attributeswill accept a class forattributesarg,read-attributes*will fail if this is done.Repro
Setup:
I can get the basic file attributes with
read-file-attributes*via class, like so:The equivalent via string
attributes:(notice the return value changes to map when fetching via string, this is an underlying JDK API thing).
Now when I move to
read-attributes, I can use a stringattribute:But... when I try
read-attributeswith a class attribute, it fails:Observation
Neither
read-attributesnorread-attributes*mentions supported types forattributesargs, but the implementation supports both string and class variants.I guess that most folks would pass in a string
attribute? It seems the more clojure-friendly option.As for the differing return values, would a bb fs user ever prefer/need the class variant that the class
attributereturns over the map thatbasic:*returns?Option 0: Do nothing
Assume folks will be using string
attributes.Pros:
Cons:
Option 1: Document
read-attributesandread-attributes*accept stringattributesargLeave the class
attributesargs as an undocumented/unsupported feature.Pros:
Option 2: Document
attributesarg types and returns forread-attributes*andread-attributesFor
read-attributesthis would mean documenting that we only suport a stringattributesarg.For
read-attributes*this would mean documenting string and classattributesarg. And their effect on return value type.Pros:
Cons:
Option 3: Support class
attributesarg forread-attributesPros:
read-attributes*andread-attributesCons:
Proposal
If we assume that bb fs users would prefer to specify
attributesas a string and have no real need for a class version of attributes (over the map variant), then I think Option 1: doc stringattributesarg only makes sense.What do you think?