Subject: bug#66554: [PATCH] Add the public API of Compat to the core

From: Philip Kaludercic <[email-masked]>
Date: Fri, 12 Jan 2024 16:29:15 +0000

Daniel Mendler <[email-masked]> writes:

> Philip Kaludercic <[email-masked]> writes:
>
>> Daniel Mendler <[email-masked]> writes:
>>
>>> Philip Kaludercic <[email-masked]> writes:
>>>> Stefan Monnier <[email-masked]> writes:
>>>>> The addition cab done procedurally, as in
>>>>>
>>>>>     ;;;;####autoload (push (list 'compat emacs-major-version
>>>>> emacs-minor-version) package--builtin-versions)
>>>>
>>>> If this work, I like this idea a lot!  I'll test it out to see if this
>>>> could simplify things.
>>>
>>> Philip, could we push (list 'compat emacs-major-version
>>> emacs-minor-version most-positive-fixnum)? Wouldn't this solve the two
>>> problems we have - no manual version bump and Compat could keep its
>>> current version scheme?
>>
>> Yes, I just tried it out and it works (and it doesn't work the way we
>> want it to without `most-positive-fixnum'):
>
> Thanks, your patch looks good. Stefan's idea of using an autoload to
> specify the version is nice. As Eli mentioned the Elisp manual should
> probably refer to the Compat manual, and maybe the change also needs a
> NEWS entry? Anything else?

I don't think we need anything else, so here is the updated patch:

>From a93f008f1fc58fdfbe4e832624e3ae7b28a6fda3 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <[email-masked]>
Date: Wed, 13 Sep 2023 12:26:22 +0200
Subject: [PATCH] Add the public API of Compat to the core

* lisp/emacs-lisp/compat.el: Add stub file with minimal definitions,
so that core packages, that haven't been installed from ELPA, can make
use of the public API and use more recent function signatures.
* lisp/progmodes/python.el (compat): Remove 'noerror flag, because
Compat can now be required without the real package being available.
* doc/lispref/package.texi (Forwards-Compatibility): Mention Compat
and link to the manual.
* etc/NEWS: Document change.  (Bug#66554)
---
 doc/lispref/package.texi  | 13 ++++++++
 etc/NEWS                  | 11 +++++++
 lisp/emacs-lisp/compat.el | 66 +++++++++++++++++++++++++++++++++++++++
 lisp/progmodes/python.el  |  2 +-
 4 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 lisp/emacs-lisp/compat.el

diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi
index 6f52a33d194..b2b6e6b9671 100644
--- a/doc/lispref/package.texi
+++ b/doc/lispref/package.texi
@@ -28,6 +28,7 @@ Packaging
 * Multi-file Packages::     How to package multiple files.
 * Package Archives::        Maintaining package archives.
 * Archive Web Server::      Interfacing to an archive web server.
+* Forwards-Compatibility::  Supporting older versions of Emacs.
 @end menu
 
 @node Packaging Basics
@@ -390,3 +391,15 @@ Archive Web Server
 package, or the single file for a simple package.
 
 @end table
+
+@node Forwards-Compatibility
+@section Supporting older versions of Emacs
+@cindex compatibility compat
+
+Packages that wish to support older releases of Emacs, without giving
+up on newer functionality from recent Emacs releases, one can make use
+of the Compat package on GNU ELPA.  @xref{Usage,, Usage, compat,
+"Compat" Manual} For details on how to make use of the package (in
+case you don't have the package installed, you can also read the
+@url{https://elpa.gnu.org/packages/doc/compat.html#Usage, Online
+Compat manual}).
diff --git a/etc/NEWS b/etc/NEWS
index bce33f96aee..11dc90d5067 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1298,6 +1298,17 @@ This minor mode generates the tags table automatically based on the
 current project configuration, and later updates it as you edit the
 files and save the changes.
 
++++
+** New package Compat
+The Compat package on GNU ELPA provides forwards-compatibility
+support, so that packages that still provide support for older
+versions of Emacs can still make use of newer definitions that can be
+reasonably re-implemented in Elisp.  Now a "pseudo" Compat package is
+part of Emacs, that doesn't provide any compatibility support, but
+only implements the public-facing API of Compat so that core packages
+can use Compat, while also preventing the installation of Compat on
+the most recent version of Emacs.
+
 
 * Incompatible Lisp Changes in Emacs 30.1
 
diff --git a/lisp/emacs-lisp/compat.el b/lisp/emacs-lisp/compat.el
new file mode 100644
index 00000000000..b2c1125cb8d
--- /dev/null
+++ b/lisp/emacs-lisp/compat.el
@@ -0,0 +1,66 @@
+;;; compat.el --- Pseudo-Compatibility for Elisp -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
+
+;; Author:								\
+;;   Philip Kaludercic <[email-masked]>,				\
+;;   Daniel Mendler <[email-masked]>
+;; Maintainer:								\
+;;   Daniel Mendler <[email-masked]>,				\
+;;   Compat Development <~pkal/[email-masked]>,
+;;   [email-masked]
+;; URL: https://github.com/emacs-compat/compat
+;; Keywords: lisp, maint
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; The Compat package on ELPA provides forward-compatibility
+;; definitions for other packages.  While mostly transparent, a
+;; minimal API is necessary whenever core definitions change calling
+;; conventions (e.g. `plist-get' can be invoked with a predicate from
+;; Emacs 29.1 onward).  For core packages on ELPA to be able to take
+;; advantage of this functionality, the macros `compat-function' and
+;; `compat-call' have to be available in the core, usable even if
+;; users do not have the Compat package installed, which this file
+;; ensures.
+
+;; Note that Compat is not a core package and this file is not
+;; available on GNU ELPA.
+
+;;; Code:
+
+(defmacro compat-function (fun)
+  "Return compatibility function symbol for FUN.
+This is a pseudo-compatibility stub for core packages on ELPA,
+that depend on the Compat package, whenever the user doesn't have
+the package installed on their current system."
+  `#',fun)
+
+(defmacro compat-call (fun &rest args)
+  "Call compatibility function or macro FUN with ARGS.
+This is a pseudo-compatibility stub for core packages on ELPA,
+that depend on the Compat package, whenever the user doesn't have
+the package installed on their current system."
+  (cons fun args))
+
+;; To ensure that if the user has installed Compat X.Y.Z.A on Emacs
+;; X.Y, that the this file is preferred by package.el, we
+;; programmatically set the version of this file:
+
+;;;###autoload (push (list 'compat emacs-major-version emacs-minor-version most-positive-fixnum) package--builtin-versions)
+
+(provide 'compat)
+;;; compat.el ends here
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 1148da11a06..c3f18692f61 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -267,7 +267,7 @@
 (eval-when-compile (require 'subr-x))   ;For `string-empty-p' and `string-join'.
 (require 'treesit)
 (require 'pcase)
-(require 'compat nil 'noerror)
+(require 'compat)
 (require 'project nil 'noerror)
 (require 'seq)
 
-- 
2.39.2

> Daniel

Eli Zaretskii <[email-masked]> writes:

>> From: Philip Kaludercic <[email-masked]>
>> Cc: Stefan Monnier <[email-masked]>,  [email-masked],
>>   [email-masked],  Stefan Kangas <[email-masked]>
>> Date: Thu, 11 Jan 2024 20:43:11 +0000
>> 
>> +;; To ensure that if the user has installed Compat X.Y.Z.A on Emacs
>> +;; X.Y, that the this file is preferred by package.el, we
>                 ^^^^^^^^
> Typo.

Thanks; I also rewrote the comment to explain what is going on.

Eli Zaretskii <[email-masked]> writes:

>> From: Philip Kaludercic <[email-masked]>
>> Cc: [email-masked],  [email-masked],
>>   [email-masked],  [email-masked]
>> Date: Fri, 12 Jan 2024 07:38:20 +0000
>> 
>> The consequence is that we don't have to update any files, and I would
>> assume we don't have to document anything in make-tarball.txt, because
>> nothing has to be done when bumping the version of Emacs itself.
>
> Thanks.
>
> What happens when we bump Emacs version from NN.x to NN.x.90 or from
> NN.x.90 to NN.x.91?  emacs-major-version and emacs-minor-version stay
> the same, but the Emacs version is bumped, and there could be changes
> in compat.el specific to the next release, NN.x+1 or NN+1.1, no?

Generally speaking, Compat only provides support for "proper" releases,
and not for pre-releases.