[Python-ideas] Re: Structure Pattern for annotation

2021-10-17 Thread Joren Hammudoglu
I guess you could work around this by exploiting the slicing operator:

GenericClass[:(A, B)]

It makes sense to use the : in the context of typing, but I can see how this 
syntax can be confusing. The least confusing implementation I could think of is 
to limit the use of GenericClass[:_] to tuples, lists, sets and dicts (and 
future callable type signatures?), i.e.; it should only be used for structural 
type pattern matching.

Here is a simple demo: 
https://gist.github.com/jorenham/1c241a1cf33d2cc8235631b63fa8f279
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JDBJGEPF2HVRJKZIWDU6CM5SW7ABDWZQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-15 Thread Jelle Zijlstra
El vie, 15 oct 2021 a las 14:42, Abdulla Al Kathiri (<
alkathiri.abdu...@gmail.com>) escribió:

> I don’t understand why tuple structure is not supported already. It makes
> reading the function signature a breeze and very natural. You can also do
> it without parentheses which mimics the return of multiple objects often
> seen in functions(def func(*args: int) -> str, [int])
>
> I brought this up before and one issue is that it's hard to distinguish
between a tuple used as a type parameter and multiple type parameters:

GenericClass[(A, B)]  # parameterized by the type Tuple[A, B]
GenericClass[A, B]  # two type parameters

The ASTs for both of those are the same, so it would be difficult for mypy
to distinguish them.

I do agree that it would be nice to write types like ([str], [int]), but
there are some practical problems.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/BZBQFKZFBFE7VQZZ5FEMNYN3KJDZPNMF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-15 Thread Abdulla Al Kathiri
I don’t understand why tuple structure is not supported already. It makes 
reading the function signature a breeze and very natural. You can also do it 
without parentheses which mimics the return of multiple objects often seen in 
functions(def func(*args: int) -> str, [int])

