Breaking change: Remove deprecated syntax accessor.

This has been replaced by edition and feature getters.  Any code depending on syntax will likely be broken by editions files, and should be migrated to the finer-grained feature helpers.

PiperOrigin-RevId: 589866745
diff --git a/python/descriptor.c b/python/descriptor.c
index 60dd2bf..ea4c028 100644
--- a/python/descriptor.c
+++ b/python/descriptor.c
@@ -648,18 +648,6 @@
   return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
 }
 
-static PyObject* PyUpb_Descriptor_GetSyntax(PyObject* self, void* closure) {
-  PyErr_WarnEx(NULL,
-               "descriptor.syntax is deprecated. It will be removed soon. "
-               "Most usages are checking field descriptors. Consider to use "
-               "has_presence, is_packed on field descriptors.",
-               1);
-  const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(self);
-  const char* syntax =
-      upb_MessageDef_Syntax(msgdef) == kUpb_Syntax_Proto2 ? "proto2" : "proto3";
-  return PyUnicode_InternFromString(syntax);
-}
-
 static PyGetSetDef PyUpb_Descriptor_Getters[] = {
     {"name", PyUpb_Descriptor_GetName, NULL, "Last name"},
     {"full_name", PyUpb_Descriptor_GetFullName, NULL, "Full name"},
@@ -694,13 +682,6 @@
      "Containing type"},
     {"is_extendable", PyUpb_Descriptor_GetIsExtendable, NULL},
     {"has_options", PyUpb_Descriptor_GetHasOptions, NULL, "Has Options"},
-    // begin:github_only
-    {"syntax", &PyUpb_Descriptor_GetSyntax, NULL, "Syntax"},
-    // end:github_only
-    // begin:google_only
-//     // TODO Use this to open-source syntax deprecation.
-//     {"deprecated_syntax", &PyUpb_Descriptor_GetSyntax, NULL, "Syntax"},
-    // end:google_only
     {NULL}};
 
 static PyMethodDef PyUpb_Descriptor_Methods[] = {
@@ -1384,17 +1365,10 @@
   return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
 }
 
