Skip to content

What tools and process should I use? #14499

Closed

Description

@hunterhogan

A specific issue, but a general question

I want to talk about networkx, but I really want to learn how to have productive conversations about complex technical topics.

The basics

My noob ignorance is a barrier

To achieve the above goals, I need to correctly navigate git, GitHub, typeshed pull request processes (OR to know that I should not use a pull request and to know what other tool I should use), diagnostic errors from umpteen apps, and, you know, to accurately annotate a sophisticated package. Furthermore, I have only contributed to stdlib, and it feels strange to me to discuss an actively maintained third-party package. I feel like there must be etiquette for this, but I don't know what that might be.

Plus, I have no self-confidence about most topics, and I hate that I keep pissing people off.

Another (self-inflicted) complication

The typeshed stubs do not have docstrings. My stubs have edited docstrings based on the original docstrings. This is probably a trivial issue, but it is another issue.

Guidance?

The diff tool in a pull request seems useful, but I am not ready to claim that my versions of the three files should be part of typeshed, so a pull request seems like the wrong tool.

The amount of information seems excessive for Python Type School!.

An important feature of a good process is the ability to accurately and quickly identify "misfits." If my suggested annotations are patently wrong, for example, a good process allows y'all to avoid wasting your time.

There is probably a smart way, or at least a smarter way, for me to start a conversation about this, but I don't know what it is.