> On 14 Oct 2021, at 12:53 PM, Alex Waygood  wrote:
> 
> I agree with Steven. I very much like Abdulla's proposed syntax for dicts, 
> TypedDicts and sets. But I'm not sure that the idea for `Annotated` is 
> workable, and the proposal for lists seems too prone to ambiguity, given how 
> extensively square brackets are already used in typing syntax.
> 
> One question about the proposals, however: how would we represent other 
> mappings apart from dicts? Would `collections.abc.Mapping` and 
> `types.MappingProxyType` still be spelled as `Mapping[str, int]` and 
> `MappingProxyType[str, int]`? If so, that would be a slightly annoying 
> inconsistency.
> 
> I do also quite like the idea of an improved syntax for tuples specifically. 
> Tuples are already very different types to lists/strings/etc in the context 
> of typing, essentially representing heterogeneous structs of fixed length 
> rather than homogenous sequences of unspecified length. As such, I think it 
> "makes sense" to special-case tuples without special-casing other sequences 
> such as list, `collections.abc.Sequence` or `collections.deque`.
> 
> def foo() -> tuple[list[list[str]], list[list[str]]]
> 
> would become
> 
> def foo() -> (list[list[str]], list[list[str]])
> 
> That feels quite readable and natural, to me.
> 
> Best,
> Alex 
> 
>> On 14 Oct 2021, at 09:25, Steven D'Aprano  wrote:
>> 
>> On Thu, Oct 14, 2021 at 12:32:57AM +0400, Abdulla Al Kathiri wrote:
>> 
>>> Today I found myself write a function that returns a tuple of list of 
>>> list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it 
>>> easier to read to write it like the following:
>>> ([[str]], [[str]])? 
>> 
>> Not really. Your first example is explicit and I can get the meaning by 
>> just reading it out loud:
>> 
>>tuple[list[list[str]], list[list[str]]]
>> 
>>"tuple (of) list (of) list (of) str, list (of) list (of) str
>> 
>> Your abbreviated version:
>> 
>>([[str]], [[str]])
>> 
>> is too terse. I have to stop and think about what it means, not just 
>> read it out loud. Without the hint of named types (tuple and list), my 
>> first reaction to seeing [str] is "is this an optional string?".
>> 
>> And then I wonder why it's not written:
>> 
>>([[""]], [[""]])
>> 
>> Why abbreviate list and tuple but not string?
>> 
>> Code is read more than it is written, and can be too terse as well as 
>> too verbose.
>> 
>> On the other hand:
>> 
>>> Similarly for TypedDict, replace the following..
>>> class Movie(TypedDict):
>>>name: str
>>>year: int
>>> with 
>>> {‘name’: str, ‘year’: int}
>> 
>> To my eye, that one does work. As far as I know, curly brackets {} 
>> aren't otherwise used in annotations (unlike square brackets), and they 
>> don't look like "optional" to me. They look like a dict.
>> 
>> So on first glance at least, I think that:
>> 
>>{'name': str, 'year': int}
>> 
>> is better than the class syntax we already have.
>> 
>> 
>> Likewise:
>> 
>>> dict[str, int] will be {str: int} 
>>> set[int] will be {int}. 
>> 
>> work for me too.
>> 
>> 
>>> Also, Annotated[float, “seconds”] can be replaced with something like 
>>> float #seconds indicating whatever comes after the hashtag is just 
>>> extra information similar to a normal comment in the code.
>> 
>> No, because the # indicates that the rest of the line is a comment. This 
>> is already legal:
>> 
>>def func(d: {str  # this is an actual comment
>> : int}) -> Any: ...
>> 
>> so this would be ambiguous between a real comment and an annotation.
>> 
>> Even if we agreed to change the behaviour of comments, you suggested:
>> 
>>func(d: {str # product label: [float] # prices from 2000 to 2015})
>> 
>> How is the interpreter to know that the first annotation is just
>> 
>>"product label"
>> 
>> rather than this?
>> 
>>"product label: [float] # prices from 2000 to 2015"
>> 
>> So I don't think this works.
>> 
>> 
>> -- 
>> Steve
>> ___
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at 
>> https://mail.python.org/archives/list/python-ideas@python.org/message/T7E54DZW6EENRT373ZMCTU5WWRQ5M2TN/
>> Code of Conduct: http://python.org/psf/codeofconduct/
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> 

[Python-ideas] Re: Structure Pattern for annotation

2021-10-15 Thread Abdulla Al Kathiri



> On 14 Oct 2021, at 12:21 PM, Steven D'Aprano  wrote:
> 
> 
> Why abbreviate list and tuple but not string?
> 
Empty strings would be confusing as a type unless you mean a Literal empty 
string. We just limit the picture of the type to lists, tuples, dicts, and 
sets. Builtin most often used collections. Imagine you have a default parameter 
like this... name: “” = “”. This adds unnecessary confusion.

> Not really. Your first example is explicit and I can get the meaning by 
> just reading it out loud:
> 
>tuple[list[list[str]], list[list[str]]]
> 
>"tuple (of) list (of) list (of) str, list (of) list (of) str
> 
> Your abbreviated version:
> 
>([[str]], [[str]])
> 
> is too terse. I have to stop and think about what it means, not just 
> read it out loud. Without the hint of named types (tuple and list), my 
> first reaction to seeing [str] is "is this an optional string?".

I am a visual guy. ([[str]], [[str]]) is much easier to my eyes than reading 
tuple (of) list (of) list (of) str, list (of) list (of) str. 

> don't look like "optional" to me

Optional would be Optional[str] or str | None, not [str]. 

> No, because the # indicates that the rest of the line is a comment. This 
> is already legal:
> 
>def func(d: {str  # this is an actual comment
> : int}) -> Any: ...
> 
> so this would be ambiguous between a real comment and an annotation.
> 
> Even if we agreed to change the behaviour of comments, you suggested:
> 
>func(d: {str # product label: [float] # prices from 2000 to 2015})
> 
> How is the interpreter to know that the first annotation is just
> 
>"product label"
> 
> rather than this?
> 
>"product label: [float] # prices from 2000 to 2015"
> 
> So I don't think this works.
> 

# is not a good idea I agree. How about the following for Annotated:

func(d: {str & "product label": [float]  & "prices from 2000 to 2015"})? 

The “&” is similar to “& co.” (and company). They come together but the first 
one is the group leader and represents all of them. It works in an opposite way 
to “|” (or), which gives importance equally to the members. 

def func(
time: float & “hours” & datetime.timedelta.total_seconds()/3600,
verbose: bool & “option for long text” = False,
) -> str: … 

Abdulla 



___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OGAMCS4GERWUM47AXHHYPZYGJHQDK7MK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-15 Thread Ricky Teachey
On Fri, Oct 15, 2021 at 1:06 PM Finn Mason  wrote:

> I love the proposal for dicts, but I agree that this discourages duck
> typing. Could the curly braces notation represent Mapping, not dict
> specifically?
>
> +1 to shortening tuples but not other sequences.
>
>
> --
> Finn Mason
>


That might be useful. But don't forget there is also MutableMapping.

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ICTEPGREJLEVCKYMQ6MYLKRCNZ7NO7SY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-15 Thread Finn Mason
I love the proposal for dicts, but I agree that this discourages duck
typing. Could the curly braces notation represent Mapping, not dict
specifically?

+1 to shortening tuples but not other sequences.


--
Finn Mason

On Thu, Oct 14, 2021, 6:46 AM Paul Moore  wrote:

> On Thu, 14 Oct 2021 at 13:04, Ricky Teachey  wrote:
> >
> > I think all of this additional syntax is just a mistake.
> >
> > The reason is it will encourage people to not properly annotate their
> input types for duck typing. Some of these shortcuts might be nice for
> output types. But the more general trying.Mapping, typing.Sequence and
> friends should be preferred for input types. If terse shortcuts are
> available for the concrete data structure types, but not for the generic
> types, a lot of people are going to feel nudged to type hint their python
> improperly.
>
> +1. I'm not sure how much of my reservations about this whole
> discussion are ultimately reservations about typing in general, but I
> feel that the more we make it easier to express "exact" types, the
> more we encourage people to constrain their APIs to take precise types
> rather than to work with duck types. (I saw an example recently where
> even Mapping was over-specified, all that was needed was __getitem__,
> not even __len__ or __iter__).
>
> I know protocols allow duck typing in a static type checking context -
> maybe the energy focused on "making basic types easier to write"
> should be focused on making protocols easier to write, instead.
>
> Paul
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/KALBNJN2T4HAZFK4PZUV5RGAKXAVWCMD/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/C6HATFD4GXM73TDB6IMLBDIJPRVICIKI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-14 Thread Ricky Teachey
On Thu, Oct 14, 2021 at 8:46 AM Paul Moore  wrote:

>
> ...maybe the energy focused on "making basic types easier to write"
> should be focused on making protocols easier to write, instead.
>
> Paul
>

+ a billion

Rick.

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FAKH72P57D3BZEH2BVUA5H27V63E5NCO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-14 Thread Paul Moore
On Thu, 14 Oct 2021 at 13:04, Ricky Teachey  wrote:
>
> I think all of this additional syntax is just a mistake.
>
> The reason is it will encourage people to not properly annotate their input 
> types for duck typing. Some of these shortcuts might be nice for output 
> types. But the more general trying.Mapping, typing.Sequence and friends 
> should be preferred for input types. If terse shortcuts are available for the 
> concrete data structure types, but not for the generic types, a lot of people 
> are going to feel nudged to type hint their python improperly.

+1. I'm not sure how much of my reservations about this whole
discussion are ultimately reservations about typing in general, but I
feel that the more we make it easier to express "exact" types, the
more we encourage people to constrain their APIs to take precise types
rather than to work with duck types. (I saw an example recently where
even Mapping was over-specified, all that was needed was __getitem__,
not even __len__ or __iter__).

I know protocols allow duck typing in a static type checking context -
maybe the energy focused on "making basic types easier to write"
should be focused on making protocols easier to write, instead.

Paul
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KALBNJN2T4HAZFK4PZUV5RGAKXAVWCMD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-14 Thread Alex Waygood
I agree with Steven. I very much like Abdulla's proposed syntax for dicts, 
TypedDicts and sets. But I'm not sure that the idea for `Annotated` is 
workable, and the proposal for lists seems too prone to ambiguity, given how 
extensively square brackets are already used in typing syntax.

One question about the proposals, however: how would we represent other 
mappings apart from dicts? Would `collections.abc.Mapping` and 
`types.MappingProxyType` still be spelled as `Mapping[str, int]` and 
`MappingProxyType[str, int]`? If so, that would be a slightly annoying 
inconsistency.

I do also quite like the idea of an improved syntax for tuples specifically. 
Tuples are already very different types to lists/strings/etc in the context of 
typing, essentially representing heterogeneous structs of fixed length rather 
than homogenous sequences of unspecified length. As such, I think it "makes 
sense" to special-case tuples without special-casing other sequences such as 
list, `collections.abc.Sequence` or `collections.deque`.

def foo() -> tuple[list[list[str]], list[list[str]]]

would become

def foo() -> (list[list[str]], list[list[str]])

That feels quite readable and natural, to me.

Best,
Alex 

> On 14 Oct 2021, at 09:25, Steven D'Aprano  wrote:
> On Thu, Oct 14, 2021 at 12:32:57AM +0400, Abdulla Al Kathiri wrote:
> 
>> Today I found myself write a function that returns a tuple of list of 
>> list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it 
>> easier to read to write it like the following:
>> ([[str]], [[str]])?
> 
> Not really. Your first example is explicit and I can get the meaning by 
> just reading it out loud:
> 
>tuple[list[list[str]], list[list[str]]]
> 
>"tuple (of) list (of) list (of) str, list (of) list (of) str
> 
> Your abbreviated version:
> 
>([[str]], [[str]])
> 
> is too terse. I have to stop and think about what it means, not just 
> read it out loud. Without the hint of named types (tuple and list), my 
> first reaction to seeing [str] is "is this an optional string?".
> 
> And then I wonder why it's not written:
> 
>([[""]], [[""]])
> 
> Why abbreviate list and tuple but not string?
> 
> Code is read more than it is written, and can be too terse as well as 
> too verbose.
> 
> On the other hand:
> 
>> Similarly for TypedDict, replace the following..
>> class Movie(TypedDict):
>>name: str
>>year: int
>> with 
>> {‘name’: str, ‘year’: int}
> 
> To my eye, that one does work. As far as I know, curly brackets {} 
> aren't otherwise used in annotations (unlike square brackets), and they 
> don't look like "optional" to me. They look like a dict.
> 
> So on first glance at least, I think that:
> 
>{'name': str, 'year': int}
> 
> is better than the class syntax we already have.
> 
> 
> Likewise:
> 
>> dict[str, int] will be {str: int} 
>> set[int] will be {int}.
> 
> work for me too.
> 
> 
>> Also, Annotated[float, “seconds”] can be replaced with something like 
>> float #seconds indicating whatever comes after the hashtag is just 
>> extra information similar to a normal comment in the code.
> 
> No, because the # indicates that the rest of the line is a comment. This 
> is already legal:
> 
>def func(d: {str  # this is an actual comment
> : int}) -> Any: ...
> 
> so this would be ambiguous between a real comment and an annotation.
> 
> Even if we agreed to change the behaviour of comments, you suggested:
> 
>func(d: {str # product label: [float] # prices from 2000 to 2015})
> 
> How is the interpreter to know that the first annotation is just
> 
>"product label"
> 
> rather than this?
> 
>"product label: [float] # prices from 2000 to 2015"
> 
> So I don't think this works.
> 
> 
> -- 
> Steve
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/T7E54DZW6EENRT373ZMCTU5WWRQ5M2TN/
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YUPJNZVGYDANDHFD5VI54GRRNLGUAFBP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-14 Thread Steven D'Aprano
On Thu, Oct 14, 2021 at 12:32:57AM +0400, Abdulla Al Kathiri wrote:

> Today I found myself write a function that returns a tuple of list of 
> list of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it 
> easier to read to write it like the following:
> ([[str]], [[str]])? 

Not really. Your first example is explicit and I can get the meaning by 
just reading it out loud:

tuple[list[list[str]], list[list[str]]]

"tuple (of) list (of) list (of) str, list (of) list (of) str

Your abbreviated version:

([[str]], [[str]])

is too terse. I have to stop and think about what it means, not just 
read it out loud. Without the hint of named types (tuple and list), my 
first reaction to seeing [str] is "is this an optional string?".

And then I wonder why it's not written:

([[""]], [[""]])

Why abbreviate list and tuple but not string?

Code is read more than it is written, and can be too terse as well as 
too verbose.

On the other hand:

> Similarly for TypedDict, replace the following..
> class Movie(TypedDict):
> name: str
> year: int
> with 
> {‘name’: str, ‘year’: int}

To my eye, that one does work. As far as I know, curly brackets {} 
aren't otherwise used in annotations (unlike square brackets), and they 
don't look like "optional" to me. They look like a dict.

So on first glance at least, I think that:

{'name': str, 'year': int}

is better than the class syntax we already have.


Likewise:

> dict[str, int] will be {str: int} 
> set[int] will be {int}. 

work for me too.


> Also, Annotated[float, “seconds”] can be replaced with something like 
> float #seconds indicating whatever comes after the hashtag is just 
> extra information similar to a normal comment in the code.

No, because the # indicates that the rest of the line is a comment. This 
is already legal:

def func(d: {str  # this is an actual comment
 : int}) -> Any: ...

so this would be ambiguous between a real comment and an annotation.

Even if we agreed to change the behaviour of comments, you suggested:

func(d: {str # product label: [float] # prices from 2000 to 2015})

How is the interpreter to know that the first annotation is just

"product label"

rather than this?

"product label: [float] # prices from 2000 to 2015"

So I don't think this works.


-- 
Steve
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/T7E54DZW6EENRT373ZMCTU5WWRQ5M2TN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Structure Pattern for annotation

2021-10-13 Thread David Mertz, Ph.D.
I find myself using exactly that "picture of the data" approach informally
for code I don't plan on formally type checking (but want to show intent).

E.g.

def myfun(data: {str: [CustomType]}) -> [(int, OtherType)]: ...

Maybe it's a bad habit, but it feels easier to parse visually than the real
`typing.py` stuff.


On Wed, Oct 13, 2021, 4:35 PM Abdulla Al Kathiri <
alkathiri.abdu...@gmail.com> wrote:

> Hello,
>
> Today I found myself write a function that returns a tuple of list of list
> of strings (tuple[list[list[str]], list[list[str]]]). Wouldn’t it easier to
> read to write it like the following:
> ([[str]], [[str]])?
> Similarly for TypedDict, replace the following..
>
> class Movie(TypedDict):
> name: str
> year: int
>
> with
> {‘name’: str, ‘year’: int}
> dict[str, int] will be {str: int}
> set[int] will be {int}.
> This is similar to the new proposed Callable alternative (i.e., (int,
> float) -> float) since it mimics the structure of a function.
>
> Also, Annotated[float, “seconds”] can be replaced with something like
> float #seconds indicating whatever comes after the hashtag is just extra
> information similar to a normal comment in the code.
> Imagine you could replace the following
> def func(d: dict[Annotated[str, “product label”], Annotated[list[float],
> “prices from 2000 to 2015”]])…
> With
> def func(d: {str # product label: [float] # prices from 2000 to 2015})…
> Abdulla
> Sent from my iPhone
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/D6LHXDXPN6K27KV6MZBLG66ZSGCNDRG7/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/HYBIYHKE4ZAKTV33VB4AE37MG576KYH5/
Code of Conduct: http://python.org/psf/codeofconduct/