• Typing: Is there a "cast operator"?

    From Paulo da Silva@21:1/5 to All on Sun Oct 23 21:36:21 2022
    Hello!

    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program content):

    f=None # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
    f=os.open(...
    ..
    if f is not None:
    os.write(f, ...)
    ..
    if f is not None:
    os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" Argument 1 to "close" has incompatible type "Optional[int]"; expected "int"

    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?

    I use None a lot for specify uninitialized vars.

    Thank you.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sun Oct 23 22:36:07 2022
    Às 21:36 de 23/10/22, Paulo da Silva escreveu:
    Hello!

    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program content):

    f=None  # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
        f=os.open(...
    ..
    if f is not None:
        os.write(f, ...)
    ..
    if f is not None:
        os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" Argument 1 to "close" has incompatible type "Optional[int]"; expected "int"

    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?
    And yes there is! Exactly the "cast" operator. A mistype led me to wrong
    search results. I'm sorry.

    So, in the above code, we have to do:
    os.write(cast(int,f), ...)
    and
    os.close(cast(int,f), ...)

    Regards.
    Paulo

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cameron Simpson@21:1/5 to Paulo da Silva on Mon Oct 24 09:56:07 2022
    On 23Oct2022 21:36, Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:
    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program content):

    f=None # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
    f=os.open(...
    ..
    if f is not None:
    os.write(f, ...)
    ..
    if f is not None:
    os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" >Argument 1 to "close" has incompatible type "Optional[int]"; expected "int"

    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?

    I use None a lot for specify uninitialized vars.

    Maybe you shouldn't. The other way is to just not initialise the var at
    all. You could then just specify a type. Example:

    Python 3.8.13 (default, Aug 11 2022, 15:46:53)
    [Clang 12.0.0 (clang-1200.0.32.29)] on darwin
    Type "help", "copyright", "credits" or "license" for more
    information.
    >>> f:int
    >>> f
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'f' is not defined
    >>>

    So now `f` has `int` type definitely (for `mypy`'s purposes), and if
    used before assignment raises a distinctive error (versus having the
    value `None`, which you might then pass around, and perhaps successfully
    use in some contexts).

    It is probably better on the whole to specify types up front rather than relying on `mypy` or similar to infer them. That way (a) you're stating
    your intent and (b) not relying on an inferred type, which if you've got
    bugs may be inferred _wrong_. If `mypy` infers a type incorrectly all
    the subsequent checks will also be flawed, perhaps subtly.

    Cheers,
    Cameron Simpson <cs@cskk.id.au>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Mon Oct 24 02:45:45 2022
    Às 23:56 de 23/10/22, Cameron Simpson escreveu:
    On 23Oct2022 21:36, Paulo da Silva
    <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:
    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program
    content):

    f=None  # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
        f=os.open(...
    ..
    if f is not None:
        os.write(f, ...)
    ..
    if f is not None:
        os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected
    "int"
    Argument 1 to "close" has incompatible type "Optional[int]"; expected
    "int"

    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?

    I use None a lot for specify uninitialized vars.

    Maybe you shouldn't. The other way is to just not initialise the var at
    all. You could then just specify a type. Example:

       Python 3.8.13 (default, Aug 11 2022, 15:46:53)
       [Clang 12.0.0 (clang-1200.0.32.29)] on darwin
       Type "help", "copyright", "credits" or "license" for more
    information.
       >>> f:int
       >>> f
       Traceback (most recent call last):
         File "<stdin>", line 1, in <module>
       NameError: name 'f' is not defined
       >>>

    So now `f` has `int` type definitely (for `mypy`'s purposes), and if
    used before assignment raises a distinctive error (versus having the
    value `None`, which you might then pass around, and perhaps successfully
    use in some contexts).

    It is probably better on the whole to specify types up front rather than relying on `mypy` or similar to infer them. That way (a) you're stating
    your intent and (b) not relying on an inferred type, which if you've got
    bugs may be inferred _wrong_. If `mypy` infers a type incorrectly all
    the subsequent checks will also be flawed, perhaps subtly.

    Yes.
    I also use to make f unavailable (f=None) when something goes wrong and
    I don't want to stop the script but of course I could use "del f". I
    also need to care about using "try", which might be better than "if" tests.
    A thing to think of ...

    Thanks.
    Paulo

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Stromberg@21:1/5 to p_d_a_s_i_l_v_a_ns@nonetnoaddress.p on Sun Oct 23 20:14:15 2022
    On Sun, Oct 23, 2022 at 2:11 PM Paulo da Silva < p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:

    Hello!

    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program content):

    f=None # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
    f=os.open(...
    ..
    if f is not None:
    os.write(f, ...)
    ..
    if f is not None:
    os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" Argument 1 to "close" has incompatible type "Optional[int]"; expected "int"

    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?

    I use None a lot for specify uninitialized vars.


    I've found that mypy understands simple assert statements.

    So if you:
    if f is not None:
    assert f is not None
    os.write(f, ...)

    You might be in good shape.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Dan Stromberg on Mon Oct 24 14:19:37 2022
    On Mon, 24 Oct 2022 at 14:15, Dan Stromberg <drsalists@gmail.com> wrote:
    I've found that mypy understands simple assert statements.

    So if you:
    if f is not None:
    assert f is not None
    os.write(f, ...)

    You might be in good shape.

    Why can't it simply understand the if statement? I'm not a fan of
    coddling a type system like this. The entire point of type checking is
    to help you find bugs more efficiently, so if you have to repeat
    yourself every time you do these kinds of checks just so that mypy is satisfied, that's counter-productive (case in point: what happens if
    you say "if fn is not None: assert f is not None"? Now you've
    introduced a bug just to deal with the type system).

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Dan Stromberg on Mon Oct 24 01:24:10 2022
    On 10/23/2022 11:14 PM, Dan Stromberg wrote:
    On Sun, Oct 23, 2022 at 2:11 PM Paulo da Silva < p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:

    Hello!

    I am in the process of "typing" of some of my scripts.
    Using it should help a lot to avoid some errors.
    But this is new for me and I'm facing some problems.

    Let's I have the following code (please don't look at the program content): >>
    f=None # mypy naturally assumes Optional(int) because later, at open,
    it is assigned an int.
    ..
    if f is None:
    f=os.open(...
    ..
    if f is not None:
    os.write(f, ...)
    ..
    if f is not None:
    os.close(f)

    When I use mypy, it claims
    Argument 1 to "write" has incompatible type "Optional[int]"; expected "int" >> Argument 1 to "close" has incompatible type "Optional[int]"; expected "int" >>
    How to solve this?
    Is there a way to specify that when calling os.open f is an int only?

    I use None a lot for specify uninitialized vars.


    I've found that mypy understands simple assert statements.

    So if you:
    if f is not None:
    assert f is not None
    os.write(f, ...)

    You might be in good shape.

    I'm not very familiar with anything but the simplest typing cases as
    yet, but mypy is happy with these two fragments.

    if f:
    os.write(int(f)) # f must be an int if it is not None, so we can
    cast it to int.

    Or something like this (substitute write() for print() as needed) -

    from typing import Optional, Any

    def f1(x:int)->Optional[int]:
    if x == 42:
    return x
    return None

    def zprint(arg:Any):
    if type(arg) == int:
    print(arg)

    y0 = f1(0) # None
    y42 = f1(42) # 42

    zprint(y0) # Prints nothing
    zprint(y42) # Prints 42

    Another possibility that mypy is happy with (and probably the simplest)
    - just declare g:int = None instead of g = None:

    g: int = None
    def yprint(arg: int):
    if arg:
    yprint(arg)
    else:
    print('arg is None')

    yprint(g) # Prints "arg is None"


    And **please** let's not go doing this kind of redundant and inelegant construction:

    if f is not None:
    assert f is not None
    os.write(f, ...)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter Otten@21:1/5 to Chris Angelico on Wed Oct 26 14:44:29 2022
    On 24/10/2022 05:19, Chris Angelico wrote:
    On Mon, 24 Oct 2022 at 14:15, Dan Stromberg <drsalists@gmail.com> wrote:
    I've found that mypy understands simple assert statements.

    So if you:
    if f is not None:
    assert f is not None
    os.write(f, ...)

    You might be in good shape.

    Why can't it simply understand the if statement?

    Could it be that this specific problem is fixed in current mypy?
    I get

    $ type .\tmp.py
    import os

    f = None
    if f is None:
    f = os.open("tmp.txt", os.O_RDWR|os.O_CREAT)
    os.write(f, b"yadda")
    $ mypy tmp.py
    Success: no issues found in 1 source file

    My attempt to verify that

    if name is None: ...

    is recognized:

    $ type .\tmp2.py
    import os
    import random

    f = None
    if random.randrange(2):
    f = os.open("tmp.txt", os.O_RDWR|os.O_CREAT)
    os.write(f, b"yadda")
    $ mypy tmp2.py
    tmp2.py:7: error: Argument 1 to "write" has incompatible type
    "Optional[int]"; expected "int"
    Found 1 error in 1 file (checked 1 source file)
    $ mypy --version
    mypy 0.982 (compiled: yes)
    $

    I'm not a fan of
    coddling a type system like this. The entire point of type checking is
    to help you find bugs more efficiently, so if you have to repeat
    yourself every time you do these kinds of checks just so that mypy is satisfied, that's counter-productive (case in point: what happens if
    you say "if fn is not None: assert f is not None"? Now you've
    introduced a bug just to deal with the type system).

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)