Browse Source

First version

stephen@centriqhome.com 2 years ago
parent
commit
f9f877550a
6 changed files with 178 additions and 14 deletions
  1. 9
    9
      .gitignore
  2. 4
    4
      LICENSE
  3. 23
    1
      README.md
  4. 24
    0
      project.clj
  5. 76
    0
      src/defenv/core.clj
  6. 42
    0
      test/defenv/core_test.clj

+ 9
- 9
.gitignore View File

@@ -1,13 +1,13 @@
1
+/target
2
+/classes
3
+/checkouts
1 4
 pom.xml
2 5
 pom.xml.asc
3 6
 *.jar
4 7
 *.class
5
-/lib/
6
-/classes/
7
-/target/
8
-/checkouts/
9
-.lein-deps-sum
10
-.lein-repl-history
11
-.lein-plugins/
12
-.lein-failures
13
-.nrepl-port
8
+/.lein-*
9
+/.nrepl-port
10
+.hgignore
11
+.hg/
12
+/.idea/
13
+/defenv.iml

+ 4
- 4
LICENSE View File

@@ -1,7 +1,7 @@
1 1
                     GNU GENERAL PUBLIC LICENSE
2 2
                        Version 3, 29 June 2007
3 3
 
4
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5 5
  Everyone is permitted to copy and distribute verbatim copies
6 6
  of this license document, but changing it is not allowed.
7 7
 
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
645 645
     GNU General Public License for more details.
646 646
 
647 647
     You should have received a copy of the GNU General Public License
648
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
648
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
649 649
 
650 650
 Also add information on how to contact you by electronic and paper mail.
651 651
 
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
664 664
   You should also get your employer (if you work as a programmer) or school,
665 665
 if any, to sign a "copyright disclaimer" for the program, if necessary.
666 666
 For more information on this, and how to apply and follow the GNU GPL, see
667
-<http://www.gnu.org/licenses/>.
667
+<https://www.gnu.org/licenses/>.
668 668
 
669 669
   The GNU General Public License does not permit incorporating your program
670 670
 into proprietary programs.  If your program is a subroutine library, you
671 671
 may consider it more useful to permit linking proprietary applications with
672 672
 the library.  If this is what you want to do, use the GNU Lesser General
673 673
 Public License instead of this License.  But first, please read
674
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
674
+<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 23
- 1
README.md View File

@@ -1,2 +1,24 @@
1 1
 # defenv
2
-A simple library allowing one to work with environment variables easily in Clojure
2
+
3
+A Clojure library designed to make working with environment variables easier.
4
+
5
+## Usage
6
+
7
+For example usage, check out `test/defenv/core_test.clj`
8
+
9
+## License
10
+
11
+Copyright © 2018 Stephen Starkey
12
+
13
+This program is free software: you can redistribute it and/or modify
14
+it under the terms of the GNU General Public License as published by
15
+the Free Software Foundation, either version 3 of the License, or
16
+(at your option) any later version.
17
+
18
+This program is distributed in the hope that it will be useful,
19
+but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+GNU General Public License for more details.
22
+
23
+You should have received a copy of the GNU General Public License
24
+along with this program.  If not, see <http://www.gnu.org/licenses/>.

+ 24
- 0
project.clj View File

@@ -0,0 +1,24 @@
1
+;
2
+;     This file is part of defenv.
3
+;
4
+;     defenv is free software: you can redistribute it and/or modify
5
+;     it under the terms of the GNU General Public License as published by
6
+;     the Free Software Foundation, either version 3 of the License, or
7
+;     (at your option) any later version.
8
+;
9
+;     defenv is distributed in the hope that it will be useful,
10
+;     but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+;     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+;     GNU General Public License for more details.
13
+;
14
+;     You should have received a copy of the GNU General Public License
15
+;     along with defenv.  If not, see <http://www.gnu.org/licenses/>.
16
+;
17
+
18
+(defproject coreagile/defenv "0.0.1"
19
+  :description "A simple library for managing environment variables in Clojure"
20
+  :url "https://github.com/coreagile/defenv"
21
+  :license {:name "GNU General Public License v3"
22
+            :url "https://www.gnu.org/licenses/gpl.html"}
23
+  :min-lein-version "2.0.0"
24
+  :dependencies [[org.clojure/clojure "1.8.0"]])

+ 76
- 0
src/defenv/core.clj View File