-static PyObject* PyUpb_FileDescriptor_GetSyntax(PyObject* _self,
-                                                void* closure) {
-  PyErr_WarnEx(NULL,
-               "descriptor.syntax is deprecated. It will be removed soon. "
-               "Most usages are checking field descriptors. Consider to use "
-               "has_presence, is_packed on field descriptors.",
-               1);
+static PyObject* PyUpb_FileDescriptor_GetEdition(PyObject* _self,
+                                                 void* closure) {
   PyUpb_DescriptorBase* self = (void*)_self;
-  const char* syntax =
-      upb_FileDef_Syntax(self->def) == kUpb_Syntax_Proto2 ? "proto2" : "proto3";
-  return PyUnicode_FromString(syntax);
+  return PyLong_FromLong(upb_FileDef_Edition(self->def));
 }
 
 static PyObject* PyUpb_FileDescriptor_GetHasOptions(PyObject* _self,
@@ -1445,14 +1419,7 @@
     {"public_dependencies", PyUpb_FileDescriptor_GetPublicDependencies, NULL,
      "Dependencies"},
     {"has_options", PyUpb_FileDescriptor_GetHasOptions, NULL, "Has Options"},
-    // begin:github_only
-    {"syntax", PyUpb_FileDescriptor_GetSyntax, (setter)NULL, "Syntax"},
-    // end:github_only
-    // begin:google_only
-//     // TODO Use this to open-source syntax deprecation.
-//     {"deprecated_syntax", PyUpb_FileDescriptor_GetSyntax, (setter)NULL,
-//      "Syntax"},
-    // end:google_only
+    {"edition", PyUpb_FileDescriptor_GetEdition, (setter)NULL, "Edition"},
     {NULL},
 };
 
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index fb16bb4..29885ff 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -1179,24 +1179,23 @@
   Attributes:
     name (str): Name of file, relative to root of source tree.
     package (str): Name of the package
-    syntax (str): string indicating syntax of the file (can be "proto2" or
-      "proto3")
+    edition (Edition): Enum value indicating edition of the file
     serialized_pb (bytes): Byte string of serialized
       :class:`descriptor_pb2.FileDescriptorProto`.
     dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor`
       objects this :class:`FileDescriptor` depends on.
     public_dependencies (list[FileDescriptor]): A subset of
       :attr:`dependencies`, which were declared as "public".
-    message_types_by_name (dict(str, Descriptor)): Mapping from message names
-      to their :class:`Descriptor`.
+    message_types_by_name (dict(str, Descriptor)): Mapping from message names to
+      their :class:`Descriptor`.
     enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to
       their :class:`EnumDescriptor`.
     extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension
       names declared at file scope to their :class:`FieldDescriptor`.
     services_by_name (dict(str, ServiceDescriptor)): Mapping from services'
       names to their :class:`ServiceDescriptor`.
-    pool (DescriptorPool): The pool this descriptor belongs to.  When not
-      passed to the constructor, the global default pool is used.
+    pool (DescriptorPool): The pool this descriptor belongs to.  When not passed
+      to the constructor, the global default pool is used.
   """
 
   if _USE_C_DESCRIPTORS:
@@ -1260,7 +1259,6 @@
     self.message_types_by_name = {}
     self.name = name
     self.package = package
-    self._deprecated_syntax = syntax or "proto2"
     self.serialized_pb = serialized_pb
 
     self.enum_types_by_name = {}
@@ -1269,15 +1267,6 @@
     self.dependencies = (dependencies or [])
     self.public_dependencies = (public_dependencies or [])
 
-  @property
-  def syntax(self):
-    warnings.warn(
-      'descriptor.syntax is deprecated. It will be removed'
-      ' soon. Most usages are checking field descriptors. Consider to use'
-      ' has_presence, is_packed on field descriptors.'
-    )
-    return self._deprecated_syntax
-
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.FileDescriptorProto.
 
@@ -1290,6 +1279,13 @@
   def _parent(self):
     return None
 
+  @property
+  def edition(self):
+    # pylint: disable=g-import-not-at-top
+    from google.protobuf import descriptor_pb2
+
+    return descriptor_pb2.Edition.Value(self._edition)
+
 
 def _ParseOptions(message, string):
   """Parses serialized options.
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index e18149e..bf833a4 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -539,7 +539,9 @@
     self.assertEqual(self.my_file.package, 'protobuf_unittest')
     self.assertEqual(self.my_file.pool, self.pool)
     self.assertFalse(self.my_file.has_options)
-    self.assertEqual(self.my_file.syntax, 'proto2')
+    self.assertEqual(
+        self.my_file.edition, descriptor_pb2.Edition.EDITION_PROTO2
+    )
     file_proto = descriptor_pb2.FileDescriptorProto()
     self.my_file.CopyToProto(file_proto)
     self.assertEqual(self.my_file.serialized_pb,
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 0c4ac87..2c5bd1a 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -22,7 +22,6 @@
 #include "absl/log/absl_check.h"
 #include "absl/strings/string_view.h"
 #include "google/protobuf/descriptor.h"
-#include "google/protobuf/descriptor_legacy.h"
 #include "google/protobuf/dynamic_message.h"
 #include "google/protobuf/io/coded_stream.h"
 #include "google/protobuf/pyext/descriptor_containers.h"
@@ -696,17 +695,6 @@
   return PyString_FromCppString(enum_value->name());
 }
 
-static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
-  PyErr_WarnEx(nullptr,
-               "descriptor.syntax is deprecated. It will be removed soon. "
-               "Most usages are checking field descriptors. Consider to use "
-               "has_presence, is_packed on field descriptors.",
-               1);
-  std::string syntax(FileDescriptorLegacy::SyntaxName(
-      FileDescriptorLegacy(_GetDescriptor(self)->file()).syntax()));
-  return PyUnicode_InternFromString(syntax.c_str());
-}
-
 static PyGetSetDef Getters[] = {
     {"name", (getter)GetName, nullptr, "Last name"},
     {"full_name", (getter)GetFullName, nullptr, "Full name"},
@@ -743,7 +731,6 @@
     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
      "Serialized Options"},
-    {"syntax", (getter)GetSyntax, (setter) nullptr, "Syntax"},
     {nullptr},
 };
 
@@ -1542,15 +1529,8 @@
   return CheckCalledFromGeneratedFile("_serialized_options");
 }
 
-static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
-  PyErr_WarnEx(nullptr,
-               "descriptor.syntax is deprecated. It will be removed soon. "
-               "Most usages are checking field descriptors. Consider to use "
-               "has_presence, is_packed on field descriptors.",
-               1);
-  std::string syntax(FileDescriptorLegacy::SyntaxName(
-      FileDescriptorLegacy(_GetDescriptor(self)).syntax()));
-  return PyUnicode_InternFromString(syntax.c_str());
+static PyObject* GetEdition(PyFileDescriptor* self, void* closure) {
+  return PyLong_FromLong(_GetDescriptor(self)->edition());
 }
 
 static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
@@ -1579,7 +1559,7 @@
     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
      "Serialized Options"},
-    {"syntax", (getter)GetSyntax, (setter) nullptr, "Syntax"},
+    {"edition", (getter)GetEdition, (setter) nullptr, "Edition"},
     {nullptr},
 };