Browse Source

Typecheck everything and fix issues hidden before

Getty Ritter 2 years ago
parent
commit
e5dcdca48a
8 changed files with 35 additions and 18 deletions
  1. 1 1
      lc/app.py
  2. 3 3
      lc/model.py
  3. 1 2
      lc/view.py
  4. 4 4
      lc/web.py
  5. 9 0
      stubs/playhouse/sqlite_ext.py
  6. 9 1
      stubs/pytest.py
  7. 1 1
      tasks.py
  8. 7 6
      tests/model.py

+ 1 - 1
lc/app.py

@@ -81,7 +81,7 @@ class CreateUser(Endpoint):
         req = self.request_data(r.NewUser).to_user_request()
         u = m.User.from_invite(req, token)
         flask.session["auth"] = req.to_token()
-        return self.api_ok(u.base_url(), u)
+        return self.api_ok(u.base_url(), u.to_dict())
 
 
 @endpoint("/u/<string:slug>")

+ 3 - 3
lc/model.py

@@ -72,7 +72,7 @@ class User(Model):
         return f"/u/{self.name}"
 
     def get_links(
-        self, as_user: r.User, page: int
+        self, as_user: Optional['User'], page: int
     ) -> Tuple[List[v.Link], v.Pagination]:
         links = (
             Link.select()
@@ -171,7 +171,7 @@ class Link(Model):
             self.private = link.private
             self.save()
 
-    def to_view(self, as_user: User) -> v.Link:
+    def to_view(self, as_user: Optional[User]) -> v.Link:
         return v.Link(
             id=self.id,
             url=self.url,
@@ -203,7 +203,7 @@ class Tag(Model):
     def url(self) -> str:
         return f"/u/{self.user.name}/t/{self.name}"
 
-    def get_links(self, as_user: r.User, page: int) -> Tuple[List[Link], v.Pagination]:
+    def get_links(self, as_user: Optional[User], page: int) -> Tuple[List[Link], v.Pagination]:
         links = [
             ht.link.to_view(as_user)
             for ht in HasTag.select()

+ 1 - 2
lc/view.py

@@ -35,7 +35,6 @@ class UserInvite(View):
     claimant: str
     token: str
 
-
 @dataclass
 class AdminPane(View):
     invites: List[UserInvite]
@@ -87,4 +86,4 @@ class Message(View):
 class Page(View):
     title: str
     content: str
-    user: Optional[str]
+    user: Optional[Any]

+ 4 - 4
lc/web.py

@@ -91,11 +91,11 @@ class Endpoint:
                 # should redirect to the page where that information
                 # can be viewed instead of returning that
                 # information. (I think.)
-                api_ok = self.api_post(*args, **kwargs)
+                api_ok = self.api_post(*args, **kwargs) # type: ignore
                 assert isinstance(api_ok, ApiOK)
                 return flask.jsonify(api_ok.response)
             elif flask.request.method == "DELETE":
-                return flask.jsonify(self.api_delete(*args, **kwargs).response)
+                return flask.jsonify(self.api_delete(*args, **kwargs).response) # type: ignore
             elif (
                 flask.request.method in ["GET", "HEAD"]
                 and flask.request.content_type == "application/json"
@@ -106,7 +106,7 @@ class Endpoint:
                 # I like using the HTTP headers to distinguish these
                 # cases, while other APIs tend to have a separate /api
                 # endpoint to do this.
-                return flask.jsonify(self.api_get(*args, **kwargs).response)
+                return flask.jsonify(self.api_get(*args, **kwargs).response) # type: ignore
         # if an exception arose from an "API method", then we should
         # report it as JSON
         except e.LCException as exn:
@@ -127,7 +127,7 @@ class Endpoint:
         # if we're here, it means we're just trying to get a typical
         # HTML request.
         try:
-            return self.html(*args, **kwargs)
+            return self.html(*args, **kwargs)  # type: ignore
         except e.LCException as exn:
             page = render(
                 "main",

+ 9 - 0
stubs/playhouse/sqlite_ext.py

@@ -7,3 +7,12 @@ class SqliteExtDatabase:
 
     def atomic(self):
         pass
+
+    def init(self, path: str):
+        pass
+
+    def close(self):
+        pass
+
+    def create_tables(self, tables: typing.List[typing.Any], safe: bool = True):
+        pass

+ 9 - 1
stubs/pytest.py

@@ -1,2 +1,10 @@
-def raises(e: Exception) -> object:
+from typing import Type
+
+class RaisesContext:
+    def __enter__(self):
+        pass
+    def __exit__(self, _1, _2, _3):
+        pass
+
+def raises(e: Type[Exception]) -> RaisesContext:
     pass

+ 1 - 1
tasks.py

@@ -54,7 +54,7 @@ def populate(c):
 @task
 def tc(c):
     """Typecheck with mypy"""
-    c.run("MYPYPATH=$(pwd)/stubs poetry run mypy lc/*.py tests/*.py scripts/*.py")
+    c.run("MYPYPATH=$(pwd)/stubs poetry run mypy --check-untyped-defs lc/*.py tests/*.py scripts/*.py")
 
 
 @task

+ 7 - 6
tests/model.py

@@ -144,7 +144,7 @@ class Testdb:
         req = r.Link("http://foo.com", "foo", "", False, ["foo", "bar"])
         l = m.Link.from_request(u, req)
         assert l.name == req.name
-        assert l.tags == ["foo", "bar"]
+        assert l.tags == ["foo", "bar"] # type: ignore
 
         # check the in-place update
         req.name = "bar"
@@ -157,8 +157,9 @@ class Testdb:
         self.check_tags(l, req.tags)
 
         # check that the link was persisted
-        l = m.Link.by_id(l.id)
-        assert l.name == req.name
-        assert l.private
-        assert l.created != req.created
-        self.check_tags(l, req.tags)
+        l2 = m.Link.by_id(l.id)
+        assert l2
+        assert l2.name == req.name
+        assert l2.private
+        assert l2.created != req.created
+        self.check_tags(l2, req.tags)