@@ -0,0 +1,76 @@
1
+;
2
+;     This file is part of defenv.
3
+;
4
+;     defenv is free software: you can redistribute it and/or modify
5
+;     it under the terms of the GNU General Public License as published by
6
+;     the Free Software Foundation, either version 3 of the License, or
7
+;     (at your option) any later version.
8
+;
9
+;     defenv is distributed in the hope that it will be useful,
10
+;     but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+;     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+;     GNU General Public License for more details.
13
+;
14
+;     You should have received a copy of the GNU General Public License
15
+;     along with defenv.  If not, see <http://www.gnu.org/licenses/>.
16
+;
17
+
18
+(ns defenv.core
19
+  (:require [clojure.string :as str]))
20
+
21
+(def defined-env (atom []))
22
+
23
+(defn- env-or [env-key f]
24
+  (let [val (System/getenv env-key)]
25
+    (if-not val (f) val)))
26
+
27
+(declare env)
28
+
29
+(defn- render-docs [{:keys [e-name doc default]}]
30
+  (let [e-val (env e-name default)]
31
+    (format "%s = %s%s" e-name (if e-val e-val "*MISSING*")
32
+            (if doc (str " ;; " doc) ""))))
33
+
34
+(defn make-usage-string
35
+  "Display nice documentation telling folks which environment variables need
36
+   to be set, and what the current values are."
37
+  []
38
+  (let [env-docs (map render-docs @defined-env)]
39
+    (str "One or more environment variables is missing:\n"
40
+         (str/join "\n" env-docs))))
41
+
42
+(defn- throw-usage [] (throw (ex-info (make-usage-string) {})))
43
+
44
+(defn env
45
+  "Attempt to retrieve an environment variable. If no default value is set
46
+   and the variable is not present, an exception will be thrown displaying
47
+   which variables are missing and which are set."
48
+  ([env-key] (env-or env-key throw-usage))
49
+  ([env-key default-value] (env-or env-key #(identity default-value))))
50
+
51
+(defn nilsafe-parse-int
52
+  "Given a String, if nonempty, attempt to parse it as an Integer."
53
+  [s] (when s (Integer/parseInt s)))
54
+
55
+(defn nilsafe-parse-double
56
+  "Given a String, if nonempty, attempt to parse it as a Double."
57
+  [s] (when s (Double/parseDouble s)))
58
+
59
+(defmacro defenv
60
+  "Define a binding to an environment variable. Creates a delayed object
61
+   that, when dereferenced, will load an environment variable of the given
62
+   key. If ':default {value}' shows up in the params, will send back the
63
+   given value if the variable isn't defined. If ':tfn {function}' shows up
64
+   in the params, runs the given function against the result of the environment
65
+   variable load, which is by default a string. If you add a :doc keyword,
66
+   it will be displayed whenever someone is missing the environment variable
67
+   as helpful documentation to display to the user."
68
+  [b env-name & {:keys [default tfn] :as params}]
69
+  (let [has-param? (partial contains? params)
70
+        tfn (if (has-param? :tfn) tfn 'identity)
71
+        env-args [env-name]
72
+        env-args (if (has-param? :default) (conj env-args default) env-args)
73
+        params-to-display (-> params (dissoc :tfn) (assoc :e-name env-name))]
74
+    `(do
75
+       (swap! defined-env conj ~params-to-display)
76
+       (def ~b (delay (~tfn (env ~@env-args)))))))

+ 42
- 0
test/defenv/core_test.clj View File

@@ -0,0 +1,42 @@
1
+;
2
+;     This file is part of defenv.
3
+;
4
+;     defenv is free software: you can redistribute it and/or modify
5
+;     it under the terms of the GNU General Public License as published by
6
+;     the Free Software Foundation, either version 3 of the License, or
7
+;     (at your option) any later version.
8
+;
9
+;     defenv is distributed in the hope that it will be useful,
10
+;     but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+;     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
+;     GNU General Public License for more details.
13
+;
14
+;     You should have received a copy of the GNU General Public License
15
+;     along with defenv.  If not, see <http://www.gnu.org/licenses/>.
16
+;
17
+
18
+(ns defenv.core-test
19
+  (:require [clojure.test :refer :all]
20
+            [defenv.core :refer :all])
21
+  (:import (clojure.lang ExceptionInfo)))
22
+
23
+(defenv log-level "LOG_LEVEL" :doc "Global log level." :tfn keyword
24
+        :default "info")
25
+(defenv thing "THING")
26
+(defenv amount "AMOUNT" :doc "An amount. A double." :tfn nilsafe-parse-double
27
+        :default "1.5")
28
+(defenv another "ANOTHER" :doc "This is really important!")
29
+
30
+(def expected-message
31
+  (str "One or more environment variables is missing:\n"
32
+       "LOG_LEVEL = info ;; Global log level.\n"
33
+       "THING = *MISSING*\n"
34
+       "AMOUNT = 1.5 ;; An amount. A double.\n"
35
+       "ANOTHER = *MISSING* ;; This is really important!"))
36
+
37
+(deftest usage
38
+  (is (= expected-message (make-usage-string)))
39
+  (is (= 1.5 @amount))
40
+  (is (thrown? ExceptionInfo @thing))
41
+  (is (= expected-message
42
+         (try @thing (catch ExceptionInfo e (.getMessage e))))))