diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC201_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC201_sphinx.py
new file mode 100644
index 0000000000000..2ba257368ba84
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC201_sphinx.py
@@ -0,0 +1,60 @@
+# DOC201
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    """
+    return 'test'
+
+
+# OK
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    :return: A string
+    :rtype: str
+    """
+    return 'test'
+
+
+class Bar:
+
+    # OK
+    def foo(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        :return: A string
+        :rtype: str
+        """
+        return 'test'
+
+
+    # DOC201
+    def bar(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        """
+        return 'test'
+
+
+    # OK
+    @property
+    def baz(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        """
+        return 'test'
diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC202_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC202_sphinx.py
new file mode 100644
index 0000000000000..45a08d8a82ef9
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC202_sphinx.py
@@ -0,0 +1,48 @@
+# OK
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    """
+    print('test')
+
+
+# DOC202
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    :return: A string
+    :rtype: str
+    """
+    print('test')
+
+
+class Bar:
+
+    # DOC202
+    def foo(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        :return: A string
+        :rtype: str
+        """
+        print('test')
+
+
+    # OK
+    def bar(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        """
+        print('test')
diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC402_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC402_sphinx.py
new file mode 100644
index 0000000000000..df7f776517699
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC402_sphinx.py
@@ -0,0 +1,126 @@
+# DOC402
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    """
+    yield 'test'
+
+
+# OK
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    :yield: A string
+    :rtype: str
+    """
+    yield 'test'
+
+
+class Bar:
+
+    # OK
+    def foo(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        :yield: A string
+        :rtype: str
+        """
+        yield 'test'
+
+
+    # DOC402
+    def bar(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        """
+        yield 'test'
+
+
+import typing
+
+
+# OK
+def foo() -> typing.Generator[None, None, None]:
+    """
+    Do something
+    """
+    yield None
+
+
+# OK
+def foo() -> typing.Generator[None, None, None]:
+    """
+    Do something
+    """
+    yield
+
+
+# DOC402
+def foo() -> typing.Generator[int | None, None, None]:
+    """
+    Do something
+    """
+    yield None
+    yield 1
+
+
+# DOC402
+def foo() -> typing.Generator[int, None, None]:
+    """
+    Do something
+    """
+    yield None
+
+
+# OK
+def foo():
+    """
+    Do something
+    """
+    yield None
+
+
+# OK
+def foo():
+    """
+    Do something
+    """
+    yield
+
+
+# DOC402
+def foo():
+    """
+    Do something
+    """
+    yield None
+    yield 1
+
+
+# DOC402
+def foo():
+    """
+    Do something
+    """
+    yield 1
+    yield
+
+
+# DOC402
+def bar() -> typing.Iterator[int | None]:
+    """
+    Do something
+    """
+    yield
diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC403_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC403_sphinx.py
new file mode 100644
index 0000000000000..8eb55389a4dda
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC403_sphinx.py
@@ -0,0 +1,91 @@
+# OK
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    """
+    print('test')
+
+
+# DOC403
+def foo(num: int) -> str:
+    """
+    Do something
+
+    :param num: A number
+    :type num: int
+    :yield: A string
+    :rtype: str
+    """
+    print('test')
+
+
+class Bar:
+
+    # DOC403
+    def foo(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        :yield: A string
+        :rtype: str
+        """
+        print('test')
+
+
+    # OK
+    def bar(self) -> str:
+        """
+        Do something
+
+        :param num: A number
+        :type num: int
+        """
+        print('test')
+
+
+import typing
+
+
+# OK
+def foo() -> typing.Generator[None, None, None]:
+    """
+    Do something
+
+    :yield: When X.
+    """
+    yield None
+
+
+# OK
+def foo() -> typing.Generator[None, None, None]:
+    """
+    Do something
+
+    :yield: When X.
+    """
+    yield
+
+
+# OK
+def foo():
+    """
+    Do something
+
+    :yield: When X.
+    """
+    yield None
+
+
+# OK
+def foo():
+    """
+    Do something
+
+    :yield: When X.
+    """
+    yield
diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC501_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC501_sphinx.py
new file mode 100644
index 0000000000000..2e66b8ce70488
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC501_sphinx.py
@@ -0,0 +1,115 @@
+class FasterThanLightError(Exception):
+    ...
+
+
+# OK
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises FasterThanLightError: If speed is greater than the speed of light.
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError as exc:
+        raise FasterThanLightError from exc
+
+
+# DOC501
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError as exc:
+        raise FasterThanLightError from exc
+
+
+# DOC501
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError as exc:
+        raise FasterThanLightError from exc
+    except:
+        raise ValueError
+
+
+# DOC501
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises ZeroDivisionError: If attempting to divide by zero.
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError:
+        print("Oh no, why would you divide something by zero?")
+        raise
+    except TypeError:
+        print("Not a number? Shame on you!")
+        raise
+
+
+# This is fine
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    """
+    try:
+        return distance / time
+    except Exception as e:
+        print(f"Oh no, we encountered {e}")
+        raise
+
+
+def foo():
+    """Foo.
+
+    :return: 42
+    :rtype: int
+    """
+    if True:
+        raise TypeError  # DOC501
+    else:
+        raise TypeError  # no DOC501 here because we already emitted a diagnostic for the earlier `raise TypeError`
+    raise ValueError  # DOC501
+    return 42
diff --git a/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC502_sphinx.py b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC502_sphinx.py
new file mode 100644
index 0000000000000..a41c29650f456
--- /dev/null
+++ b/crates/ruff_linter/resources/test/fixtures/pydoclint/DOC502_sphinx.py
@@ -0,0 +1,80 @@
+class FasterThanLightError(Exception):
+    ...
+
+
+# DOC502
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises FasterThanLightError: If speed is greater than the speed of light.
+    """
+    return distance / time
+
+
+# DOC502
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises FasterThanLightError: If speed is greater than the speed of light.
+    :raises DivisionByZero: If attempting to divide by zero.
+    """
+    return distance / time
+
+
+# DOC502
+def calculate_speed(distance: float, time: float) -> float:
+    """
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises FasterThanLightError: If speed is greater than the speed of light.
+    :raises DivisionByZero: If attempting to divide by zero.
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError as exc:
+        raise FasterThanLightError from exc
+
+
+# This is fine
+def calculate_speed(distance: float, time: float) -> float:
+    """Calculate speed as distance divided by time.
+
+    Calculate speed as distance divided by time.
+
+    :param distance: Distance traveled.
+    :type distance: float
+    :param time: Time spent traveling.
+    :type time: float
+    :return: Speed as distance divided by time.
+    :rtype: float
+    :raises TypeError: If one or both of the parameters is not a number.
+    :raises ZeroDivisionError: If attempting to divide by zero.
+    """
+    try:
+        return distance / time
+    except ZeroDivisionError:
+        print("Oh no, why would you divide something by zero?")
+        raise
+    except TypeError:
+        print("Not a number? Shame on you!")
+        raise
diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py
index d04c38a74bff9..8c9b4a4f25cc5 100644
--- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py
+++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py
@@ -619,3 +619,16 @@ def another_valid_google_style_docstring(a: str) -> str:
 
     """
     return a
+
+
+def foo(dag_id: str, keep_records_in_log: bool = True) -> int:
+    """
+    Delete a DAG by a dag_id.
+
+    :param dag_id: the dag_id of the DAG to delete
+    :param keep_records_in_log: whether keep records of the given dag_id
+        in the Log table in the backend database (for reasons like auditing).
+        The default value is True.
+    :return: count of deleted dags
+    """
+    return 0
diff --git a/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs b/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs
index ef2434b3e6643..2ddf1efd168ee 100644
--- a/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs
+++ b/crates/ruff_linter/src/checkers/ast/analyze/definitions.rs
@@ -313,6 +313,7 @@ pub(crate) fn definitions(checker: &mut Checker) {
                 let section_contexts = pydocstyle::helpers::get_section_contexts(
                     &docstring,
                     checker.settings.pydocstyle.convention(),
+                    checker,
                 );
 
                 if enforce_sections {
diff --git a/crates/ruff_linter/src/docstrings/mod.rs b/crates/ruff_linter/src/docstrings/mod.rs
index 7715beea865ba..5de7fe82ed18a 100644
--- a/crates/ruff_linter/src/docstrings/mod.rs
+++ b/crates/ruff_linter/src/docstrings/mod.rs
@@ -9,6 +9,7 @@ pub(crate) mod extraction;
 pub(crate) mod google;
 pub(crate) mod numpy;
 pub(crate) mod sections;
+pub(crate) mod sphinx;
 pub(crate) mod styles;
 
 #[derive(Debug)]
diff --git a/crates/ruff_linter/src/docstrings/sections.rs b/crates/ruff_linter/src/docstrings/sections.rs
index 1068a0db07535..520d9fdb5b1f6 100644
--- a/crates/ruff_linter/src/docstrings/sections.rs
+++ b/crates/ruff_linter/src/docstrings/sections.rs
@@ -1,7 +1,9 @@
 use std::fmt::{Debug, Formatter};
 use std::iter::FusedIterator;
 
-use ruff_python_ast::docstrings::{leading_space, leading_words};
+use ruff_python_ast::docstrings::{
+    leading_space, leading_space_and_colon, leading_words, sphinx_section_name,
+};
 use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
 use strum_macros::EnumIter;
 
@@ -31,17 +33,20 @@ pub(crate) enum SectionKind {
     Notes,
     OtherArgs,
     OtherArguments,
-    OtherParams,
     OtherParameters,
+    OtherParams,
+    Param,
     Parameters,
     Raises,
     References,
     Return,
     Returns,
+    RType,
     SeeAlso,
     ShortSummary,
     Tip,
     Todo,
+    Type,
     Warning,
     Warnings,
     Warns,
@@ -71,17 +76,20 @@ impl SectionKind {
             "notes" => Some(Self::Notes),
             "other args" => Some(Self::OtherArgs),
             "other arguments" => Some(Self::OtherArguments),
-            "other params" => Some(Self::OtherParams),
             "other parameters" => Some(Self::OtherParameters),
+            "other params" => Some(Self::OtherParams),
+            "param" => Some(Self::Param),
             "parameters" => Some(Self::Parameters),
             "raises" => Some(Self::Raises),
             "references" => Some(Self::References),
             "return" => Some(Self::Return),
             "returns" => Some(Self::Returns),
+            "rtype" => Some(Self::RType),
             "see also" => Some(Self::SeeAlso),
             "short summary" => Some(Self::ShortSummary),
             "tip" => Some(Self::Tip),
             "todo" => Some(Self::Todo),
+            "type" => Some(Self::Type),
             "warning" => Some(Self::Warning),
             "warnings" => Some(Self::Warnings),
             "warns" => Some(Self::Warns),
@@ -112,17 +120,20 @@ impl SectionKind {
             Self::Notes => "Notes",
             Self::OtherArgs => "Other Args",
             Self::OtherArguments => "Other Arguments",
-            Self::OtherParams => "Other Params",
             Self::OtherParameters => "Other Parameters",
+            Self::OtherParams => "Other Params",
+            Self::Param => "Param",
             Self::Parameters => "Parameters",
             Self::Raises => "Raises",
             Self::References => "References",
             Self::Return => "Return",
             Self::Returns => "Returns",
+            Self::RType => "RType",
             Self::SeeAlso => "See Also",
             Self::ShortSummary => "Short Summary",
             Self::Tip => "Tip",
             Self::Todo => "Todo",
+            Self::Type => "Type",
             Self::Warning => "Warning",
             Self::Warnings => "Warnings",
             Self::Warns => "Warns",
@@ -180,7 +191,33 @@ impl<'a> SectionContexts<'a> {
         let mut previous_line = lines.next();
 
         while let Some(line) = lines.next() {
-            if let Some(section_kind) = suspected_as_section(&line, style) {
+            if matches!(style, SectionStyle::Sphinx) {
+                if let Some(section_name) = sphinx_section_name(&line) {
+                    if let Some(kind) = SectionKind::from_str(section_name) {
+                        if style.sections().contains(&kind) {
+                            let indent = leading_space_and_colon(&line);
+                            let indent_size = indent.text_len();
+                            let section_name_size = section_name.text_len();
+
+                            if let Some(mut last) = last.take() {
+                                last.range = TextRange::new(last.start(), line.start());
+                                contexts.push(last);
+                            }
+
+                            last = Some(SectionContextData {
+                                kind,
+                                indent_size: indent.text_len(),
+                                name_range: TextRange::at(
+                                    line.start() + indent_size,
+                                    section_name_size,
+                                ),
+                                range: TextRange::empty(line.start()),
+                                summary_full_end: line.full_end(),
+                            });
+                        }
+                    }
+                }
+            } else if let Some(section_kind) = suspected_as_section(&line, style) {
                 let indent = leading_space(&line);
                 let indent_size = indent.text_len();
 
diff --git a/crates/ruff_linter/src/docstrings/sphinx.rs b/crates/ruff_linter/src/docstrings/sphinx.rs
new file mode 100644
index 0000000000000..9c3d82d85244c
--- /dev/null
+++ b/crates/ruff_linter/src/docstrings/sphinx.rs
@@ -0,0 +1,12 @@
+//! Abstractions for Sphinx-style docstrings.
+
+use crate::docstrings::sections::SectionKind;
+
+pub(crate) static SPHINX_SECTIONS: &[SectionKind] = &[
+    SectionKind::Param,
+    SectionKind::Type,
+    SectionKind::Raises,
+    SectionKind::Return,
+    SectionKind::RType,
+    SectionKind::Yield,
+];
diff --git a/crates/ruff_linter/src/docstrings/styles.rs b/crates/ruff_linter/src/docstrings/styles.rs
index b4d1d3d44c32c..be89850adc961 100644
--- a/crates/ruff_linter/src/docstrings/styles.rs
+++ b/crates/ruff_linter/src/docstrings/styles.rs
@@ -1,11 +1,13 @@
 use crate::docstrings::google::GOOGLE_SECTIONS;
 use crate::docstrings::numpy::NUMPY_SECTIONS;
 use crate::docstrings::sections::SectionKind;
+use crate::docstrings::sphinx::SPHINX_SECTIONS;
 
 #[derive(Copy, Clone, Debug, is_macro::Is)]
 pub(crate) enum SectionStyle {
     Numpy,
     Google,
+    Sphinx,
 }
 
 impl SectionStyle {
@@ -13,6 +15,7 @@ impl SectionStyle {
         match self {
             SectionStyle::Numpy => NUMPY_SECTIONS,
             SectionStyle::Google => GOOGLE_SECTIONS,
+            SectionStyle::Sphinx => SPHINX_SECTIONS,
         }
     }
 }
diff --git a/crates/ruff_linter/src/rules/pydoclint/mod.rs b/crates/ruff_linter/src/rules/pydoclint/mod.rs
index 68565de689e19..d342a5bd566fb 100644
--- a/crates/ruff_linter/src/rules/pydoclint/mod.rs
+++ b/crates/ruff_linter/src/rules/pydoclint/mod.rs
@@ -12,6 +12,7 @@ mod tests {
     use crate::registry::Rule;
     use crate::rules::pydocstyle;
     use crate::rules::pydocstyle::settings::Convention;
+    use crate::settings::types::PreviewMode;
     use crate::test::test_path;
     use crate::{assert_messages, settings};
 
@@ -63,4 +64,24 @@ mod tests {
         assert_messages!(snapshot, diagnostics);
         Ok(())
     }
+
+    #[test_case(Rule::DocstringMissingReturns, Path::new("DOC201_sphinx.py"))]
+    #[test_case(Rule::DocstringExtraneousReturns, Path::new("DOC202_sphinx.py"))]
+    #[test_case(Rule::DocstringMissingYields, Path::new("DOC402_sphinx.py"))]
+    #[test_case(Rule::DocstringExtraneousYields, Path::new("DOC403_sphinx.py"))]
+    #[test_case(Rule::DocstringMissingException, Path::new("DOC501_sphinx.py"))]
+    #[test_case(Rule::DocstringExtraneousException, Path::new("DOC502_sphinx.py"))]
+    fn rules_sphinx_style(rule_code: Rule, path: &Path) -> Result<()> {
+        let snapshot = format!("{}_{}", rule_code.as_ref(), path.to_string_lossy());
+        let diagnostics = test_path(
+            Path::new("pydoclint").join(path).as_path(),
+            &settings::LinterSettings {
+                preview: PreviewMode::Enabled,
+                pydocstyle: pydocstyle::settings::Settings::new(Some(Convention::Sphinx), [], []),
+                ..settings::LinterSettings::for_rule(rule_code)
+            },
+        )?;
+        assert_messages!(snapshot, diagnostics);
+        Ok(())
+    }
 }
diff --git a/crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs b/crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs
index 40d88023033e6..dc9c10e611803 100644
--- a/crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs
+++ b/crates/ruff_linter/src/rules/pydoclint/rules/check_docstring.rs
@@ -415,17 +415,23 @@ impl<'a> DocstringSections<'a> {
         for section in sections {
             match section.kind() {
                 SectionKind::Raises => {
+                    if matches!(style, Some(SectionStyle::Sphinx)) {
+                        continue;
+                    }
                     docstring_sections.raises = Some(RaisesSection::from_section(&section, style));
                 }
-                SectionKind::Returns => {
+                SectionKind::Returns | SectionKind::Return => {
                     docstring_sections.returns = Some(GenericSection::from_section(&section));
                 }
-                SectionKind::Yields => {
+                SectionKind::Yields | SectionKind::Yield => {
                     docstring_sections.yields = Some(GenericSection::from_section(&section));
                 }
                 _ => continue,
             }
         }
+        if matches!(style, Some(SectionStyle::Sphinx)) {
+            docstring_sections.raises = parse_raises_sphinx(sections);
+        }
         docstring_sections
     }
 }
@@ -436,6 +442,7 @@ impl<'a> DocstringSections<'a> {
 /// entries are found.
 fn parse_entries(content: &str, style: Option<SectionStyle>) -> Vec<QualifiedName> {
     match style {
+        Some(SectionStyle::Sphinx) => panic!("Cannot process Sphinx style section"),
         Some(SectionStyle::Google) => parse_entries_google(content),
         Some(SectionStyle::Numpy) => parse_entries_numpy(content),
         None => {
@@ -497,6 +504,44 @@ fn parse_entries_numpy(content: &str) -> Vec<QualifiedName> {
     entries
 }
 
+/// Parses Sphinx-style docstring sections of the form:
+///
+/// ```python
+/// :raises FasterThanLightError: If speed is greater than the speed of light.
+/// :raises DivisionByZero: If attempting to divide by zero.
+/// ```
+fn parse_raises_sphinx<'a>(sections: &'a SectionContexts) -> Option<RaisesSection<'a>> {
+    let mut entries: Vec<QualifiedName> = Vec::new();
+    let mut range_start = None;
+    let mut range_end = None;
+    for section in sections {
+        if matches!(section.kind(), SectionKind::Raises) {
+            if range_start.is_none() {
+                range_start = Some(section.start());
+            }
+            range_end = Some(section.end());
+            let mut line = section.summary_line().split(':');
+            let _indent = line.next();
+            if let Some(header) = line.next() {
+                let mut header = header.split(' ');
+                let _raises = header.next();
+                if let Some(exception) = header.next() {
+                    entries.push(QualifiedName::user_defined(exception));
+                }
+            }
+        }
+    }
+    if let Some(range_start) = range_start {
+        if let Some(range_end) = range_end {
+            return Some(RaisesSection {
+                raised_exceptions: entries,
+                range: TextRange::new(range_start, range_end),
+            });
+        }
+    }
+    None
+}
+
 /// An individual `yield` expression in a function body.
 #[derive(Debug)]
 struct YieldEntry {
@@ -857,7 +902,15 @@ pub(crate) fn check_docstring(
         Some(Convention::Numpy) => {
             DocstringSections::from_sections(section_contexts, Some(SectionStyle::Numpy))
         }
-        Some(Convention::Pep257) | None => DocstringSections::from_sections(section_contexts, None),
+        Some(Convention::Sphinx) => {
+            DocstringSections::from_sections(section_contexts, Some(SectionStyle::Sphinx))
+        }
+        Some(Convention::Pep257) | None => match section_contexts.style() {
+            SectionStyle::Sphinx => {
+                DocstringSections::from_sections(section_contexts, Some(SectionStyle::Sphinx))
+            }
+            _ => DocstringSections::from_sections(section_contexts, None),
+        },
     };
 
     let body_entries = {
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-exception_DOC502_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-exception_DOC502_sphinx.py.snap
new file mode 100644
index 0000000000000..d8c52042c1a4c
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-exception_DOC502_sphinx.py.snap
@@ -0,0 +1,38 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC502_sphinx.py:16:1: DOC502 Raised exception is not explicitly raised: `FasterThanLightError`
+   |
+14 |       :return: Speed as distance divided by time.
+15 |       :rtype: float
+16 | /     :raises FasterThanLightError: If speed is greater than the speed of light.
+17 | |     """
+   | |____^ DOC502
+18 |       return distance / time
+   |
+   = help: Remove `FasterThanLightError` from the docstring
+
+DOC502_sphinx.py:32:1: DOC502 Raised exceptions are not explicitly raised: `FasterThanLightError`, `DivisionByZero`
+   |
+30 |       :return: Speed as distance divided by time.
+31 |       :rtype: float
+32 | /     :raises FasterThanLightError: If speed is greater than the speed of light.
+33 | |     :raises DivisionByZero: If attempting to divide by zero.
+34 | |     """
+   | |____^ DOC502
+35 |       return distance / time
+   |
+   = help: Remove `FasterThanLightError`, `DivisionByZero` from the docstring
+
+DOC502_sphinx.py:49:1: DOC502 Raised exception is not explicitly raised: `DivisionByZero`
+   |
+47 |       :return: Speed as distance divided by time.
+48 |       :rtype: float
+49 | /     :raises FasterThanLightError: If speed is greater than the speed of light.
+50 | |     :raises DivisionByZero: If attempting to divide by zero.
+51 | |     """
+   | |____^ DOC502
+52 |       try:
+53 |           return distance / time
+   |
+   = help: Remove `DivisionByZero` from the docstring
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-returns_DOC202_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-returns_DOC202_sphinx.py.snap
new file mode 100644
index 0000000000000..735f52c6107a7
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-returns_DOC202_sphinx.py.snap
@@ -0,0 +1,26 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC202_sphinx.py:19:1: DOC202 Docstring should not have a returns section because the function doesn't return anything
+   |
+17 |       :param num: A number
+18 |       :type num: int
+19 | /     :return: A string
+20 | |     :rtype: str
+   | |_^ DOC202
+21 |       """
+22 |       print('test')
+   |
+   = help: Remove the "Returns" section
+
+DOC202_sphinx.py:34:1: DOC202 Docstring should not have a returns section because the function doesn't return anything
+   |
+32 |           :param num: A number
+33 |           :type num: int
+34 | /         :return: A string
+35 | |         :rtype: str
+   | |_^ DOC202
+36 |           """
+37 |           print('test')
+   |
+   = help: Remove the "Returns" section
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-yields_DOC403_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-yields_DOC403_sphinx.py.snap
new file mode 100644
index 0000000000000..30669e049dc10
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-extraneous-yields_DOC403_sphinx.py.snap
@@ -0,0 +1,26 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC403_sphinx.py:19:1: DOC403 Docstring has a "Yields" section but the function doesn't yield anything
+   |
+17 |       :param num: A number
+18 |       :type num: int
+19 | /     :yield: A string
+20 | |     :rtype: str
+   | |_^ DOC403
+21 |       """
+22 |       print('test')
+   |
+   = help: Remove the "Yields" section
+
+DOC403_sphinx.py:34:1: DOC403 Docstring has a "Yields" section but the function doesn't yield anything
+   |
+32 |           :param num: A number
+33 |           :type num: int
+34 | /         :yield: A string
+35 | |         :rtype: str
+   | |_^ DOC403
+36 |           """
+37 |           print('test')
+   |
+   = help: Remove the "Yields" section
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-exception_DOC501_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-exception_DOC501_sphinx.py.snap
new file mode 100644
index 0000000000000..07b4d68a88d88
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-exception_DOC501_sphinx.py.snap
@@ -0,0 +1,61 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC501_sphinx.py:39:15: DOC501 Raised exception `FasterThanLightError` missing from docstring
+   |
+37 |         return distance / time
+38 |     except ZeroDivisionError as exc:
+39 |         raise FasterThanLightError from exc
+   |               ^^^^^^^^^^^^^^^^^^^^ DOC501
+   |
+   = help: Add `FasterThanLightError` to the docstring
+
+DOC501_sphinx.py:57:15: DOC501 Raised exception `FasterThanLightError` missing from docstring
+   |
+55 |         return distance / time
+56 |     except ZeroDivisionError as exc:
+57 |         raise FasterThanLightError from exc
+   |               ^^^^^^^^^^^^^^^^^^^^ DOC501
+58 |     except:
+59 |         raise ValueError
+   |
+   = help: Add `FasterThanLightError` to the docstring
+
+DOC501_sphinx.py:59:15: DOC501 Raised exception `ValueError` missing from docstring
+   |
+57 |         raise FasterThanLightError from exc
+58 |     except:
+59 |         raise ValueError
+   |               ^^^^^^^^^^ DOC501
+   |
+   = help: Add `ValueError` to the docstring
+
+DOC501_sphinx.py:82:9: DOC501 Raised exception `TypeError` missing from docstring
+   |
+80 |     except TypeError:
+81 |         print("Not a number? Shame on you!")
+82 |         raise
+   |         ^^^^^ DOC501
+   |
+   = help: Add `TypeError` to the docstring
+
+DOC501_sphinx.py:111:15: DOC501 Raised exception `TypeError` missing from docstring
+    |
+109 |     """
+110 |     if True:
+111 |         raise TypeError  # DOC501
+    |               ^^^^^^^^^ DOC501
+112 |     else:
+113 |         raise TypeError  # no DOC501 here because we already emitted a diagnostic for the earlier `raise TypeError`
+    |
+    = help: Add `TypeError` to the docstring
+
+DOC501_sphinx.py:114:11: DOC501 Raised exception `ValueError` missing from docstring
+    |
+112 |     else:
+113 |         raise TypeError  # no DOC501 here because we already emitted a diagnostic for the earlier `raise TypeError`
+114 |     raise ValueError  # DOC501
+    |           ^^^^^^^^^^ DOC501
+115 |     return 42
+    |
+    = help: Add `ValueError` to the docstring
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-returns_DOC201_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-returns_DOC201_sphinx.py.snap
new file mode 100644
index 0000000000000..d5431e24058a0
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-returns_DOC201_sphinx.py.snap
@@ -0,0 +1,20 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC201_sphinx.py:9:5: DOC201 `return` is not documented in docstring
+  |
+7 |     :type num: int
+8 |     """
+9 |     return 'test'
+  |     ^^^^^^^^^^^^^ DOC201
+  |
+  = help: Add a "Returns" section to the docstring
+
+DOC201_sphinx.py:48:9: DOC201 `return` is not documented in docstring
+   |
+46 |         :type num: int
+47 |         """
+48 |         return 'test'
+   |         ^^^^^^^^^^^^^ DOC201
+   |
+   = help: Add a "Returns" section to the docstring
diff --git a/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-yields_DOC402_sphinx.py.snap b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-yields_DOC402_sphinx.py.snap
new file mode 100644
index 0000000000000..e28a52f99f675
--- /dev/null
+++ b/crates/ruff_linter/src/rules/pydoclint/snapshots/ruff_linter__rules__pydoclint__tests__docstring-missing-yields_DOC402_sphinx.py.snap
@@ -0,0 +1,68 @@
+---
+source: crates/ruff_linter/src/rules/pydoclint/mod.rs
+---
+DOC402_sphinx.py:9:5: DOC402 `yield` is not documented in docstring
+  |
+7 |     :type num: int
+8 |     """
+9 |     yield 'test'
+  |     ^^^^^^^^^^^^ DOC402
+  |
+  = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:48:9: DOC402 `yield` is not documented in docstring
+   |
+46 |         :type num: int
+47 |         """
+48 |         yield 'test'
+   |         ^^^^^^^^^^^^ DOC402
+   |
+   = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:75:5: DOC402 `yield` is not documented in docstring
+   |
+73 |     Do something
+74 |     """
+75 |     yield None
+   |     ^^^^^^^^^^ DOC402
+76 |     yield 1
+   |
+   = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:84:5: DOC402 `yield` is not documented in docstring
+   |
+82 |     Do something
+83 |     """
+84 |     yield None
+   |     ^^^^^^^^^^ DOC402
+   |
+   = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:108:5: DOC402 `yield` is not documented in docstring
+    |
+106 |     Do something
+107 |     """
+108 |     yield None
+    |     ^^^^^^^^^^ DOC402
+109 |     yield 1
+    |
+    = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:117:5: DOC402 `yield` is not documented in docstring
+    |
+115 |     Do something
+116 |     """
+117 |     yield 1
+    |     ^^^^^^^ DOC402
+118 |     yield
+    |
+    = help: Add a "Yields" section to the docstring
+
+DOC402_sphinx.py:126:5: DOC402 `yield` is not documented in docstring
+    |
+124 |     Do something
+125 |     """
+126 |     yield
+    |     ^^^^^ DOC402
+    |
+    = help: Add a "Yields" section to the docstring
diff --git a/crates/ruff_linter/src/rules/pydocstyle/helpers.rs b/crates/ruff_linter/src/rules/pydocstyle/helpers.rs
index d802afcc69d5c..4b7ca9c03e308 100644
--- a/crates/ruff_linter/src/rules/pydocstyle/helpers.rs
+++ b/crates/ruff_linter/src/rules/pydocstyle/helpers.rs
@@ -6,10 +6,12 @@ use ruff_python_trivia::Cursor;
 use ruff_source_file::{Line, UniversalNewlines};
 use ruff_text_size::{TextRange, TextSize};
 
+use crate::checkers::ast::Checker;
 use crate::docstrings::sections::{SectionContexts, SectionKind};
 use crate::docstrings::styles::SectionStyle;
 use crate::docstrings::Docstring;
 use crate::rules::pydocstyle::settings::{Convention, Settings};
+use crate::warn_user_once;
 
 /// Return the index of the first logical line in a string.
 pub(super) fn logical_line(content: &str) -> Option<usize> {
@@ -73,6 +75,7 @@ pub(crate) fn should_ignore_definition(
 pub(crate) fn get_section_contexts<'a>(
     docstring: &'a Docstring<'a>,
     convention: Option<Convention>,
+    checker: &mut Checker,
 ) -> SectionContexts<'a> {
     match convention {
         Some(Convention::Google) => {
@@ -81,7 +84,14 @@ pub(crate) fn get_section_contexts<'a>(
         Some(Convention::Numpy) => {
             return SectionContexts::from_docstring(docstring, SectionStyle::Numpy);
         }
-        Some(Convention::Pep257) | None => {
+        Some(Convention::Sphinx) if checker.settings.preview.is_enabled() => {
+            return SectionContexts::from_docstring(docstring, SectionStyle::Sphinx);
+        }
+        Some(Convention::Pep257 | Convention::Sphinx) | None => {
+            if matches!(convention, Some(Convention::Sphinx)) {
+                warn_user_once!("Sphinx support is currently in preview. Setting convention = \"sphinx\" will be ignored.");
+            }
+
             // There are some overlapping section names, between the Google and NumPy conventions
             // (e.g., "Returns", "Raises"). Break ties by checking for the presence of some of the
             // section names that are unique to each convention.
diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs
index 10346ec19482a..f11119dd913f9 100644
--- a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs
+++ b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs
@@ -1330,9 +1330,11 @@ pub(crate) fn sections(
     match convention {
         Some(Convention::Google) => parse_google_sections(checker, docstring, section_contexts),
         Some(Convention::Numpy) => parse_numpy_sections(checker, docstring, section_contexts),
+        Some(Convention::Sphinx) => parse_sphinx_sections(checker, docstring, section_contexts),
         Some(Convention::Pep257) | None => match section_contexts.style() {
             SectionStyle::Google => parse_google_sections(checker, docstring, section_contexts),
             SectionStyle::Numpy => parse_numpy_sections(checker, docstring, section_contexts),
+            SectionStyle::Sphinx => parse_sphinx_sections(checker, docstring, section_contexts),
         },
     }
 }
@@ -1631,7 +1633,7 @@ fn blanks_and_section_underline(
 
             checker.diagnostics.push(diagnostic);
         }
-        if checker.enabled(Rule::EmptyDocstringSection) {
+        if !style.is_sphinx() && checker.enabled(Rule::EmptyDocstringSection) {
             checker.diagnostics.push(Diagnostic::new(
                 EmptyDocstringSection {
                     name: context.section_name().to_string(),
@@ -1649,7 +1651,7 @@ fn common_section(
     next: Option<&SectionContext>,
     style: SectionStyle,
 ) {
-    if checker.enabled(Rule::CapitalizeSectionName) {
+    if !style.is_sphinx() && checker.enabled(Rule::CapitalizeSectionName) {
         let capitalized_section_name = context.kind().as_str();
         if context.section_name() != capitalized_section_name {
             let section_range = context.section_name_range();
@@ -2005,6 +2007,23 @@ fn google_section(
     }
 }
 
+fn parse_sphinx_sections(
+    checker: &mut Checker,
+    docstring: &Docstring,
+    section_contexts: &SectionContexts,
+) {
+    let mut iterator = section_contexts.iter().peekable();
+    while let Some(context) = iterator.next() {
+        common_section(
+            checker,
+            docstring,
+            &context,
+            iterator.peek(),
+            SectionStyle::Sphinx,
+        );
+    }
+}
+
 fn parse_numpy_sections(
     checker: &mut Checker,
     docstring: &Docstring,
diff --git a/crates/ruff_linter/src/rules/pydocstyle/settings.rs b/crates/ruff_linter/src/rules/pydocstyle/settings.rs
index c8b05ba3c5012..2d883684e96ef 100644
--- a/crates/ruff_linter/src/rules/pydocstyle/settings.rs
+++ b/crates/ruff_linter/src/rules/pydocstyle/settings.rs
@@ -20,6 +20,8 @@ pub enum Convention {
     Google,
     /// Use NumPy-style docstrings.
     Numpy,
+    /// Use Sphinx-style docstrings.
+    Sphinx,
     /// Use PEP257-style docstrings.
     Pep257,
 }
@@ -28,47 +30,65 @@ impl Convention {
     pub const fn rules_to_be_ignored(self) -> &'static [Rule] {
         match self {
             Convention::Google => &[
-                Rule::OneBlankLineBeforeClass,
-                Rule::OneBlankLineAfterClass,
-                Rule::MultiLineSummarySecondLine,
-                Rule::SectionUnderlineNotOverIndented,
-                Rule::EndsInPeriod,
-                Rule::NonImperativeMood,
+                Rule::BlankLineAfterLastSection,
+                Rule::DashedUnderlineAfterSection,
                 Rule::DocstringStartsWithThis,
+                Rule::EndsInPeriod,
+                Rule::MultiLineSummarySecondLine,
                 Rule::NewLineAfterSectionName,
-                Rule::DashedUnderlineAfterSection,
+                Rule::NonImperativeMood,
+                Rule::OneBlankLineAfterClass,
+                Rule::OneBlankLineBeforeClass,
                 Rule::SectionUnderlineAfterName,
                 Rule::SectionUnderlineMatchesSectionLength,
-                Rule::BlankLineAfterLastSection,
+                Rule::SectionUnderlineNotOverIndented,
             ],
             Convention::Numpy => &[
-                Rule::UndocumentedPublicInit,
-                Rule::OneBlankLineBeforeClass,
+                Rule::BlankLineAfterLastSection,
+                Rule::EndsInPunctuation,
                 Rule::MultiLineSummaryFirstLine,
                 Rule::MultiLineSummarySecondLine,
                 Rule::NoSignature,
+                Rule::OneBlankLineBeforeClass,
+                Rule::SectionNameEndsInColon,
+                Rule::UndocumentedParam,
+                Rule::UndocumentedPublicInit,
+            ],
+            Convention::Sphinx => &[
                 Rule::BlankLineAfterLastSection,
+                Rule::CapitalizeSectionName,
+                Rule::DashedUnderlineAfterSection,
+                Rule::DocstringStartsWithThis,
                 Rule::EndsInPunctuation,
+                Rule::MultiLineSummaryFirstLine,
+                Rule::MultiLineSummarySecondLine,
+                Rule::NewLineAfterSectionName,
+                Rule::NoBlankLineAfterSection,
+                Rule::NoBlankLineBeforeSection,
+                Rule::OneBlankLineBeforeClass,
                 Rule::SectionNameEndsInColon,
+                Rule::SectionUnderlineAfterName,
+                Rule::SectionUnderlineMatchesSectionLength,
+                Rule::SectionUnderlineNotOverIndented,
                 Rule::UndocumentedParam,
             ],
             Convention::Pep257 => &[
-                Rule::OneBlankLineBeforeClass,
+                Rule::BlankLineAfterLastSection,
+                Rule::CapitalizeSectionName,
+                Rule::DashedUnderlineAfterSection,
+                Rule::DocstringStartsWithThis,
+                Rule::EndsInPunctuation,
                 Rule::MultiLineSummaryFirstLine,
                 Rule::MultiLineSummarySecondLine,
-                Rule::SectionNotOverIndented,
-                Rule::SectionUnderlineNotOverIndented,
-                Rule::DocstringStartsWithThis,
-                Rule::CapitalizeSectionName,
                 Rule::NewLineAfterSectionName,
-                Rule::DashedUnderlineAfterSection,
-                Rule::SectionUnderlineAfterName,
-                Rule::SectionUnderlineMatchesSectionLength,
                 Rule::NoBlankLineAfterSection,
                 Rule::NoBlankLineBeforeSection,
-                Rule::BlankLineAfterLastSection,
-                Rule::EndsInPunctuation,
+                Rule::OneBlankLineBeforeClass,
                 Rule::SectionNameEndsInColon,
+                Rule::SectionNotOverIndented,
+                Rule::SectionUnderlineAfterName,
+                Rule::SectionUnderlineMatchesSectionLength,
+                Rule::SectionUnderlineNotOverIndented,
                 Rule::UndocumentedParam,
             ],
         }
@@ -80,6 +100,7 @@ impl fmt::Display for Convention {
         match self {
             Self::Google => write!(f, "google"),
             Self::Numpy => write!(f, "numpy"),
+            Self::Sphinx => write!(f, "sphinx"),
             Self::Pep257 => write!(f, "pep257"),
         }
     }
diff --git a/crates/ruff_python_ast/src/docstrings.rs b/crates/ruff_python_ast/src/docstrings.rs
index 3722afe636b4e..303b98530055d 100644
--- a/crates/ruff_python_ast/src/docstrings.rs
+++ b/crates/ruff_python_ast/src/docstrings.rs
@@ -20,3 +20,18 @@ pub fn clean_space(indentation: &str) -> String {
         .map(|char| if char.is_whitespace() { char } else { ' ' })
         .collect()
 }
+
+/// Extract the leading whitespace and colon from a line of text within a Python docstring.
+pub fn leading_space_and_colon(line: &str) -> &str {
+    line.find(|char: char| !char.is_whitespace() && char != ':')
+        .map_or(line, |index| &line[..index])
+}
+
+/// Sphinx section section name.
+pub fn sphinx_section_name(line: &str) -> Option<&str> {
+    let mut spans = line.split(':');
+    let _indentation = spans.next()?;
+    let header = spans.next()?;
+    let _after_header = spans.next()?;
+    header.split(' ').next()
+}
diff --git a/ruff.schema.json b/ruff.schema.json
index c39a68ebd6aa7..f6b56597dfb01 100644
--- a/ruff.schema.json
+++ b/ruff.schema.json
@@ -791,6 +791,13 @@
             "numpy"
           ]
         },
+        {
+          "description": "Use Sphinx-style docstrings.",
+          "type": "string",
+          "enum": [
+            "sphinx"
+          ]
+        },
         {
           "description": "Use PEP257-style docstrings.",
           "type": "string",