Repository: pallets/werkzeug

Issue:
RuleFactories have incorrect type annotations
The `__init__()` functions of most RuleFactories in `routing.py` have incorrect type annotations. The classes in question are `Subdomain`, `Submount`, `EndpointPrefix` and `RuleTemplateFactory`. All respective `__init__()` methods have the type of their `rules` parameter declared as `Iterable[Rule]`, when it should be `Iterable[RuleFactory]`.

I noticed this when upgrading werkzeug to 2.0.0 as this update introduced type annotations. My `Map` contains several `Submounts` which in turn contain other `Submounts`, which works perfectly fine. The new type annotations, however, don't allow this as `Submounts` aren't `Rules`:
```
aas/adapter/http.py:334: error: List item 0 has incompatible type "Submount"; expected "Rule"
```  
  
  
#### Why I believe these type annotations are incorrect:
The `get_rules()` method of these `RuleFactories` contains the following loop:
```python
for rulefactory in self.rules:
```
The naming here makes it pretty clear to me that `self.rules` (which is assigned directly from the `rules` parameter of the `__init__()` method) contains rule factories and not just rules. Also there would be no usecase for a `get_rules()` function if `self.rules` already only contained rules.
This and the fact that my code, in which I use nested `RuleFactories`, works, lead me to believe that the type annotation here are indeed wrong.

If confirmed, I'd be happy to provide a PR to fix this issue.


Discussion:
I believe I used `Rule` because that's the much more common case, and `RuleFactory` has other APIs that sort of make this type cascade. Can't really remember, but I recall it being less clear with the `RuleFactory`. PRs welcome though if you want to explore what it would look like.

Resolving patch:
diff --git a/src/werkzeug/routing.py b/src/werkzeug/routing.py
--- a/src/werkzeug/routing.py
+++ b/src/werkzeug/routing.py
@@ -403,7 +403,7 @@ class Subdomain(RuleFactory):
     for the current request.
     """
 
-    def __init__(self, subdomain: str, rules: t.Iterable["Rule"]) -> None:
+    def __init__(self, subdomain: str, rules: t.Iterable[RuleFactory]) -> None:
         self.subdomain = subdomain
         self.rules = rules
 
@@ -429,7 +429,7 @@ class Submount(RuleFactory):
     Now the rule ``'blog/show'`` matches ``/blog/entry/<entry_slug>``.
     """
 
-    def __init__(self, path: str, rules: t.Iterable["Rule"]) -> None:
+    def __init__(self, path: str, rules: t.Iterable[RuleFactory]) -> None:
         self.path = path.rstrip("/")
         self.rules = rules
 
@@ -454,7 +454,7 @@ class EndpointPrefix(RuleFactory):
         ])
     """
 
-    def __init__(self, prefix: str, rules: t.Iterable["Rule"]) -> None:
+    def __init__(self, prefix: str, rules: t.Iterable[RuleFactory]) -> None:
         self.prefix = prefix
         self.rules = rules
 
@@ -499,7 +499,9 @@ class RuleTemplateFactory(RuleFactory):
     :internal:
     """
 
-    def __init__(self, rules: t.Iterable["Rule"], context: t.Dict[str, t.Any]) -> None:
+    def __init__(
+        self, rules: t.Iterable[RuleFactory], context: t.Dict[str, t.Any]
+    ) -> None:
         self.rules = rules
         self.context = context
 


Test patch: