Recognize new-style attrs decorators in too-few-public-methods check (#9346)

Beginning with attrs 21.1.0, the recommended way to use attrs is through
`import attrs` and using `attrs.define`/`attrs.frozen`, not `import
attr` and `attr.s` or `attr.attrs`. Pylint does understand `attr.attrs`
(#2988), but new-style uses of attrs are not understood to be data class
decorators.

Modify `_is_exempt_from_public_methods` to recognize `attrs.define` and
`attrs.frozen` in a similar way as is currently done with
`dataclasses.dataclass`.

Closes #9345.
diff --git a/doc/whatsnew/fragments/9345.false_positive b/doc/whatsnew/fragments/9345.false_positive
new file mode 100644
index 0000000..af8a386
--- /dev/null
+++ b/doc/whatsnew/fragments/9345.false_positive
@@ -0,0 +1,4 @@
+Treat `attrs.define` and `attrs.frozen` as dataclass decorators in
+`too-few-public-methods` check.
+
+Closes #9345
diff --git a/pylint/checkers/design_analysis.py b/pylint/checkers/design_analysis.py
index 8ff26ec..de9cac6 100644
--- a/pylint/checkers/design_analysis.py
+++ b/pylint/checkers/design_analysis.py
@@ -92,6 +92,8 @@
 SPECIAL_OBJ = re.compile("^_{2}[a-z]+_{2}$")
 DATACLASSES_DECORATORS = frozenset({"dataclass", "attrs"})
 DATACLASS_IMPORT = "dataclasses"
+ATTRS_DECORATORS = frozenset({"define", "frozen"})
+ATTRS_IMPORT = "attrs"
 TYPING_NAMEDTUPLE = "typing.NamedTuple"
 TYPING_TYPEDDICT = "typing.TypedDict"
 TYPING_EXTENSIONS_TYPEDDICT = "typing_extensions.TypedDict"
@@ -214,6 +216,10 @@
             or DATACLASS_IMPORT in root_locals
         ):
             return True
+        if name in ATTRS_DECORATORS and (
+            root_locals.intersection(ATTRS_DECORATORS) or ATTRS_IMPORT in root_locals
+        ):
+            return True
     return False
 
 
diff --git a/tests/functional/t/too/too_few_public_methods_37.py b/tests/functional/t/too/too_few_public_methods_37.py
index db9c9f1..3d3a125 100644
--- a/tests/functional/t/too/too_few_public_methods_37.py
+++ b/tests/functional/t/too/too_few_public_methods_37.py
@@ -8,6 +8,9 @@
 import typing
 from dataclasses import dataclass
 
+import attrs  # pylint: disable=import-error
+from attrs import define, frozen  # pylint: disable=import-error
+
 
 @dataclasses.dataclass
 class ScheduledTxSearchModel:
@@ -40,3 +43,27 @@
     def to_array(self):
         """Convert to a NumPy array `np.array((x, y, z))`."""
         return self.attr1
+
+
+@define
+class AttrsBarePoint:
+    x: float
+    y: float
+
+
+@frozen
+class AttrsBareFrozenPoint:
+    x: float
+    y: float
+
+
+@attrs.define
+class AttrsQualifiedPoint:
+    x: float
+    y: float
+
+
+@attrs.frozen
+class AttrsQualifiedFrozenPoint:
+    x: float
+    y: float