{"action":"created","comment":{"url":"https://api.github.com/repos/python/peps/pulls/comments/112432436","pull_request_review_id":33744406,"id":112432436,"diff_hunk":"@@ -439,98 +448,123 @@ but a static type checker will handle them specially. Subclassing a protocol\n class would not turn the subclass into a protocol unless it also has\n ``typing.Protocol`` as an explicit base class. Without this base, the class\n is \"downgraded\" to a regular ABC that cannot be used with structural\n-subtyping.\n+subtyping. The rationale for this rule is that we don't want to accidentally\n+have some class act as a protocol just because one of its base classes\n+happens to be one. We still slightly prefer nominal subtyping over structural\n+subtyping in the static typing world.\n \n A subprotocol can be defined by having *both* one or more protocols as\n immediate base classes and also having ``typing.Protocol`` as an immediate\n base class::\n \n   from typing import Sized, Protocol\n \n-  class SizedAndCloseable(Sized, Protocol):\n+  class SizedAndClosable(Sized, Protocol):\n       def close(self) -> None:\n           ...\n \n-Now the protocol ``SizedAndCloseable`` is a protocol with two methods,\n+Now the protocol ``SizedAndClosable`` is a protocol with two methods,\n ``__len__`` and ``close``. If one omits ``Protocol`` in the base class list,\n this would be a regular (non-protocol) class that must implement ``Sized``.\n-If ``Protocol`` is included in the base class list, all the other base classes\n-must be protocols. A protocol can't extend a regular class.\n-\n-Alternatively, one can implement ``SizedAndCloseable`` like this, assuming\n-the existence of ``SupportsClose`` from the example in `definition`_ section::\n+Alternatively, one can implement ``SizedAndClosable`` protocol by merging\n+the ``SupportsClose`` protocol from the example in `definition`_ section\n+with ``typing.Sized``::\n \n   from typing import Sized\n \n-  class SupportsClose(...): ...  # Like above\n+  class SupportsClose(Protocol):\n+      def close(self) -> None:\n+          ...\n \n-  class SizedAndCloseable(Sized, SupportsClose, Protocol):\n+  class SizedAndClosable(Sized, SupportsClose, Protocol):\n       pass\n \n The two definitions of ``SizedAndClosable`` are equivalent.\n Subclass relationships between protocols are not meaningful when\n considering subtyping, since structural compatibility is\n the criterion, not the MRO.\n \n-Note that rules around explicit subclassing are different from regular ABCs,\n-where abstractness is simply defined by having at least one abstract method\n-being unimplemented. Protocol classes must be marked *explicitly*.\n+If ``Protocol`` is included in the base class list, all the other base classes\n+must be protocols. A protocol can't extend a regular class, see `rejected`_\n+ideas for rationale. Note that rules around explicit subclassing are different\n+from regular ABCs, where abstractness is simply defined by having at least one\n+abstract method being unimplemented. Protocol classes must be marked\n+*explicitly*.\n \n \n-Generic and recursive protocols\n--------------------------------\n+Generic protocols\n+-----------------\n \n Generic protocols are important. For example, ``SupportsAbs``, ``Iterable``\n and ``Iterator`` are generic protocols. They are defined similar to normal\n non-protocol generic types::\n \n-  T = TypeVar('T', covariant=True)\n-\n   class Iterable(Protocol[T]):\n       @abstractmethod\n       def __iter__(self) -> Iterator[T]:\n           ...\n \n-Note that ``Protocol[T, S, ...]`` is allowed as a shorthand for\n-``Protocol, Generic[T, S, ...]``.\n+``Protocol[T, S, ...]`` is allowed as a shorthand for\n+``Protocol, Generic[T, S, ...]``. Declaring variance is not necessary for\n+protocol classes, since it can be inferred from a protocol definition.\n+Example::\n+\n+  class Box(Protocol[T]):\n+      content: T\n+\n+  x: Box[float]\n+  y: Box[int]\n+  x = y  # This is OK due to inferred covariance of the protocol 'Box'.\n+\n+\n+Recursive protocols\n+-------------------\n \n Recursive protocols are also supported. Forward references to the protocol\n class names can be given as strings as specified by PEP 484. Recursive\n-protocols will be useful for representing self-referential data structures\n+protocols are useful for representing self-referential data structures\n like trees in an abstract fashion::\n \n   class Traversable(Protocol):\n       leaves: Iterable['Traversable']\n \n+Note that for recursive protocols, a class is considered a subtype of\n+the protocol in situations where such decision depends on itself.\n+Continuing the previous example::\n+\n+  class SimpleTree:\n+      leaves: List['SimpleTree']\n+\n+  root: Traversable = SimpleTree()  # OK\n+\n+  class Tree(Generic[T]):\n+      def __init__(self, value: T,\n+                         leaves: List['Tree[T]']) -> None:\n+          self.value = value\n+          self.leaves = leaves\n+\n+  def walk(graph: Traversable) -> None:\n+      ...\n+  tree: Tree[float] = Tree(0, [])\n+  walk(tree)  # OK, 'Tree[float]' is a subtype of 'Traversable'\n+\n \n Using Protocols\n ===============\n \n Subtyping relationships with other types\n ----------------------------------------\n \n-Protocols cannot be instantiated, so there are no values with\n-protocol types. For variables and parameters with protocol types, subtyping\n-relationships are subject to the following rules:\n+Protocols cannot be instantiated, so there are no values whose\n+*exact* type is a protocol. For variables and parameters with protocol types,","path":"pep-0544.txt","position":267,"original_position":267,"commit_id":"26a5aa01d93ff1bc3be60c100631b0ef45d947f7","original_commit_id":"26a5aa01d93ff1bc3be60c100631b0ef45d947f7","user":{"login":"JukkaL","id":1107911,"avatar_url":"https://avatars1.githubusercontent.com/u/1107911?v=3","gravatar_id":"","url":"https://api.github.com/users/JukkaL","html_url":"https://github.com/JukkaL","followers_url":"https://api.github.com/users/JukkaL/followers","following_url":"https://api.github.com/users/JukkaL/following{/other_user}","gists_url":"https://api.github.com/users/JukkaL/gists{/gist_id}","starred_url":"https://api.github.com/users/JukkaL/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JukkaL/subscriptions","organizations_url":"https://api.github.com/users/JukkaL/orgs","repos_url":"https://api.github.com/users/JukkaL/repos","events_url":"https://api.github.com/users/JukkaL/events{/privacy}","received_events_url":"https://api.github.com/users/JukkaL/received_events","type":"User","site_admin":false},"body":"Maybe use 'runtime type' instead of 'exact type' as it's less open to interpretation.","created_at":"2017-04-20T11:44:57Z","updated_at":"2017-04-20T11:56:17Z","html_url":"https://github.com/python/peps/pull/243#discussion_r112432436","pull_request_url":"https://api.github.com/repos/python/peps/pulls/243","_links":{"self":{"href":"https://api.github.com/repos/python/peps/pulls/comments/112432436"},"html":{"href":"https://github.com/python/peps/pull/243#discussion_r112432436"},"pull_request":{"href":"https://api.github.com/repos/python/peps/pulls/243"}}},"pull_request":{"url":"https://api.github.com/repos/python/peps/pulls/243","id":116578009,"html_url":"https://github.com/python/peps/pull/243","diff_url":"https://github.com/python/peps/pull/243.diff","patch_url":"https://github.com/python/peps/pull/243.patch","issue_url":"https://api.github.com/repos/python/peps/issues/243","number":243,"state":"open","locked":false,"title":"Updates for PEP 544: Protocols","user":{"login":"ilevkivskyi","id":12005495,"avatar_url":"https://avatars2.githubusercontent.com/u/12005495?v=3","gravatar_id":"","url":"https://api.github.com/users/ilevkivskyi","html_url":"https://github.com/ilevkivskyi","followers_url":"https://api.github.com/users/ilevkivskyi/followers","following_url":"https://api.github.com/users/ilevkivskyi/following{/other_user}","gists_url":"https://api.github.com/users/ilevkivskyi/gists{/gist_id}","starred_url":"https://api.github.com/users/ilevkivskyi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilevkivskyi/subscriptions","organizations_url":"https://api.github.com/users/ilevkivskyi/orgs","repos_url":"https://api.github.com/users/ilevkivskyi/repos","events_url":"https://api.github.com/users/ilevkivskyi/events{/privacy}","received_events_url":"https://api.github.com/users/ilevkivskyi/received_events","type":"User","site_admin":false},"body":"This implements two sets of comments by Guido, comments from python-dev, and adds links to working implementation.\r\n\r\nAttn: @JukkaL @ambv @gvanrossum ","created_at":"2017-04-19T15:36:10Z","updated_at":"2017-04-20T11:56:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"66716b82980b5d738db6ea893f69c7b5b590835a","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/python/peps/pulls/243/commits","review_comments_url":"https://api.github.com/repos/python/peps/pulls/243/comments","review_comment_url":"https://api.github.com/repos/python/peps/pulls/comments{/number}","comments_url":"https://api.github.com/repos/python/peps/issues/243/comments","statuses_url":"https://api.github.com/repos/python/peps/statuses/26a5aa01d93ff1bc3be60c100631b0ef45d947f7","head":{"label":"ilevkivskyi:protocol-updates","ref":"protocol-updates","sha":"26a5aa01d93ff1bc3be60c100631b0ef45d947f7","user":{"login":"ilevkivskyi","id":12005495,"avatar_url":"https://avatars2.githubusercontent.com/u/12005495?v=3","gravatar_id":"","url":"https://api.github.com/users/ilevkivskyi","html_url":"https://github.com/ilevkivskyi","followers_url":"https://api.github.com/users/ilevkivskyi/followers","following_url":"https://api.github.com/users/ilevkivskyi/following{/other_user}","gists_url":"https://api.github.com/users/ilevkivskyi/gists{/gist_id}","starred_url":"https://api.github.com/users/ilevkivskyi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilevkivskyi/subscriptions","organizations_url":"https://api.github.com/users/ilevkivskyi/orgs","repos_url":"https://api.github.com/users/ilevkivskyi/repos","events_url":"https://api.github.com/users/ilevkivskyi/events{/privacy}","received_events_url":"https://api.github.com/users/ilevkivskyi/received_events","type":"User","site_admin":false},"repo":{"id":63314770,"name":"peps","full_name":"ilevkivskyi/peps","owner":{"login":"ilevkivskyi","id":12005495,"avatar_url":"https://avatars2.githubusercontent.com/u/12005495?v=3","gravatar_id":"","url":"https://api.github.com/users/ilevkivskyi","html_url":"https://github.com/ilevkivskyi","followers_url":"https://api.github.com/users/ilevkivskyi/followers","following_url":"https://api.github.com/users/ilevkivskyi/following{/other_user}","gists_url":"https://api.github.com/users/ilevkivskyi/gists{/gist_id}","starred_url":"https://api.github.com/users/ilevkivskyi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ilevkivskyi/subscriptions","organizations_url":"https://api.github.com/users/ilevkivskyi/orgs","repos_url":"https://api.github.com/users/ilevkivskyi/repos","events_url":"https://api.github.com/users/ilevkivskyi/events{/privacy}","received_events_url":"https://api.github.com/users/ilevkivskyi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ilevkivskyi/peps","description":"Python Enhancement Proposals","fork":true,"url":"https://api.github.com/repos/ilevkivskyi/peps","forks_url":"https://api.github.com/repos/ilevkivskyi/peps/forks","keys_url":"https://api.github.com/repos/ilevkivskyi/peps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ilevkivskyi/peps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ilevkivskyi/peps/teams","hooks_url":"https://api.github.com/repos/ilevkivskyi/peps/hooks","issue_events_url":"https://api.github.com/repos/ilevkivskyi/peps/issues/events{/number}","events_url":"https://api.github.com/repos/ilevkivskyi/peps/events","assignees_url":"https://api.github.com/repos/ilevkivskyi/peps/assignees{/user}","branches_url":"https://api.github.com/repos/ilevkivskyi/peps/branches{/branch}","tags_url":"https://api.github.com/repos/ilevkivskyi/peps/tags","blobs_url":"https://api.github.com/repos/ilevkivskyi/peps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ilevkivskyi/peps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ilevkivskyi/peps/git/refs{/sha}","trees_url":"https://api.github.com/repos/ilevkivskyi/peps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ilevkivskyi/peps/statuses/{sha}","languages_url":"https://api.github.com/repos/ilevkivskyi/peps/languages","stargazers_url":"https://api.github.com/repos/ilevkivskyi/peps/stargazers","contributors_url":"https://api.github.com/repos/ilevkivskyi/peps/contributors","subscribers_url":"https://api.github.com/repos/ilevkivskyi/peps/subscribers","subscription_url":"https://api.github.com/repos/ilevkivskyi/peps/subscription","commits_url":"https://api.github.com/repos/ilevkivskyi/peps/commits{/sha}","git_commits_url":"https://api.github.com/repos/ilevkivskyi/peps/git/commits{/sha}","comments_url":"https://api.github.com/repos/ilevkivskyi/peps/comments{/number}","issue_comment_url":"https://api.github.com/repos/ilevkivskyi/peps/issues/comments{/number}","contents_url":"https://api.github.com/repos/ilevkivskyi/peps/contents/{+path}","compare_url":"https://api.github.com/repos/ilevkivskyi/peps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ilevkivskyi/peps/merges","archive_url":"https://api.github.com/repos/ilevkivskyi/peps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ilevkivskyi/peps/downloads","issues_url":"https://api.github.com/repos/ilevkivskyi/peps/issues{/number}","pulls_url":"https://api.github.com/repos/ilevkivskyi/peps/pulls{/number}","milestones_url":"https://api.github.com/repos/ilevkivskyi/peps/milestones{/number}","notifications_url":"https://api.github.com/repos/ilevkivskyi/peps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ilevkivskyi/peps/labels{/name}","releases_url":"https://api.github.com/repos/ilevkivskyi/peps/releases{/id}","deployments_url":"https://api.github.com/repos/ilevkivskyi/peps/deployments","created_at":"2016-07-14T07:53:04Z","updated_at":"2016-07-14T07:53:07Z","pushed_at":"2017-04-19T20:23:29Z","git_url":"git://github.com/ilevkivskyi/peps.git","ssh_url":"git@github.com:ilevkivskyi/peps.git","clone_url":"https://github.com/ilevkivskyi/peps.git","svn_url":"https://github.com/ilevkivskyi/peps","homepage":"https://www.python.org/dev/peps/","size":8644,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"python:master","ref":"master","sha":"e0adf8405575da6987234d03bc12a5688e97c89c","user":{"login":"python","id":1525981,"avatar_url":"https://avatars0.githubusercontent.com/u/1525981?v=3","gravatar_id":"","url":"https://api.github.com/users/python","html_url":"https://github.com/python","followers_url":"https://api.github.com/users/python/followers","following_url":"https://api.github.com/users/python/following{/other_user}","gists_url":"https://api.github.com/users/python/gists{/gist_id}","starred_url":"https://api.github.com/users/python/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/python/subscriptions","organizations_url":"https://api.github.com/users/python/orgs","repos_url":"https://api.github.com/users/python/repos","events_url":"https://api.github.com/users/python/events{/privacy}","received_events_url":"https://api.github.com/users/python/received_events","type":"Organization","site_admin":false},"repo":{"id":13414105,"name":"peps","full_name":"python/peps","owner":{"login":"python","id":1525981,"avatar_url":"https://avatars0.githubusercontent.com/u/1525981?v=3","gravatar_id":"","url":"https://api.github.com/users/python","html_url":"https://github.com/python","followers_url":"https://api.github.com/users/python/followers","following_url":"https://api.github.com/users/python/following{/other_user}","gists_url":"https://api.github.com/users/python/gists{/gist_id}","starred_url":"https://api.github.com/users/python/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/python/subscriptions","organizations_url":"https://api.github.com/users/python/orgs","repos_url":"https://api.github.com/users/python/repos","events_url":"https://api.github.com/users/python/events{/privacy}","received_events_url":"https://api.github.com/users/python/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/python/peps","description":"Python Enhancement Proposals","fork":false,"url":"https://api.github.com/repos/python/peps","forks_url":"https://api.github.com/repos/python/peps/forks","keys_url":"https://api.github.com/repos/python/peps/keys{/key_id}","collaborators_url":"https://api.github.com/repos/python/peps/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/python/peps/teams","hooks_url":"https://api.github.com/repos/python/peps/hooks","issue_events_url":"https://api.github.com/repos/python/peps/issues/events{/number}","events_url":"https://api.github.com/repos/python/peps/events","assignees_url":"https://api.github.com/repos/python/peps/assignees{/user}","branches_url":"https://api.github.com/repos/python/peps/branches{/branch}","tags_url":"https://api.github.com/repos/python/peps/tags","blobs_url":"https://api.github.com/repos/python/peps/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/python/peps/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/python/peps/git/refs{/sha}","trees_url":"https://api.github.com/repos/python/peps/git/trees{/sha}","statuses_url":"https://api.github.com/repos/python/peps/statuses/{sha}","languages_url":"https://api.github.com/repos/python/peps/languages","stargazers_url":"https://api.github.com/repos/python/peps/stargazers","contributors_url":"https://api.github.com/repos/python/peps/contributors","subscribers_url":"https://api.github.com/repos/python/peps/subscribers","subscription_url":"https://api.github.com/repos/python/peps/subscription","commits_url":"https://api.github.com/repos/python/peps/commits{/sha}","git_commits_url":"https://api.github.com/repos/python/peps/git/commits{/sha}","comments_url":"https://api.github.com/repos/python/peps/comments{/number}","issue_comment_url":"https://api.github.com/repos/python/peps/issues/comments{/number}","contents_url":"https://api.github.com/repos/python/peps/contents/{+path}","compare_url":"https://api.github.com/repos/python/peps/compare/{base}...{head}","merges_url":"https://api.github.com/repos/python/peps/merges","archive_url":"https://api.github.com/repos/python/peps/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/python/peps/downloads","issues_url":"https://api.github.com/repos/python/peps/issues{/number}","pulls_url":"https://api.github.com/repos/python/peps/pulls{/number}","milestones_url":"https://api.github.com/repos/python/peps/milestones{/number}","notifications_url":"https://api.github.com/repos/python/peps/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/python/peps/labels{/name}","releases_url":"https://api.github.com/repos/python/peps/releases{/id}","deployments_url":"https://api.github.com/repos/python/peps/deployments","created_at":"2013-10-08T13:27:12Z","updated_at":"2017-04-19T21:56:14Z","pushed_at":"2017-04-19T20:23:31Z","git_url":"git://github.com/python/peps.git","ssh_url":"git@github.com:python/peps.git","clone_url":"https://github.com/python/peps.git","svn_url":"https://github.com/python/peps","homepage":"https://www.python.org/dev/peps/","size":8508,"stargazers_count":435,"watchers_count":435,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":162,"mirror_url":null,"open_issues_count":12,"forks":162,"open_issues":12,"watchers":435,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/python/peps/pulls/243"},"html":{"href":"https://github.com/python/peps/pull/243"},"issue":{"href":"https://api.github.com/repos/python/peps/issues/243"},"comments":{"href":"https://api.github.com/repos/python/peps/issues/243/comments"},"review_comments":{"href":"https://api.github.com/repos/python/peps/pulls/243/comments"},"review_comment":{"href":"https://api.github.com/repos/python/peps/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/python/peps/pulls/243/commits"},"statuses":{"href":"https://api.github.com/repos/python/peps/statuses/26a5aa01d93ff1bc3be60c100631b0ef45d947f7"}}}}
{"actor":{"display_login":"JukkaL"}}