From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp12.migadu.com ([2001:41d0:403:478a::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id SHmAIkwWG2W0dgAAauVa8A:P1 (envelope-from ) for ; Mon, 02 Oct 2023 21:13:16 +0200 Received: from aspmx1.migadu.com ([2001:41d0:403:478a::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp12.migadu.com with LMTPS id SHmAIkwWG2W0dgAAauVa8A (envelope-from ) for ; Mon, 02 Oct 2023 21:13:16 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id EC74154DCE for ; Mon, 2 Oct 2023 21:13:15 +0200 (CEST) Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gmail.com header.s=20230601 header.b=JwtUrZjH; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none) ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1696273996; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:resent-cc:resent-from:resent-sender: resent-message-id:in-reply-to:in-reply-to:references:references: list-id:list-help:list-unsubscribe:list-subscribe:list-post: dkim-signature; bh=y1tCF0Q4l6sCtxpqP3uX3tRZ8WmvuSaiZvJxLARp7ME=; b=QHktvMiyY8wi1l0x8d0OTPRdBD1x56UpZTmMjIQvq2/4FyGn6L1rN64KIgjmcUusg3XlCH TpV4Mezsc+PCkYXYf5NfiIksd9QeHVtHgfJURtOmH82XBC9+JyvdT0kxW7MBzEVt6sMV/U y2sFOeU16rU9SRv3R8VdK2+Xdd1CTqSwJkNcMzMdKD+C7cfwQoDAl0XCAq769k8T7G8+sz XypxVMuweIKzeSEfFU3wsiGMbIMsgvylzReAa9+PDuqzBEDvOi2A3ES/W0ZntFWNHFrACQ KuYvEsa7b6zzWiEOaAvzXyDzWt/zyrdiUqVsBMDsGMQG2AJ6xk7IGtzvy53FPA== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1696273996; a=rsa-sha256; cv=none; b=ZK7L4KbNIFNjLbS2gnioU9Y8Sms3bb7XX4bHtrtka1LKkWSzKMHERQAbeCxWP+7wRTvS+E CUmUskB6m6Npn0I34tRyeoQtTwz/GCsyAybt6Enm1+wtp+++CoSjoXEEEJJYsBqTdULULg f3tiCgijaQZOLprIk0YVy07sQvE5HSgp1OOq4mEW7BRWNU6I0/xoF5fGzjtPZfwvjKwsjR 6Dm/9n/6Sl31Jmh2tyvhuMtzdCJwQb55cNlqcnUlSmfpkwHUqy3YbYW6xA2WmO81ydQisL xaQex4+keBDS1/q4l5YlXRTpq7ZPgjMHidHr39rsc/hMolszu+OwYHNkouGXgA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gmail.com header.s=20230601 header.b=JwtUrZjH; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=none) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qnOLZ-0000Mu-80; Mon, 02 Oct 2023 15:12:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qnOLW-0000LA-7w for guix-patches@gnu.org; Mon, 02 Oct 2023 15:12:46 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qnOLV-0001wp-Kr for guix-patches@gnu.org; Mon, 02 Oct 2023 15:12:45 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qnOLl-0004BT-Sk for guix-patches@gnu.org; Mon, 02 Oct 2023 15:13:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#63985] [PATCH RFC 0/5] Generic INI serializer & SRFI-171 for define-configuration Resent-From: Maxim Cournoyer Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 02 Oct 2023 19:13:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 63985 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: Bruno Victal Cc: 63985@debbugs.gnu.org Received: via spool by 63985-submit@debbugs.gnu.org id=B63985.169627396416058 (code B ref 63985); Mon, 02 Oct 2023 19:13:01 +0000 Received: (at 63985) by debbugs.gnu.org; 2 Oct 2023 19:12:44 +0000 Received: from localhost ([127.0.0.1]:38003 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qnOLT-0004Av-BO for submit@debbugs.gnu.org; Mon, 02 Oct 2023 15:12:44 -0400 Received: from mail-qv1-xf32.google.com ([2607:f8b0:4864:20::f32]:59613) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qnOLR-0004Ag-49 for 63985@debbugs.gnu.org; Mon, 02 Oct 2023 15:12:42 -0400 Received: by mail-qv1-xf32.google.com with SMTP id 6a1803df08f44-65af1037ca8so696156d6.2 for <63985@debbugs.gnu.org>; Mon, 02 Oct 2023 12:12:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1696273938; x=1696878738; darn=debbugs.gnu.org; h=mime-version:user-agent:message-id:in-reply-to:date:references :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=y1tCF0Q4l6sCtxpqP3uX3tRZ8WmvuSaiZvJxLARp7ME=; b=JwtUrZjH27hjxR314aMhCcCpmtG7ksAuQUi1wDlslm+nGfiA5I6RhcdT3o38vRYINX EjuQ4GmSm3l+Go7tFUIiQUnRgs2v7FttlH65H0GKC5WvsSdOentp26/fADV6cVwdban2 t+qwbMsvxXh7DG5YFlzoZHs+QHixKSEbMexi4adQgm0f0YN6EECt7hwAowhtJo1W5QS7 DRHdnSat87BBDtDBFicSh9NLfQU46wLiI+mNWHu84q0RXJFeuafVVyacQkMrZvF8H2gi f2xlUSjSvbmKOuCAB8cNFl5+xV/LkowvfblsOHFIXRXscCT31xLbNFSIwPadalKjKfot Ul/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696273938; x=1696878738; h=mime-version:user-agent:message-id:in-reply-to:date:references :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=y1tCF0Q4l6sCtxpqP3uX3tRZ8WmvuSaiZvJxLARp7ME=; b=H2sambUwZbFZh0Rh2AHRkPvUdniXFLlntmlFuOc0Qn5tHHmSG1rTU4iMxmeYl4w+qf N6IDHvK7DOiLjz8SzfolN8ZVW4kIeJEDdIcjMXIbXIguHSclvNqfxWeXoe7e8nQa49TE nzMQtLESyqybmCe1gBHLoa6QZ1cf2dW2CJrNWBxtffNtocXJBFXjzJ+dnwdbFDRhmj0/ DXFBNgDzHsdVYnouBpWPq+q5mFXNPIdKuIaTL6A3Fg26RryHg6883GcEDDKg7ZILRO5S UpQU8bYi4cjAza0Rpai6W8UxV3AX+VO3DcA7k67E5ZRO6V9GJQbaBpRZ/TstJmxqG89v 7GGg== X-Gm-Message-State: AOJu0Ywxmk3C4Ul0VSITgyfJ62GY/WHSkAC6GZ7pFbGxWkkt2pzJn0tI oHO4lQnTD8wfzKnY8Yjhk84mTmQPDII= X-Google-Smtp-Source: AGHT+IHAv7Tj9BDNq1aMQilvUcAUUxQcQ0vXRKwWUQWYkd6bCrEuNsxknYRaq1NpQ/a9glZbjsulLg== X-Received: by 2002:a0c:f0c7:0:b0:65d:145e:310f with SMTP id d7-20020a0cf0c7000000b0065d145e310fmr12359416qvl.43.1696273938228; Mon, 02 Oct 2023 12:12:18 -0700 (PDT) Received: from hurd (dsl-10-136-90.b2b2c.ca. [72.10.136.90]) by smtp.gmail.com with ESMTPSA id w17-20020a0cdf91000000b0064c9f754794sm7963054qvl.86.2023.10.02.12.12.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Oct 2023 12:12:17 -0700 (PDT) From: Maxim Cournoyer References: <3ff11bf98a7658400615305609654432a4f30bb0.1687816734.git.mirai@makinata.eu> Date: Mon, 02 Oct 2023 15:12:16 -0400 In-Reply-To: <3ff11bf98a7658400615305609654432a4f30bb0.1687816734.git.mirai@makinata.eu> (Bruno Victal's message of "Mon, 26 Jun 2023 22:59:31 +0100") Message-ID: <87il7o3kkv.fsf_-_@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Scanner: mx0.migadu.com X-Migadu-Spam-Score: -2.13 X-Spam-Score: -2.13 X-Migadu-Queue-Id: EC74154DCE X-TUID: Q+IjKNw/3Fwz Hi Bruno, Bruno Victal writes: > Allow relaying additional arguments to a serialize- procedure. > > * gnu/services/configuration.scm (configuration-field) > : New field. > (base-transducer, define-maybe-helper): Adjust to relay additional arguments. > (normalize-extra-args): Implement serializer-options literal. > * tests/services/configuration.scm: Add tests for serializer-options. > * doc/guix.texi (Complex Configurations): Document serializer-options. Interesting! > --- > doc/guix.texi | 11 +++++ > gnu/services/configuration.scm | 49 ++++++++++++------- > tests/services/configuration.scm | 82 ++++++++++++++++++++++++++++++++ > 3 files changed, 126 insertions(+), 16 deletions(-) > > diff --git a/doc/guix.texi b/doc/guix.texi > index 8355260378..14802e9366 100644 > --- a/doc/guix.texi > +++ b/doc/guix.texi > @@ -42032,6 +42032,17 @@ Complex Configurations > ((symbol? value) (symbol->string value)) > (else (error "bad value")))) > @end lisp > + > +@item @code{(serializer-options @var{arglst})} > +@var{arglst} is a list of extra arguments that are relayed to the > +serializing procedure. This allows for writing serialization > +procedures that take more than two arguments. > + > +An example of a serializer procedure that requires additional data: > +@lisp > +(define* (serialize-port field value #:key context) > + #~(format #f "section=~a,port=~d" #$context #$value)) > +@end lisp > @end table > > In some cases multiple different configuration records might be defined > diff --git a/gnu/services/configuration.scm b/gnu/services/configuration.scm > index cd2cb8318b..4eee5a26c2 100644 > --- a/gnu/services/configuration.scm > +++ b/gnu/services/configuration.scm > @@ -50,6 +50,7 @@ (define-module (gnu services configuration) > configuration-field-error > configuration-field-sanitizer > configuration-field-serializer > + configuration-field-serializer-options > configuration-field-getter > configuration-field-default-value-thunk > configuration-field-documentation > @@ -127,6 +128,7 @@ (define-record-type* > (predicate configuration-field-predicate) > (sanitizer configuration-field-sanitizer) > (serializer configuration-field-serializer) > + (serializer-options configuration-field-serializer-options) > (default-value-thunk configuration-field-default-value-thunk) > (documentation configuration-field-documentation)) > > @@ -144,9 +146,13 @@ (define (base-transducer config) > ;; Only serialize fields whose value isn't '%unset-marker%. > (tfilter-maybe-value config) > (tmap (lambda (field) > - ((configuration-field-serializer field) > - (configuration-field-name field) > - ((configuration-field-getter field) config)))))) > + (let ((serializer (configuration-field-serializer field)) > + (field-name (configuration-field-name field)) > + (value > + ((configuration-field-getter field) config)) > + (serializer-options > + (configuration-field-serializer-options field))) > + (apply serializer field-name value serializer-options)))))) > > (define (serialize-configuration config fields) > #~(string-append > @@ -173,10 +179,9 @@ (define (define-maybe-helper serialize? prefix syn) > (or (not (maybe-value-set? val)) > (stem? val))) > #,@(if serialize? > - (list #'(define (serialize-maybe-stem field-name val) > - (if (stem? val) > - (serialize-stem field-name val) > - ""))) > + (list #'(define (serialize-maybe-stem field-name val . rest) > + (when (maybe-value-set? val) > + (apply serialize-stem field-name val rest)))) > '())))))) > > (define-syntax define-maybe > @@ -210,38 +215,49 @@ (define (define-configuration-helper serialize? serializer-prefix syn) > "Extract and normalize arguments following @var{doc}." > (let loop ((s s) > (sanitizer* #f) > - (serializer* #f)) > - (syntax-case s (sanitizer serializer empty-serializer) > + (serializer* #f) > + (serializer-options* #f)) > + (syntax-case s (sanitizer serializer empty-serializer serializer-options) > (((sanitizer proc) tail ...) > (if sanitizer* > (syntax-violation 'sanitizer > "duplicate entry" #'proc) > - (loop #'(tail ...) #'proc serializer*))) > + (loop #'(tail ...) > + #'proc serializer* serializer-options*))) > (((serializer proc) tail ...) > (if serializer* > (syntax-violation 'serializer > "duplicate or conflicting entry" #'proc) > - (loop #'(tail ...) sanitizer* #'proc))) > + (loop #'(tail ...) > + sanitizer* #'proc serializer-options*))) > ((empty-serializer tail ...) > (if serializer* > (syntax-violation 'empty-serializer > "duplicate or conflicting entry" #f) > - (loop #'(tail ...) sanitizer* #'empty-serializer))) > + (loop #'(tail ...) > + sanitizer* #'empty-serializer #f))) > + (((serializer-options args) tail ...) > + (if serializer-options* > + (syntax-violation 'serializer-options > + "duplicate or conflicting entry" #f) > + (loop #'(tail ...) > + sanitizer* serializer* #'args))) > (() ; stop condition > - (values (list sanitizer* serializer*))) > + (values (list sanitizer* serializer* > + (or serializer-options* #'(quote ()))))) > ((proc) ; TODO: deprecated, to be removed. > - (every not (list sanitizer* serializer*)) > + (every not (list sanitizer* serializer* serializer-options*)) > (begin > (warning #f (G_ "specifying serializers after documentation is \ > deprecated, use (serializer ~a) instead~%") (syntax->datum #'proc)) > - (values (list #f #'proc))))))) > + (values (list #f #'proc #'(quote ())))))))) > > (syntax-case syn () > ((_ stem (field field-type+def doc extra-args ...) ...) > (with-syntax > ((((field-type def) ...) > (map normalize-field-type+def #'(field-type+def ...))) > - (((sanitizer* serializer*) ...) > + (((sanitizer* serializer* serializer-options*) ...) > (map normalize-extra-args #'((extra-args ...) ...)))) > (with-syntax > (((field-getter ...) > @@ -327,6 +343,7 @@ (define (define-configuration-helper serialize? serializer-prefix syn) > (or field-sanitizer > (id #'stem #'validate- #'stem #'- #'field))) > (serializer field-serializer) > + (serializer-options serializer-options*) > (default-value-thunk > (lambda () > (if (maybe-value-set? (syntax->datum field-default)) > diff --git a/tests/services/configuration.scm b/tests/services/configuration.scm > index 40a4e74b4d..8b1d1e4749 100644 > --- a/tests/services/configuration.scm > +++ b/tests/services/configuration.scm > @@ -297,6 +297,88 @@ (define (sanitize-port value) > (lambda _ "lorem") > (sanitizer (lambda () #t))))))) > > +(test-group "Serializer options" > + (test-group "Serialize keyword arguments" > + (define* (serialize-port field value #:key host) > + (format #f "host=~a,port=~d" host value)) > + > + (define-configuration kwarg-config > + (port > + (port 80) > + "Lorem Ipsum." > + (serializer-options '(#:host "[2001:db8::1]")))) > + > + (define-maybe port) > + (define-configuration kwarg-maybe-config > + (port > + (maybe-port 80) > + "Lorem Ipsum." > + (serializer-options '(#:host "[2001:db8::1]")))) > + > + (test-equal "keyword argument provided" > + "host=[2001:db8::1],port=80" > + (eval-gexp > + (serialize-configuration (kwarg-config) > + kwarg-config-fields))) > + > + (test-equal "keyword argument provided, maybe type" > + "host=[2001:db8::1],port=80" > + (eval-gexp > + (serialize-configuration (kwarg-maybe-config) > + kwarg-maybe-config-fields)))) > + > + (test-group "Serialize optional arguments" > + (define* (serialize-port field-name value #:optional override-name) > + (format #f "~a=~d" (or override-name field-name) value)) > + > + (define-configuration with-optarg > + (port > + (port 80) > + "Lorem Ipsum." > + (serializer-options '(service-port)))) > + > + (define-configuration without-optarg > + (port > + (port 80) > + "Lorem Ipsum.")) > + > + (test-equal "optional argument, provided" > + "service-port=80" > + (eval-gexp (serialize-configuration (with-optarg) > + with-optarg-fields))) > + > + (test-equal "optional argument, absent" > + "port=80" > + (eval-gexp (serialize-configuration (without-optarg) > + without-optarg-fields)))) > + > + (test-group "Serialize optional & keyword arguments" > + (define* (serialize-port field-name value #:optional override-name > + #:key host) > + (format #f "host=~a,~a=~d" host (or override-name field-name) value)) > + > + (define-configuration mixed-args > + (port > + (port 80) > + "Lorem Ipsum." > + (serializer-options '(service-port #:host "example.com")))) > + > + (define-configuration mixed-no-optarg > + (port > + (port 80) > + "Lorem Ipsum." > + (serializer-options '(#:host "example.com")))) > + > + (test-equal "mixed arguments, optional provided" > + "host=example.com,service-port=80" > + (eval-gexp (serialize-configuration (mixed-args) > + mixed-args-fields))) > + > + (test-equal "mixed arguments, optional absent" > + "host=example.com,port=80" > + (eval-gexp (serialize-configuration (mixed-no-optarg) > + mixed-no-optarg-fields))))) Could you offer some of your perspective as to why you preferred that approach compared to generating multiple, tailored for use, serializers, possibly created via a procedure? Was there a problem with doing so, or what is less readable, etc.? -- Thanks, Maxim