diff --git a/src/clj/new/clj_template.clj b/src/clj/new/clj_template.clj index 4cd17e1..40e0196 100644 --- a/src/clj/new/clj_template.clj +++ b/src/clj/new/clj_template.clj @@ -30,14 +30,31 @@ (with-bindings {#'clj.new.templates/*force?* force #'clj.new.templates/*dir* dir} - (file-map->files - data - {"deps.edn" (render "deps.edn" data) - (format "src/%s/%s.clj" (:base data) (:suffix data)) (render "core.clj" data) - (format "src/%s/python.clj" (:base data)) (render "python.clj" data)})))) + (let [lpc-path ".clj-kondo/configs/libpython-clj" + tp-path ".clj-kondo/configs/tech.parallel"] + (file-map->files + data + {"deps.edn" (render "deps.edn" data) + (format "src/%s/%s.clj" (:base data) (:suffix data)) (render "core.clj" data) + (format "src/%s/python.clj" (:base data)) (render "python.clj" data) + ;; clj-kondo hooks related + ".clj-kondo/config.edn" + (render ".clj-kondo/config.edn" data) + ;; libpython_clj + (str lpc-path "/config.edn") + (render (str lpc-path "/config.edn") data) + (str lpc-path "/hooks/libpython_clj/jna/base/def_pylib_fn.clj") + (render (str lpc-path "/hooks/libpython_clj/jna/base/def_pylib_fn.clj") data) + (str lpc-path "/hooks/libpython_clj/require/import_python.clj") + (render (str lpc-path "/hooks/libpython_clj/require/import_python.clj") data) + ;; tech.parallel + (str tp-path "/config.edn") + (render (str tp-path "/config.edn") data) + (str tp-path "/hooks/tech/parallel/utils/export_symbols.clj") + (render (str tp-path "/hooks/tech/parallel/utils/export_symbols.clj") data)}))))) -(defn clj-template +(defn clj-template ([name] (libpython-clj-template! name)) ([name & args] (clj-template name))) diff --git a/src/clj/new/libpython_clj/.clj-kondo/config.edn b/src/clj/new/libpython_clj/.clj-kondo/config.edn new file mode 100644 index 0000000..b950f91 --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/config.edn @@ -0,0 +1,3 @@ +{ + :config-paths ["configs/libpython-clj" "configs/tech.parallel"] +} diff --git a/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/config.edn b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/config.edn new file mode 100644 index 0000000..9109c86 --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/config.edn @@ -0,0 +1,14 @@ +{ + :hooks + {:analyze-call {libpython-clj.jna.base/def-pylib-fn + hooks.libpython-clj.jna.base.def-pylib-fn/def-pylib-fn + libpython-clj.require/import-python + hooks.libpython-clj.require.import-python/import-python}} + :linters {:unused-namespace {:exclude [builtins.list + builtins.dict + builtins.set + builtins.tuple + builtins.frozenset + builtins.str + builtins]}} +} diff --git a/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/jna/base/def_pylib_fn.clj b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/jna/base/def_pylib_fn.clj new file mode 100644 index 0000000..bac1e09 --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/jna/base/def_pylib_fn.clj @@ -0,0 +1,83 @@ +;; XXX: work on export-symbols from tech.parallel.utils? +(ns hooks.libpython-clj.jna.base.def-pylib-fn + "The def-pylib-fn macro from libpython-clj/jna/base.clj" + (:require [clj-kondo.hooks-api :as api])) + +;; from: libpython-clj/jna/base.clj + +;; (defmacro def-pylib-fn +;; [fn-name docstring rettype & argpairs] +;; `(defn ~fn-name +;; ~docstring +;; ~(mapv first argpairs) +;; (when-not (== (current-thread-id) (.get ^AtomicLong gil-thread-id)) +;; (throw (Exception. "Failure to capture gil when calling into libpython"))) +;; (let [~'tvm-fn (jna/find-function ~(str fn-name) *python-library*) +;; ~'fn-args (object-array +;; ~(mapv (fn [[arg-symbol arg-coersion]] +;; (when (= arg-symbol arg-coersion) +;; (throw (ex-info (format "Argument symbol (%s) cannot match coersion (%s)" +;; arg-symbol arg-coersion) +;; {}))) +;; `(~arg-coersion ~arg-symbol)) +;; argpairs))] +;; ~(if rettype +;; `(.invoke (jna-base/to-typed-fn ~'tvm-fn) ~rettype ~'fn-args) +;; `(.invoke (jna-base/to-typed-fn ~'tvm-fn) ~'fn-args))))) + +;; called like: + +;; (def-pylib-fn PyImport_AddModule +;; "Return value: Borrowed reference. +;; +;; Similar to PyImport_AddModuleObject(), but the name is a UTF-8 encoded string instead +;; of a Unicode object." +;; Pointer +;; [name str]) + +(defn def-pylib-fn + "Macro in libpython-clj/jna/base.clj. + + Example call: + + (def-pylib-fn PyImport_AddModule + \"Return value: Borrowed reference. + + Similar to PyImport_AddModuleObject(), but the name is a UTF-8 ... + of a Unicode object.\" + Pointer + [name str]) + + This has the form: + + (def-pylib-fn fn-name docstring rettype & argpairs) + + May be treating it as: + + (defn fn-name + [arg1 arg2 ,,, argn] + [arg1 arg2 ,,, argn]) ; fake usage of args? + + where arg1, ..., argn are extracted from argpairs is acceptable. + + XXX: using the second elements of argpairs might be worth doing + to avoid unused warnings. + + " + [{:keys [:node]}] + (let [[_ fn-name _ _ & argpairs] (:children node) + pairs (map (fn [vec-node] + (let [[an-arg a-type] (:children vec-node)] + [an-arg a-type])) + argpairs) + new-node (with-meta (api/list-node + (apply concat + [(api/token-node 'defn) + fn-name + (api/vector-node (map first pairs))] + pairs)) + (meta node))] + ;; XXX: uncomment following and run clj-kondo on cl_format.clj to debug + ;;(prn (api/sexpr node)) + ;;(prn (api/sexpr new-node)) + {:node new-node})) diff --git a/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/require/import_python.clj b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/require/import_python.clj new file mode 100644 index 0000000..c6089d3 --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/configs/libpython-clj/hooks/libpython_clj/require/import_python.clj @@ -0,0 +1,75 @@ +(ns hooks.libpython-clj.require.import-python + "The import-python macro from libpython-clj/require.clj" + (:require [clj-kondo.hooks-api :as api])) + +;; from: libpython-clj/require.clj + +;; (defn import-python +;; "Loads python, python.list, python.dict, python.set, python.tuple, +;; and python.frozenset." +;; [] +;; (require-python +;; '(builtins +;; [list :as python.list] +;; [dict :as python.dict] +;; [set :as python.set] +;; [tuple :as python.tuple] +;; [frozenset :as python.frozenset] +;; [str :as python.str]) +;; '[builtins :as python]) +;; :ok) + +;; alternative: +;; +;; (require +;; (quote [builtins.list :as python.list]) +;; (quote [builtins.dict :as python.dict]) +;; (quote [builtins.set :as python.set]) +;; (quote [builtins.tuple :as python.tuple]) +;; (quote [builtins.frozenset :as python.frozenset]) +;; (quote [builtins.str :as python.str]) +;; (quote [builtins :as python])) + +(defn make-require + [ns-sym alias-sym] + (api/list-node + [(api/token-node 'require) + (api/list-node + [(api/token-node 'quote) + (api/vector-node + [(api/token-node ns-sym) + (api/keyword-node :as) + (api/token-node alias-sym)])])])) + +(defn import-python + "Macro in libpython-clj/require.clj. + + Example call: + + (import-python) + + May be treating it as: + + (do + (require (quote [builtins.list :as python.list])) + (require (quote [builtins.dict :as python.dict])) + ,,, + ) + + " + [{:keys [:node]}] + (let [new-node + (with-meta (api/list-node + [(api/token-node 'do) + (make-require 'builtins.list 'python.list) + (make-require 'builtins.dict 'python.dict) + (make-require 'builtins.set 'python.set) + (make-require 'builtins.tuple 'python.tuple) + (make-require 'builtins.frozenset 'python.frozenset) + (make-require 'builtins.str 'python.str) + (make-require 'builtins 'python)]) + (meta node))] + ;; XXX: uncomment following and run clj-kondo on cl_format.clj to debug + ;;(prn (api/sexpr node)) + ;;(prn (api/sexpr new-node)) + {:node new-node})) diff --git a/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/config.edn b/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/config.edn new file mode 100644 index 0000000..5ece7be --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/config.edn @@ -0,0 +1,4 @@ +{ + :hooks {:analyze-call {tech.parallel.utils/export-symbols + hooks.tech.parallel.utils.export-symbols/export-symbols}} +} diff --git a/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/hooks/tech/parallel/utils/export_symbols.clj b/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/hooks/tech/parallel/utils/export_symbols.clj new file mode 100644 index 0000000..bd4477a --- /dev/null +++ b/src/clj/new/libpython_clj/.clj-kondo/configs/tech.parallel/hooks/tech/parallel/utils/export_symbols.clj @@ -0,0 +1,77 @@ +(ns hooks.tech.parallel.utils.export-symbols + "The export-symbols macro from tech/parallel/utils.clj" + (:require [clj-kondo.hooks-api :as api])) + +;; from: tech/parallel/utils.clj + +;; (defmacro export-symbols +;; [src-ns & symbol-list] +;; `(do +;; (require '~src-ns) +;; ~@(->> symbol-list +;; (mapv +;; (fn [sym-name] +;; `(let [varval# (requiring-resolve (symbol ~(name src-ns) +;; ~(name sym-name))) +;; var-meta# (meta varval#)] +;; (when (:macro var-meta#) +;; (throw +;; (ex-info +;; (format "Cannot export macros as this breaks aot: %s" +;; '~sym-name) +;; {:symbol '~sym-name}))) +;; (def ~(symbol (name sym-name)) @varval#) +;; (alter-meta! #'~(symbol (name sym-name)) +;; merge +;; (select-keys var-meta# +;; [:file :line :column +;; :doc +;; :column :tag +;; :arglists])))))))) + +(defn export-symbols + "Macro in tech/parallel/utils.clj. + + Example call: + + (export-symbols libpython-clj.jna.base + find-pylib-symbol + as-pyobj + ensure-pyobj) + + This has the form: + + (export-symbols ns-name var-name-1 var-name-2 ... var-name-n) + + May be treating it as: + + (do + (def var-name-1 ns-name/var-name-1) + (def var-name-2 ns-name/var-name-2) + ,,, + (def var-name-n ns-name/var-name-n)) + + is acceptable. + + Thanks lread :) + + " + [{:keys [:node]}] + (let [[_ ns-node & var-nodes] (:children node) + new-node (api/list-node + (conj + (doall + (for [var-node var-nodes + :let [var-sym (api/sexpr var-node) + var-fq (str (api/sexpr ns-node) "/" var-sym)]] + (with-meta + (api/list-node + [(api/token-node 'def) + (api/token-node (symbol var-sym)) + (api/token-node (symbol var-fq))]) + (meta var-node)))) + (api/token-node 'do)))] + ;; XXX: uncomment following and run clj-kondo on cl_format.clj to debug + ;;(prn (api/sexpr node)) + ;;(prn (api/sexpr new-node)) + {:node new-node}))