Activity

  1. Akuli commented on Jul 31, 2025

    @Akuli
    Collaborator

    Let me first answer a few of your simpler questions, then your "big" main question about diffing.

    There is probably a smart way, or at least a smarter way, for me to start a conversation about this, but I don't know what it is.

    This is pretty good actually! :) Asking on the issue tracker is the right thing to do if you're not sure whether you should make a pull request.

    it feels strange to me to discuss an actively maintained third-party package. I feel like there must be etiquette for this, but I don't know what that might be.

    Contributing to third-party packages is very similar to contributing to stdlib. As a contributor, you don't need to worry about this.

    The typeshed stubs do not have docstrings. My stubs have edited docstrings based on the original docstrings. This is probably a trivial issue, but it is another issue.

    The docstrings will show up in the diff. To get nice diffs, both compared files should be in a similar format (e.g. both contain docstrings or neither contains docstrings).


    Now, let's tackle your big "main" question:

    The diff tool in a pull request seems useful, but I am not ready to claim that my versions of the three files should be part of typeshed, so a pull request seems like the wrong tool.

    You're right, a pull request is not needed for this. You want to get a diff without making a GitHub pull request. Let me walk you through that.

    Let's create two files, foo.pyi and bar.pyi. Here is foo.pyi (typeshed's stub file):

    import os.path
    
    def foo() -> None: ...
    def bar() -> itn: ...
    def baz() -> str: ...

    And here is bar.pyi (your stub file):

    import os.path
    
    def foo() -> None: ...
    def bar() -> int: ...
    def baz() -> str: ...

    We want to see a diff similar to what GitHub shows, but without a pull request, i.e. notice that return type of bar() is misspelled. Here's how to get that diff (assuming Windows, since you're on windows if I remember correctly).

    Option 1: using diff

    1. Open Git Bash or WSL. Doesn't really matter which. (Other terminal things may also work.)
    2. Go to the folder that contains foo.pyi and bar.pyi with cd. For example cd Desktop/typeshed. Use / as path separator, not \. (Alternatively, right-click a folder and select "Git Bash here" to skip this step).
    3. Run the following command to compare the files:
      diff -u --color foo.pyi bar.pyi
      
      If the files are in different folders, supply their paths as needed, e.g. diff -u --color folder1/foo.pyi folder2/subfolder/bar.pyi

    You should get something like this:

    Image

    Option 2: using Git

    1. Add foo.pyi to a Git repository if it isn't already. (In your case, just git clone typeshed and you're done with this step.)
    2. Check that git status doesn't show anything related to foo.pyi.
    3. Replace content of foo.pyi with your bar.pyi. Just copy it on top.
    4. Check that git status says "modified: foo.pyi" in red. (Red means it's not about to be committed.)
    5. Run git diff. This tells git to report what changed.
    6. (Optional) Run git restore foo.pyi. This brings back the original file contents.
    7. (Optional) Check that git status doesn't show anything related to foo.pyi.
    Image
  2. hunterhogan commented on Jul 31, 2025

    @hunterhogan
    ContributorAuthor

    Thank you for the detailed response.

    Steps taken:

    1. Script to remove docstrings.
    2. (.venv) C:\apps\stubFileNotFound>black --config c:\clones\typeshed\pyproject.toml C:\data\networkx
    3. (.venv) C:\apps\stubFileNotFound>black --config c:\clones\typeshed\pyproject.toml "C:\clones\typeshed\stubs\networkx\networkx\classes\graph.pyi" but it didn't change the file, so the imports are sorted differently.
    4. WinMerge. I despise git, and I can't decipher the + - stuff, so that would preclude a conversation.

    I think this is the same format as git.
    digraph.sillyFormat.txt
    graph.sillyFormat.txt

    The same data, but rename to .htm to view.
    digraph.htm.txt
    graph.htm.txt

    If this process works, I'll make the LCA algorithm, too.

    But, these objects are the most important, right?

  3. Akuli commented on Jul 31, 2025

    @Akuli
    Collaborator

    WinMerge. I despise git, and I can't decipher the + - stuff, so that would preclude a conversation.

    While Git could quite conveniently do the diffing, help you select which parts of the diff to include in a PR, and then help you create the PR, I understand that you don't like Git and you don't want to do any of this with git. I was the same way when I was getting started with git :)

    The diff tool, my Option 1, has nothing to do with git. It does the thing you did with WinMerge, but on command line. I mentioned Git Bash, but you can just as well use WSL instead, or anything else that happens to have a working diff program. Git comes with diff, but it is not the only way to get the diff program.

    But, these objects are the most important, right?

    Yes, these diffs are what you care about. Next you need to study them and figure out what things to include in pull requests.

    I looked at your digraph diff. It seems to be backwards compared to how we are used to reading diffs: typeshed's version is + (green) and yours is - (red).

    Here are examples of changes that I would include in a PR: (I'm not sure whether all of these are correct, but we can figure it out when reviewing)

    • Your in_edges returns InEdgeView. Typeshed's in_edges returns OutEdgeView, which seems like a typo in typeshed.
    • Typeshed's in_degree and out_degree can be ints or views. Yours can only be views. I haven't checked, but my guess is that you are right and they are always views.

    And here are examples of changes that don't make the cut:

    • Your version of the stub includes private things, such as _adj and _CachedPropertyResetterPred. In typeshed, we only add private things if someone needs them for some specific use case.
    • Your succ and pred use Incomplete where typeshed uses Any. While they are technically the same, there is a "cultural" difference that is often discussed here. IMO Any is better in this case, because the data comes from adding edges, and there's no good way to teach that to type checkers. However, we would appreciate adding a comment that explains why Any is used.
    • You have included various things that are inherited from the base class Graph. In typeshed, we like to repeat things inherited from a base class only if we want something different than the definition in base class (such as the to_undirected method).

    I would split these changes to at least 3 pull requests, one per file. We have many open pull requests, but smaller pull requests are still easier to review.

  4. hunterhogan commented on Aug 1, 2025

    @hunterhogan
    ContributorAuthor

    diff

    hunte@duda:~$ diff -u --color /mnt/c/clones/typeshed/stubs/networkx/networkx/classes/graph.pyi /mnt/c/data/networkx/graph.pyi
    --- /mnt/c/clones/typeshed/stubs/networkx/networkx/classes/graph.pyi    2025-08-01 05:03:18.080726700 -0500
    +++ /mnt/c/data/networkx/graph.pyi      2025-08-01 04:58:32.389885100 -0500
    @@ -1,5 +1,4 @@
    -from _typeshed import Incomplete
    -from collections.abc import Callable, Collection, Hashable, Iterable, Iterator, Mapping, MutableMapping
    +from collections.abc import Callable, Collection, Hashable, Iterable, Iterator, MutableMapping
     from functools import cached_property
     from typing import Any, ClassVar, TypeVar, overload
     from typing_extensions import Self, TypeAlias
    @@ -7,7 +6,7 @@
     import numpy
     from networkx.classes.coreviews import AdjacencyView, AtlasView
     from networkx.classes.digraph import DiGraph
    -from networkx.classes.reportviews import DegreeView, DiDegreeView, NodeView, OutEdgeView
    +from networkx.classes.reportviews import DegreeView, EdgeView, NodeView
    
     _Node = TypeVar("_Node", bound=Hashable)
     _NodeWithData: TypeAlias = tuple[_Node, dict[str, Any]]
    @@ -29,6 +28,7 @@
     __all__ = ["Graph"]
    
     class Graph(Collection[_Node]):
    +
         __networkx_backend__: ClassVar[str]
         node_dict_factory: ClassVar[_MapFactory]
         node_attr_dict_factory: ClassVar[_MapFactory]
    @@ -38,12 +38,13 @@
         graph_attr_dict_factory: ClassVar[_MapFactory]
    
         graph: dict[str, Any]
    +    __networkx_cache__: dict[str, Any]
    
         def to_directed_class(self) -> type[DiGraph[_Node]]: ...
         def to_undirected_class(self) -> type[Graph[_Node]]: ...
    -    def __init__(self, incoming_graph_data: _Data[_Node] | None = None, **attr) -> None: ...
    +    def __init__(self, incoming_graph_data: _Data[_Node] | None = None, **attr: Any) -> None: ...
         @cached_property
    -    def adj(self) -> AdjacencyView[_Node, _Node, dict[str, Incomplete]]: ...
    +    def adj(self) -> AdjacencyView[_Node, _Node, dict[str, Any]]: ...
         @property
         def name(self) -> str: ...
         @name.setter
    @@ -52,8 +53,8 @@
         def __iter__(self) -> Iterator[_Node]: ...
         def __contains__(self, n: object) -> bool: ...
         def __len__(self) -> int: ...
    -    def add_node(self, node_for_adding: _Node, **attr: Any) -> None: ...  # attr: Set or change node attributes using key=value
    -    def add_nodes_from(self, nodes_for_adding: Iterable[_NodePlus[_Node]], **attr) -> None: ...
    +    def add_node(self, node_for_adding: _Node, **attr: Any) -> None: ...
    +    def add_nodes_from(self, nodes_for_adding: Iterable[_NodePlus[_Node]], **attr: Any) -> None: ...
         def remove_node(self, n: _Node) -> None: ...
         def remove_nodes_from(self, nodes: Iterable[_Node]) -> None: ...
         @cached_property
    @@ -61,14 +62,13 @@
         def number_of_nodes(self) -> int: ...
         def order(self) -> int: ...
         def has_node(self, n: _Node) -> bool: ...
    -    # attr: Edge data (or labels or objects) can be assigned using keyword arguments
         def add_edge(self, u_of_edge: _Node, v_of_edge: _Node, **attr: Any) -> None: ...
    -    def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr) -> None: ...
    +    def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr: Any) -> None: ...
         def add_weighted_edges_from(
    -        self, ebunch_to_add: Iterable[tuple[_Node, _Node, Incomplete]], weight: str = "weight", **attr
    +        self, ebunch_to_add: Iterable[tuple[_Node, _Node, float]], weight: str = "weight", **attr: Any
         ) -> None: ...
         def remove_edge(self, u: _Node, v: _Node) -> None: ...
    -    def remove_edges_from(self, ebunch: Iterable[_EdgePlus[_Node]]) -> None: ...
    +    def remove_edges_from(self, ebunch: Iterable[_Edge[_Node]]) -> None: ...
         @overload
         def update(self, edges: Graph[_Node], nodes: None = None) -> None: ...
         @overload
    @@ -78,11 +78,11 @@
         def has_edge(self, u: _Node, v: _Node) -> bool: ...
         def neighbors(self, n: _Node) -> Iterator[_Node]: ...
         @cached_property
    -    def edges(self) -> OutEdgeView[_Node]: ...
    -    def get_edge_data(self, u: _Node, v: _Node, default=None) -> Mapping[str, Incomplete]: ...
    -    def adjacency(self) -> Iterator[tuple[_Node, Mapping[_Node, Mapping[str, Incomplete]]]]: ...
    +    def edges(self) -> EdgeView[_Node]: ...
    +    def get_edge_data(self, u: _Node, v: _Node, default: Any = None) -> dict[str, Any]: ...
    +    def adjacency(self) -> Iterator[tuple[_Node, dict[_Node, dict[str, Any]]]]: ...
         @cached_property
    -    def degree(self) -> DegreeView[_Node] | DiDegreeView[_Node]: ...  # Include subtypes' possible return types
    +    def degree(self) -> int | DegreeView[_Node]: ...
         def clear(self) -> None: ...
         def clear_edges(self) -> None: ...
         def is_multigraph(self) -> bool: ...

    git diff

    (.v312) C:\clones\typeshed>git diff
    diff --git a/stubs/networkx/networkx/classes/graph.pyi b/stubs/networkx/networkx/classes/graph.pyi
    index ec771d64e..782d9530c 100644
    --- a/stubs/networkx/networkx/classes/graph.pyi
    +++ b/stubs/networkx/networkx/classes/graph.pyi
    @@ -1,5 +1,4 @@
    -from _typeshed import Incomplete
    -from collections.abc import Callable, Collection, Hashable, Iterable, Iterator, Mapping, MutableMapping
    +from collections.abc import Callable, Collection, Hashable, Iterable, Iterator, MutableMapping
     from functools import cached_property
     from typing import Any, ClassVar, TypeVar, overload
     from typing_extensions import Self, TypeAlias
    @@ -7,7 +6,7 @@ from typing_extensions import Self, TypeAlias
     import numpy
     from networkx.classes.coreviews import AdjacencyView, AtlasView
     from networkx.classes.digraph import DiGraph
    -from networkx.classes.reportviews import DegreeView, DiDegreeView, NodeView, OutEdgeView
    +from networkx.classes.reportviews import DegreeView, EdgeView, NodeView
     
     _Node = TypeVar("_Node", bound=Hashable)
     _NodeWithData: TypeAlias = tuple[_Node, dict[str, Any]]
    @@ -29,6 +28,7 @@ _Data: TypeAlias = (
     __all__ = ["Graph"]
     
     class Graph(Collection[_Node]):
    +
         __networkx_backend__: ClassVar[str]
         node_dict_factory: ClassVar[_MapFactory]
         node_attr_dict_factory: ClassVar[_MapFactory]
    @@ -38,12 +38,13 @@ class Graph(Collection[_Node]):
         graph_attr_dict_factory: ClassVar[_MapFactory]
     
         graph: dict[str, Any]
    +    __networkx_cache__: dict[str, Any]
     
         def to_directed_class(self) -> type[DiGraph[_Node]]: ...
         def to_undirected_class(self) -> type[Graph[_Node]]: ...
    -    def __init__(self, incoming_graph_data: _Data[_Node] | None = None, **attr) -> None: ...
    +    def __init__(self, incoming_graph_data: _Data[_Node] | None = None, **attr: Any) -> None: ...
         @cached_property
    -    def adj(self) -> AdjacencyView[_Node, _Node, dict[str, Incomplete]]: ...
    +    def adj(self) -> AdjacencyView[_Node, _Node, dict[str, Any]]: ...
         @property
         def name(self) -> str: ...
         @name.setter
    @@ -52,8 +53,8 @@ class Graph(Collection[_Node]):
         def __iter__(self) -> Iterator[_Node]: ...
         def __contains__(self, n: object) -> bool: ...
         def __len__(self) -> int: ...
    -    def add_node(self, node_for_adding: _Node, **attr: Any) -> None: ...  # attr: Set or change node attributes using key=value
    -    def add_nodes_from(self, nodes_for_adding: Iterable[_NodePlus[_Node]], **attr) -> None: ...
    +    def add_node(self, node_for_adding: _Node, **attr: Any) -> None: ...
    +    def add_nodes_from(self, nodes_for_adding: Iterable[_NodePlus[_Node]], **attr: Any) -> None: ...
         def remove_node(self, n: _Node) -> None: ...
         def remove_nodes_from(self, nodes: Iterable[_Node]) -> None: ...
         @cached_property
    @@ -61,14 +62,13 @@ class Graph(Collection[_Node]):
         def number_of_nodes(self) -> int: ...
         def order(self) -> int: ...
         def has_node(self, n: _Node) -> bool: ...
    -    # attr: Edge data (or labels or objects) can be assigned using keyword arguments
         def add_edge(self, u_of_edge: _Node, v_of_edge: _Node, **attr: Any) -> None: ...
    -    def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr) -> None: ...
    +    def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr: Any) -> None: ...
         def add_weighted_edges_from(
    -        self, ebunch_to_add: Iterable[tuple[_Node, _Node, Incomplete]], weight: str = "weight", **attr
    +        self, ebunch_to_add: Iterable[tuple[_Node, _Node, float]], weight: str = "weight", **attr: Any
         ) -> None: ...
         def remove_edge(self, u: _Node, v: _Node) -> None: ...
    -    def remove_edges_from(self, ebunch: Iterable[_EdgePlus[_Node]]) -> None: ...
    +    def remove_edges_from(self, ebunch: Iterable[_Edge[_Node]]) -> None: ...
         @overload
         def update(self, edges: Graph[_Node], nodes: None = None) -> None: ...
         @overload
    @@ -78,11 +78,11 @@ class Graph(Collection[_Node]):
         def has_edge(self, u: _Node, v: _Node) -> bool: ...
         def neighbors(self, n: _Node) -> Iterator[_Node]: ...
         @cached_property
    -    def edges(self) -> OutEdgeView[_Node]: ...
    -    def get_edge_data(self, u: _Node, v: _Node, default=None) -> Mapping[str, Incomplete]: ...
    -    def adjacency(self) -> Iterator[tuple[_Node, Mapping[_Node, Mapping[str, Incomplete]]]]: ...
    +    def edges(self) -> EdgeView[_Node]: ...
    +    def get_edge_data(self, u: _Node, v: _Node, default: Any = None) -> dict[str, Any]: ...
    +    def adjacency(self) -> Iterator[tuple[_Node, dict[_Node, dict[str, Any]]]]: ...
         @cached_property
    -    def degree(self) -> DegreeView[_Node] | DiDegreeView[_Node]: ...  # Include subtypes' possible return types
    +    def degree(self) -> int | DegreeView[_Node]: ...
         def clear(self) -> None: ...
         def clear_edges(self) -> None: ...
         def is_multigraph(self) -> bool: ...
    (END)

    fwiw, I'm a trained editor, pioneered web usability in the 90s, and cut my teeth on line basic: Wordstar 2000 was better than diff or git.

    My post is incomplete due to pain. I'll try again later.

  5. hunterhogan commented on Aug 2, 2025

    @hunterhogan
    ContributorAuthor

    You have included various things that are inherited from the base class Graph. In typeshed, we like to repeat things inherited from a base class only if we want something different than the definition in base class (such as the to_undirected method).

    Therefore, I am starting with Graph.

    I looked at your digraph diff. It seems to be backwards compared to how we are used to reading diffs: typeshed's version is + (green) and yours is - (red).

    Is the above version backwards or normal?

    • Your succ and pred use Incomplete where typeshed uses Any.

    This is confusing to me because my versions don't use Incomplete or have any missing annotations.

    I'm now trying to decipher the stubtest errors.

    Details

    Command output:

    error: networkx.MultiDiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx_init_.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multidigraph.py:417
    def (self, u_for_edge, v_for_edge, key=None, **attr)

    error: networkx.MultiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx_init_.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multigraph.py:431
    def (self, u_for_edge, v_for_edge, key=None, **attr)

    error: networkx.classes.MultiDiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx\classes_init_.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multidigraph.py:417
    def (self, u_for_edge, v_for_edge, key=None, **attr)

    error: networkx.classes.MultiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx\classes_init_.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multigraph.py:431
    def (self, u_for_edge, v_for_edge, key=None, **attr)

    error: networkx.classes.multidigraph.MultiDiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx\classes\multidigraph.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multidigraph.py:417
    def (self, u_for_edge, v_for_edge, key=None, **attr)

    error: networkx.classes.multigraph.MultiGraph.add_edge is inconsistent, runtime argument "key" has a default value but stub argument does not
    Stub: in file C:\clones\typeshed\stubs\networkx\networkx\classes\multigraph.pyi:21
    def (self: networkx.classes.multigraph.MultiGraph[_Node1], u_for_edge: _Node1, v_for_edge: _Node`1, key: Union[typing.Hashable, builtins.int], **attr: Any) -> Union[typing.Hashable, builtins.int]
    Runtime: in file C:\Users\hunte\AppData\Local\Temp\stubtest-fs1zytcl\Lib\site-packages\networkx\classes\multigraph.py:431
    def (self, u_for_edge, v_for_edge, key=None, **attr)

  6. Akuli commented on Aug 2, 2025

    @Akuli
    Collaborator

    The PR looks reasonable. Thanks!

    The above diffs also look much better. Something weird happened previously.

  7. hunterhogan commented on Aug 4, 2025

    @hunterhogan
    ContributorAuthor

    You have included various things that are inherited from the base class Graph. In typeshed, we like to repeat things inherited from a base class only if we want something different than the definition in base class (such as the to_undirected method).

    Therefore, I am starting with Graph.

    Because DiGraph depends on Graph, I assumed it would be wise to implement Graph first. Then I could work on DiGraph with a solid foundation.

  8. hunterhogan commented on Aug 17, 2025

    @hunterhogan
    ContributorAuthor

    Diff from mypy_primer, showing the effect of this PR on open source code:

    discord.py (https://github.com/Rapptz/discord.py)
    - discord/ext/commands/hybrid.py:883: error: Overlap between argument names and ** TypedDict items: "name", "with_app_command"  [misc]
    + discord/ext/commands/hybrid.py:883: error: Overlap between argument names and ** TypedDict items: "with_app_command", "name"  [misc]
    - discord/ext/commands/hybrid.py:935: error: Overlap between argument names and ** TypedDict items: "name", "with_app_command"  [misc]
    + discord/ext/commands/hybrid.py:935: error: Overlap between argument names and ** TypedDict items: "with_app_command", "name"  [misc]
    

    Originally posted by @github-actions[bot] in #14582 (comment)

    Line 883

    def hybrid_command(
        name: Union[str, app_commands.locale_str] = MISSING,
        *,
        with_app_command: bool = True,
        **attrs: Unpack[_HybridCommandDecoratorKwargs],  # type: ignore # name, with_app_command
    ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], HybridCommand[CogT, P, T]]:

    Line 935

    def hybrid_group(
        name: Union[str, app_commands.locale_str] = MISSING,
        *,
        with_app_command: bool = True,
        **attrs: Unpack[_HybridGroupDecoratorKwargs],  # type: ignore # name, with_app_command
    ) -> Callable[[CommandCallback[CogT, ContextT, P, T]], HybridGroup[CogT, P, T]]:

    I don't understand what I need to do. #14582

  9. hauntsaninja commented on Aug 17, 2025

    @hauntsaninja
    Collaborator

    There was a mypy bug resulting in nondeterministic output that was fixed promptly in python/mypy#19666. You can safely ignore it.

    More detail: mypy_primer shows the difference in output between two runs of mypy (in this case, one with the version of typeshed from your PR, one with the version of typeshed from master). The idea being, if your PR affects mypy's output in some way, we will see the diff in mypy output. In the comment, you can see that the only thing in the diff is that the order of some arguments in an error message has changed (which is a harmless thing to have changed, and will not stop changing once the above mentioned fix gets picked up).

  10. TomerGodinger commented on Aug 17, 2025

    @TomerGodinger

    I think there was some mixup here, specifically regarding this bit in one of Akuli's posts above:

    Typeshed's in_degree and out_degree can be ints or views. Yours can only be views. I haven't checked, but my guess is that you are right and they are always views.

    Indeed, it can only be a view, but the merged PR has changed the type to include int, which now causes the following error from Mypy when using e.g. some_graph.in_degree(some_node):

    error: "int" not callable  [operator]
    

    I haven't checked but I believe the same problem exists for out_degree.

    @hunterhogan Can we please revert the changes to these two lines?

    @cached_property
    def in_degree(self) -> int | InDegreeView[_Node] | InMultiDegreeView[_Node]: ...
    @cached_property
    def out_degree(self) -> int | OutDegreeView[_Node] | OutMultiDegreeView[_Node]: ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions