Skip to content

Commit

Permalink
Allow None for optional bools
Browse files Browse the repository at this point in the history
  • Loading branch information
notmgsk committed Dec 29, 2020
1 parent 251383c commit 9b31725
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 19 deletions.
24 changes: 19 additions & 5 deletions src-tests/suite.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,22 @@
:required t
:default "a string"
:documentation "String docs.")

(flt
:type :float
:required t
:default 0.0
:documentation "A float."))


:documentation "A float.")
(optional-bool-none
:type :bool
:required nil)
(optional-bool-false
:type :bool
:required nil
:default nil)
(optional-bool-true
:type :bool
:required nil
:default t))
:documentation "Test message")

(let ((m (make-instance 'my-msg :required-int 5)))
Expand All @@ -66,7 +74,13 @@
(is (string= (gethash "yo" (my-msg-optional-map m)) "working"))
(is (= (length (gethash "suite" rpcq::*messages*)) 1))
(is (typep (my-msg-flt m) 'double-float))
(is (string= (my-msg-str m) "a string"))))
(is (string= (my-msg-str m) "a string"))
(is (typep (my-msg-optional-bool-none m) 'optional-bool))
(is (eql (my-msg-optional-bool-none m) ':none))
(is (typep (my-msg-optional-bool-true m) 'optional-bool))
(is (my-msg-optional-bool-true m))
(is (typep (my-msg-optional-bool-false m) 'optional-bool))
(is (null (my-msg-optional-bool-false m)))))

(deftest test-prepare-rpc-call-args ()
(loop
Expand Down
3 changes: 1 addition & 2 deletions src/core-messages.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -898,8 +898,7 @@
True - Relay closed, allows flux current to flow.\
False - Relay open, no flux current can flow."
:type :bool
:required nil
:default nil))
:required nil))

:documentation "Configuration for a single QFD Channel.")

Expand Down
1 change: 1 addition & 0 deletions src/package.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@
#:rpc-protocol-error
#:rpc-protocol-error-id
#:rpc-protocol-error-object
#:optional-bool
))
22 changes: 12 additions & 10 deletions src/rpcq-python.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
(let ((*python-types* *python-instance-check-types*))
(python-type field-type)))

(defun python-argspec-default (field-type default)
"Translate DEFAULT values for immutable objects of a given
FIELD-TYPE to python."
(defun python-argspec-default (field-type default &optional defaultp)
"Translate DEFAULT values for immutable objects of a given FIELD-TYPE to python.
DEFAULTP indicates whether DEFAULT has a value of NIL because NIL was provided in the DEFMESSAGE (T), or because it was missing in the DEFMESSAGE (NIL)."
(typecase field-type
((eql :string)
(if default
Expand All @@ -60,9 +61,10 @@ FIELD-TYPE to python."
(format nil "b~S" (to-string default))
"None"))
((eql :bool)
(if default
"True"
"False"))
(cond
((not defaultp) "None")
(default "True")
(t "False")))
((eql :integer)
(if default
(format nil "~d" default)
Expand Down Expand Up @@ -207,11 +209,10 @@ else:
(required (getf field-settings ':required))
(documentation (getf field-settings ':documentation))
(defaultp (member ':default field-settings))
(default (or (getf field-settings ':default)))
(default (getf field-settings ':default))
(deprecated (getf field-settings ':deprecated))
(deprecates (getf field-settings ':deprecates))
(deprecated-by (getf field-settings ':deprecated-by)))

;; optional fields automatically acquire a NIL default
(unless (or required defaultp)
(setf default nil)
Expand All @@ -228,7 +229,7 @@ else:
(push (list slot-name nil required "None") deprecated-fields)))
;; recipe for a deprecating slot
(deprecates
(let ((definite-default (python-argspec-default type default)))
(let ((definite-default (python-argspec-default type default (member ':default field-settings))))
(python-out `((" ~a: ~a = ~a" ,(symbol-name slot-name)
,(python-maybe-optional-typing-type type t)
,definite-default)
Expand All @@ -238,7 +239,8 @@ else:
(defaultp
(python-out `((" ~a: ~a = ~a" ,(symbol-name slot-name)
,(python-maybe-optional-typing-type type required)
,(python-argspec-default type default))
,(python-argspec-default type default
(member ':default field-settings)))
(" \"\"\"~a\"\"\"" ,documentation))))
;; recipe for a slot otherwise
(t
Expand Down
19 changes: 17 additions & 2 deletions src/rpcq.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ The input strings are assumed to be FORMAT-compatible, so sequences like ~<newli
(stream
(%deserialize (messagepack:decode-stream payload))))))

(deftype optional-bool ()
"An optional boolean value includes the extra None value, specific to Python."
`(or null
boolean
(eql :none)))

(defun slot-type-and-initform (field-type required default)
"Translate a FIELD-TYPE to a Lisp type and initform taking into account
whether the field is REQUIRED and a specified DEFAULT value.
Expand Down Expand Up @@ -216,6 +222,7 @@ We distinguish between the following options for any field type:
- if a value is not provided, then a fallback value is used
- you can explicitly pass None/null/NIL for this field
"
(check-type required optional-bool)
(cond

;; handle :string :integer :float :bool :bytes
Expand All @@ -226,7 +233,7 @@ We distinguish between the following options for any field type:
:bytes (simple-array (unsigned-byte 8))
:integer fixnum
:float double-float
:bool boolean
:bool optional-bool
:any t)
field-type))
;; make sure the default value (if defined) is coerced
Expand Down Expand Up @@ -317,6 +324,12 @@ LIMITATIONS:
"-"
(snake-to-kebab (symbol-name slot-name))))

(defaultify (default defaultp field-type)
(cond
(defaultp default)
((eql field-type ':bool) ':none)
(t nil)))

(make-slot-spec (field-spec)
(let*
((slot-name (car field-spec))
Expand All @@ -325,7 +338,9 @@ LIMITATIONS:
(required (getf field-settings ':required))
(documentation (getf field-settings ':documentation))
(defaultp (member ':default field-settings))
(default (getf field-settings ':default))
(default (defaultify (getf field-settings ':default)
defaultp
field-type))
(deprecated (getf field-settings ':deprecated))
(deprecates (getf field-settings ':deprecates))
(deprecated-by (getf field-settings ':deprecated-by)))
Expand Down

0 comments on commit 9b31725

Please sign in to comment.