• Fwd: A typing question

    From Sam Ezeh@21:1/5 to p_d_a_s_i_l_v_a_ns@nonetnoaddress.p on Sat Oct 29 22:23:11 2022
    Do you want the following?

    ```
    from typing import List, Optional


    class GLOBALS:
    foos: Optional[Foos] = None


    class Foo:
    def __init__(self):
    pass


    class Foos:
    Foos: List[Foo] = []

    def __init__(self):
    pass


    GLOBALS.foos = Foos()
    ```

    Kind regards,
    Sam Ezeh

    On Sat, 29 Oct 2022 at 22:13, Paulo da Silva < p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:

    Hi!

    Consider this simple script ...

    ___________________
    from typing import List, Optional

    class GLOBALS:
    foos=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE in a real script

    def __init__(self):
    pass

    GLOBALS.foos: Optional[Foos]=Foos()
    ___________________

    Running mypy on it:
    pt9.py:18: error: Type cannot be declared in assignment to non-self
    attribute
    pt9.py:18: error: Incompatible types in assignment (expression has type "Foos", variable has type "None")
    Line 18 is last line and pt9.py is the scrip.

    Replacing last line by
    GLOBALS.foos=Foos()
    and running mypy still gives the second error.
    pt9.py:18: error: Incompatible types in assignment (expression has type "Foos", variable has type "None")

    What is the common practice in these cases?

    Thank you.

    --
    https://mail.python.org/mailman/listinfo/python-list


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Sam Ezeh on Sun Oct 30 10:34:47 2022
    Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the original:

    GLOBALS.foos: Optional[Foos]=Foos()

    but not the fall-back:

    GLOBALS.foos=Foos()


    Must admit, the first query coming to mind was: why is the typing taking
    place at initialisation-time, rather than within the (class) definition?
    At definition time "foos" has already been typed as None by implication!


    Solution (below) will not work if the mention of Foos in GLOBALS is a forward-reference. Either move GLOBALS to suit, or surround "Foos" with
    quotes.


    Also, these days (Python version allowing) importing "List" is
    unnecessary. Instead could use "list".



    On 30/10/2022 10.23, Sam Ezeh wrote:
    Do you want the following?

    ```
    from typing import List, Optional


    class GLOBALS:
    foos: Optional[Foos] = None


    class Foo:
    def __init__(self):
    pass


    class Foos:
    Foos: List[Foo] = []

    def __init__(self):
    pass


    GLOBALS.foos = Foos()
    ```

    Kind regards,
    Sam Ezeh

    On Sat, 29 Oct 2022 at 22:13, Paulo da Silva < p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:

    Hi!

    Consider this simple script ...

    ___________________
    from typing import List, Optional

    class GLOBALS:
    foos=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE in a real script

    def __init__(self):
    pass

    GLOBALS.foos: Optional[Foos]=Foos()
    ___________________

    Running mypy on it:
    pt9.py:18: error: Type cannot be declared in assignment to non-self
    attribute
    pt9.py:18: error: Incompatible types in assignment (expression has type
    "Foos", variable has type "None")
    Line 18 is last line and pt9.py is the scrip.

    Replacing last line by
    GLOBALS.foos=Foos()
    and running mypy still gives the second error.
    pt9.py:18: error: Incompatible types in assignment (expression has type
    "Foos", variable has type "None")

    What is the common practice in these cases?

    Thank you.

    --
    https://mail.python.org/mailman/listinfo/python-list


    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sat Oct 29 23:59:44 2022
    Às 22:34 de 29/10/22, dn escreveu:
    Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the original:

        GLOBALS.foos: Optional[Foos]=Foos()

    but not the fall-back:

        GLOBALS.foos=Foos()


    Must admit, the first query coming to mind was: why is the typing taking place at initialisation-time, rather than within the (class) definition?
    At definition time "foos" has already been typed as None by implication!


    Solution (below) will not work if the mention of Foos in GLOBALS is a forward-reference. Either move GLOBALS to suit, or surround "Foos" with quotes.
    This is the problem for me. So far, without typing, I used to have some
    config and globals classes, mostly to just group definitions an make the program more readable. A matter of taste and style.
    Now, "typing" is breaking this, mostly because of this forward reference
    issue.
    The funny thing is that if I replace foos by Foos it works because it
    gets known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE

    def __init__(self):
    pass

    GLOBALS.Foos=Foos()
    ________________________





    Also, these days (Python version allowing) importing "List" is
    unnecessary. Instead could use "list".



    On 30/10/2022 10.23, Sam Ezeh wrote:
    Do you want the following?

    ```
    from typing import List, Optional


    class GLOBALS:
         foos: Optional[Foos] = None


    class Foo:
         def __init__(self):
             pass


    class Foos:
         Foos: List[Foo] = []

         def __init__(self):
             pass


    GLOBALS.foos = Foos()
    ```

    Kind regards,
    Sam Ezeh

    On Sat, 29 Oct 2022 at 22:13, Paulo da Silva <
    p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> wrote:

    Hi!

    Consider this simple script ...

    ___________________
    from typing import List, Optional

    class GLOBALS:
          foos=None

    class Foo:

          def __init__(self):
              pass

    class Foos:
          Foos: List[Foo]=[]
          # SOME GLOBALS ARE USED HERE in a real script

          def __init__(self):
              pass

    GLOBALS.foos: Optional[Foos]=Foos()
    ___________________

    Running mypy on it:
    pt9.py:18: error: Type cannot be declared in assignment to non-self
    attribute
    pt9.py:18: error: Incompatible types in assignment (expression has type
    "Foos", variable has type "None")
    Line  18 is last line and pt9.py is the scrip.

    Replacing last line by
    GLOBALS.foos=Foos()
    and running mypy still gives the second error.
    pt9.py:18: error: Incompatible types in assignment (expression has type
    "Foos", variable has type "None")

    What is the common practice in these cases?

    Thank you.

    --
    https://mail.python.org/mailman/listinfo/python-list



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Paulo da Silva on Sun Oct 30 15:32:45 2022
    On 30/10/2022 11.59, Paulo da Silva wrote:
    Solution (below) will not work if the mention of Foos in GLOBALS is a
    forward-reference. Either move GLOBALS to suit, or surround "Foos"
    with quotes.
    This is the problem for me. So far, without typing, I used to have some config and globals classes, mostly to just group definitions an make the program more readable. A matter of taste and style.

    Agreed, a good practice.


    Now, "typing" is breaking this, mostly because of this forward reference issue.

    As a first step, use the quotation-marks to indicate that such will be
    defined later in the code:-

    class GLOBALS:
    Foos: Optional[Foos]=None

    class GLOBALS:
    Foos: Optional["Foos"]=None


    Later, as gather (typing) expertise, can become more sophisticated, as-and-when...


    The funny thing is that if I replace foos by Foos it works because it
    gets known by the initial initialization :-) !

    Is the objective to write (good) code, or merely to satisfy the
    type-checker?

    Something that is misleading is not going to be appreciated by others (including the +6-months you), eg

    a = a + 1 # decrement total

    Typing is not compulsory, and has been designed so that we can implement
    it a bit at a time, eg only one function amongst many contained by a
    module - if that's the only code that requires maintenance/update.

    Best not to create "technical debt" though!

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sun Oct 30 04:48:12 2022
    Às 02:32 de 30/10/22, dn escreveu:
    On 30/10/2022 11.59, Paulo da Silva wrote:
    Solution (below) will not work if the mention of Foos in GLOBALS is a
    forward-reference. Either move GLOBALS to suit, or surround "Foos"
    with quotes.
    This is the problem for me. So far, without typing, I used to have
    some config and globals classes, mostly to just group definitions an
    make the program more readable. A matter of taste and style.

    Agreed, a good practice.
    Thank you.


    Now, "typing" is breaking this, mostly because of this forward
    reference issue.

    As a first step, use the quotation-marks to indicate that such will be defined later in the code:-

    class GLOBALS:
        Foos: Optional[Foos]=None

    class GLOBALS:
        Foos: Optional["Foos"]=None


    Later, as gather (typing) expertise, can become more sophisticated, as-and-when...


    The funny thing is that if I replace foos by Foos it works because it
    gets known by the initial initialization :-) !

    Is the objective to write (good) code, or merely to satisfy the
    type-checker?

    Something that is misleading is not going to be appreciated by others (including the +6-months you), eg

    a = a + 1   # decrement total

    Typing is not compulsory, and has been designed so that we can implement
    it a bit at a time, eg only one function amongst many contained by a
    module - if that's the only code that requires maintenance/update.

    Best not to create "technical debt" though!

    The main idea is to eventually catch some, otherwise "hidden", errors
    and produce better and cleaner code. Documentation is also a must.

    Regards

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter J. Holzer@21:1/5 to Paulo da Silva on Sun Oct 30 11:26:56 2022
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    Às 22:34 de 29/10/22, dn escreveu:
    Solution (below) will not work if the mention of Foos in GLOBALS is a forward-reference.
    Either move GLOBALS to suit, or surround "Foos" with quotes.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    This is the problem for me.

    Quotes are a bit ugly, but why are they a problem?

    [...]

    The funny thing is that if I replace foos by Foos it works because it gets known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me. What is the «Foos» in «Optional[Foos]»
    referring to?

    If it's the class attribute «Foos» then that's not a type and even if
    its type is inferred that's not the same as «Optional[it's type]», or is
    it?

    If it's referring to the global symbol «Foos» (i.e. the class defined
    later) that hasn't been defined yet, so it shouldn't work (or
    alternatively, if forward references are allowed it should always work).

    hp

    --
    _ | Peter J. Holzer | Story must make more sense than reality.
    |_|_) | |
    | | | hjp@hjp.at | -- Charles Stross, "Creative writing
    __/ | http://www.hjp.at/ | challenge!"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEETtJbRjyPwVTYGJ5k8g5IURL+KF0FAmNeUWsACgkQ8g5IURL+ KF3WIQ//W9Svykrqz2/dlXoFLfLRAy/WWyK0c5OHN7zNuC5auf64Bci/4RjkxuM0 nrq8GcyEppFEw+85fhhIFpdxkle8ef+k49pIRPrmg6rUL5Y8sUbHY1c6S8dzTa76 Tn+LW+9h4YWWNijs+3rCesjkxqLLj2+qJUTAVYoPD+wH5xqm5CFBNkyouSC7rHxV RSzlzK2h3I4VwybPo088sqUV/+5MRZOPy0Ydrefjgmy2r8xfAKv/K/jgq7BVO3g2 eqVVfinkUM78Ksy0ABlFpMDRUOYfBWteqiCT1XOXDaieFXphuaXKGgCRn+2FXNLN 6i1f1wsgXqcuM7CRJqzu7lWUN79+mbbMZwuOrEaClPU51nFlBQYDBgnCpiXfsEC3 htOklgmzBeuJxeZrVtVGrxi8pBEqCB8wKtBiCRTsZzpT4mORErz9oQ/4QNJ/BU96 +UNvFpTLV52sqVLkio4F6QIiONrSbAObzge9FdT3z1s1BviPnwIYRwKEtQ+vDJNa WWwRKLdqq08A7V3OYSkIxtt1L830C438rr87zX9Ldikqk8/gLF+KJzO7NDYchzPp fTSedRUDfj55wkg6Ze1oSlzeUTHrYE2lxGEzdGMGQopMyfw3CF29EjD89TQdHOAO Y38i0AY19BP9LjzUsxcscK4NE2ApM+X4imxGFlN
  • From Thomas Passin@21:1/5 to Peter J. Holzer on Sun Oct 30 09:23:27 2022
    On 10/30/2022 6:26 AM, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    Às 22:34 de 29/10/22, dn escreveu:
    Solution (below) will not work if the mention of Foos in GLOBALS is a
    forward-reference.
    Either move GLOBALS to suit, or surround "Foos" with quotes.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    This is the problem for me.

    Quotes are a bit ugly, but why are they a problem?

    [...]

    The funny thing is that if I replace foos by Foos it works because it gets >> known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me. What is the «Foos» in «Optional[Foos]» referring to?

    If it's the class attribute «Foos» then that's not a type and even if
    its type is inferred that's not the same as «Optional[it's type]», or is it?

    If it's referring to the global symbol «Foos» (i.e. the class defined later) that hasn't been defined yet, so it shouldn't work (or
    alternatively, if forward references are allowed it should always work).

    Quoting a forward-referenced type is the way to use one. Unquoted types
    need to have been declared already.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter J. Holzer@21:1/5 to Thomas Passin on Sun Oct 30 14:37:29 2022
    On 2022-10-30 09:23:27 -0400, Thomas Passin wrote:
    On 10/30/2022 6:26 AM, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    The funny thing is that if I replace foos by Foos it works because it gets
    known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me. What is the «Foos» in «Optional[Foos]» referring to?

    If it's the class attribute «Foos» then that's not a type and even if
    its type is inferred that's not the same as «Optional[it's type]», or is it?

    If it's referring to the global symbol «Foos» (i.e. the class defined later) that hasn't been defined yet, so it shouldn't work (or alternatively, if forward references are allowed it should always work).

    Quoting a forward-referenced type is the way to use one. Unquoted types
    need to have been declared already.

    Yes. I was referring to the code as written. Why does that work? I don't
    think it should.

    hp

    --
    _ | Peter J. Holzer | Story must make more sense than reality.
    |_|_) | |
    | | | hjp@hjp.at | -- Charles Stross, "Creative writing
    __/ | http://www.hjp.at/ | challenge!"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEETtJbRjyPwVTYGJ5k8g5IURL+KF0FAmNefhMACgkQ8g5IURL+ KF3QyRAAh9sr3MBxAWzzJNjM1pZggVqXtQoCsdhbFjppNxBEqlOJFb98eesuCj/L 60qhflR74Y0mPiTmL+8DIU0YKjAIZwUQIvINYARx0gyalIHOT+23e8QrZ7VyfQXP NMffohGuyYvIMbUSk8NWJJ9uWMHBroW3d8lRG3L4rLaQVLdyKKsId8+iHxs/50p9 Dg/9L7gZEDswD28kx6gAEAb4pBvGirXkPZR1bXEa03obzGLVrA9zHTi1H8IZxVKX tDL4UqLnjbqlbPDkuzvUlww57f0D1B9xILjVGzcwTYWp21/gzbdVu2u6xm6TMwgc aw+I8MkZJtmKk6AFjCsHZxbvQh21huw6M7iPYMMHkoOADvM5F20kweIrTrXEs/5o Y3Y2zAJDL3G22A75hrt2i3ukKT6WzBLmzTrQYTgA6wvimsGEEvrEu1L939juqosz xqHrsq+LVe0z+QlHljFa/STncHhUj+ezANjlJQU1gyjjFK8AITkbMFKLmJlCipHk 3pzkjolTIqIzKqikuzSNBFn8jhEedLJ1uMlQcbdkulVE0tBUhyQU0CWlIh/FK6MD 96TNDXFX+6i8BAfe5NfdOfFNIvJWAQepB4rsQhfUaxs1moqDj+ZEqYiu/+mrJ7A+ ExDsEJzhzsWCZTuivAeU3qIjCZeAsHrErdCaLGB
  • From Stefan Ram@21:1/5 to Paulo da Silva on Sun Oct 30 17:06:34 2022
    Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
    Is there anything to do without loosing my script structure and usual >practice?

    to lose (losing): to stop having something
    to loose (loosing): to let or make loose (see next line)
    loose (adj.): not firmly attached/tied/fastened/controlled
    to loosen: similar to "to loose"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sun Oct 30 16:52:02 2022
    Às 10:26 de 30/10/22, Peter J. Holzer escreveu:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    Às 22:34 de 29/10/22, dn escreveu:
    Solution (below) will not work if the mention of Foos in GLOBALS is a
    forward-reference.
    Either move GLOBALS to suit, or surround "Foos" with quotes.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    This is the problem for me.

    Quotes are a bit ugly, but why are they a problem?

    [...]

    The funny thing is that if I replace foos by Foos it works because it gets >> known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me. What is the «Foos» in «Optional[Foos]» referring to?

    If it's the class attribute «Foos» then that's not a type and even if
    its type is inferred that's not the same as «Optional[it's type]», or is it?

    If it's referring to the global symbol «Foos» (i.e. the class defined later) that hasn't been defined yet, so it shouldn't work (or
    alternatively, if forward references are allowed it should always work).

    The problem is exactly this.
    Is there anything to do without loosing my script structure and usual
    practice? The forward reference only is needed to the "typing thing".
    Even if I declare class "Foos: pass" before, then another error arises - something like "already declared" below.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sun Oct 30 19:13:56 2022
    Às 22:34 de 29/10/22, dn escreveu:
    Out of interest, tested snippet in PyCharm, cf native-mypy. It flags the original:

        GLOBALS.foos: Optional[Foos]=Foos()

    but not the fall-back:

        GLOBALS.foos=Foos()


    Must admit, the first query coming to mind was: why is the typing taking place at initialisation-time, rather than within the (class) definition?
    At definition time "foos" has already been typed as None by implication!


    Solution (below) will not work if the mention of Foos in GLOBALS is a forward-reference. Either move GLOBALS to suit, or surround "Foos" with quotes.
    Somehow I missed this sentence the 1st. time I read this post :-(
    This is good enough to me! Thank you.
    I didn't know about this "quoting" thing.

    Regards
    Paulo

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paulo da Silva@21:1/5 to All on Sun Oct 30 19:00:30 2022
    Às 17:06 de 30/10/22, Stefan Ram escreveu:
    Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
    Is there anything to do without loosing my script structure and usual
    practice?

    to lose (losing): to stop having something
    to loose (loosing): to let or make loose (see next line)
    loose (adj.): not firmly attached/tied/fastened/controlled
    to loosen: similar to "to loose"

    It was a keyboard bounce ;-)
    How about answering the question?
    Thank you.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter Otten@21:1/5 to Peter J. Holzer on Sun Oct 30 20:43:23 2022
    On 30/10/2022 14:37, Peter J. Holzer wrote:
    On 2022-10-30 09:23:27 -0400, Thomas Passin wrote:
    On 10/30/2022 6:26 AM, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    The funny thing is that if I replace foos by Foos it works because it gets >>>> known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me. What is the «Foos» in «Optional[Foos]»
    referring to?

    If it's the class attribute «Foos» then that's not a type and even if
    its type is inferred that's not the same as «Optional[it's type]», or is >>> it?

    If it's referring to the global symbol «Foos» (i.e. the class defined
    later) that hasn't been defined yet, so it shouldn't work (or
    alternatively, if forward references are allowed it should always work).

    Quoting a forward-referenced type is the way to use one. Unquoted types
    need to have been declared already.

    Yes. I was referring to the code as written. Why does that work? I don't think it should.

    For me it makes sense. I think mypy should refrain from trying to figure
    out order of execution. If the above is disallowed, how about

    if random.randrange(2):
    class A: pass

    class B(A): pass

    ?

    One interesting consequence of that policy -- take the whole scope
    instead of the most recent appearance of a name is that

    class A: pass
    class A: pass

    won't compile.

    While I didn't expect that I think I like it ;)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Stefan Ram on Mon Oct 31 11:34:58 2022
    On 31/10/2022 06.06, Stefan Ram wrote:
    Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
    Is there anything to do without loosing my script structure and usual
    practice?

    to lose (losing): to stop having something
    to loose (loosing): to let or make loose (see next line)
    loose (adj.): not firmly attached/tied/fastened/controlled
    to loosen: similar to "to loose"


    Hay, your write*!

    Well done. There's many a native-speaker who doesn't know the
    distinction, or doesn't care about accuracy.

    It's a pity that there's no decent typing module for the English language!



    * yes, each word sounds about-right, but is totally wrong...
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to PythonList@danceswithmice.info on Mon Oct 31 09:44:30 2022
    On Mon, 31 Oct 2022 at 09:39, dn <PythonList@danceswithmice.info> wrote:

    On 31/10/2022 06.06, Stefan Ram wrote:
    Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
    Is there anything to do without loosing my script structure and usual
    practice?

    to lose (losing): to stop having something
    to loose (loosing): to let or make loose (see next line)
    loose (adj.): not firmly attached/tied/fastened/controlled
    to loosen: similar to "to loose"


    Hay, your write*!

    Well done. There's many a native-speaker who doesn't know the
    distinction, or doesn't care about accuracy.


    I'm curious to what extent sloppy English correlates with sloppy code.
    Do people care about learning proper Python but not about proper
    English, or do they think there's no such thing as proper English just
    because there's no English Steering Council?

    A lot of people seem to treat English the way web browsers treat HTML
    - as long as you can make some sense out of it, it's good enough. Some
    nerds treat English the way the W3C treats HTML - there actually is a
    standard and everything has defined rules. I know which camp I prefer
    to communicate with.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Paulo da Silva on Mon Oct 31 11:30:40 2022
    On 30/10/2022 17.48, Paulo da Silva wrote:
    Às 02:32 de 30/10/22, dn escreveu:
    On 30/10/2022 11.59, Paulo da Silva wrote:
    Solution (below) will not work if the mention of Foos in GLOBALS is
    a forward-reference. Either move GLOBALS to suit, or surround "Foos"
    with quotes.
    This is the problem for me. So far, without typing, I used to have
    some config and globals classes, mostly to just group definitions an
    make the program more readable. A matter of taste and style.

    Agreed, a good practice.
    Thank you.


    Now, "typing" is breaking this, mostly because of this forward
    reference issue.

    As a first step, use the quotation-marks to indicate that such will be
    defined later in the code:-

    class GLOBALS:
        Foos: Optional[Foos]=None

    class GLOBALS:
         Foos: Optional["Foos"]=None


    Later, as gather (typing) expertise, can become more sophisticated,
    as-and-when...


    The funny thing is that if I replace foos by Foos it works because it
    gets known by the initial initialization :-) !

    Is the objective to write (good) code, or merely to satisfy the
    type-checker?

    Something that is misleading is not going to be appreciated by others
    (including the +6-months you), eg

    a = a + 1   # decrement total

    Typing is not compulsory, and has been designed so that we can
    implement it a bit at a time, eg only one function amongst many
    contained by a module - if that's the only code that requires
    maintenance/update.

    Best not to create "technical debt" though!

    The main idea is to eventually catch some, otherwise "hidden", errors
    and produce better and cleaner code. Documentation is also a must.


    Good idea!

    All-along typing has been regarded as a tool for dev.aids, eg IDEs like
    PyCharm and tools such as mypy - rather than a (compulsory) component of
    the Python language itself. This means the folk who decide they don't
    like the idea can happily (and safely) ignore it - and continue to write
    code in perfect-Python. Also, that 'old program[me]s' will continue to
    operate, just as well as they ever did, without any reference to the
    typing library/ies at all. So, there is no imposed-cost, or 'pressure'
    to (wait to) upgrade (such as there was with the jump from Python 2 to
    Python 3).


    IMHO I'm finding that the auto-checking performed by the IDE is very
    helpful and stops my imagination from outstripping my coding-abilities
    (in the way that my eyes for chocolate cake are bigger than my
    stomach!). I'll go so far as to say that the discipline imposed/flagged
    by typing has been more beneficial, than my flirtation with an 'AI
    assistant' suggesting what I should code next! The assistant rarely
    seems to correctly anticipate my thinking*, whereas typing pulls me up
    when the code falls-short and prevents me from falling flat on my face!

    * which may say something unfortunate about my coding/design, or may
    simply show that SODD (Stack Overflow Driven Development - or the GitHub equivalent) leaves much to be desired. Hence the gold-plated advice:
    never copy-paste code without understanding it first!


    As time goes by, 'The Python Gods' have been introducing more and more capability under the typing banner. Which makes the policy as-outlined,
    the sensible (and parallel) course. S/w architecture and coding-quality
    books talk about "The Boy Scout Rule" (leave the camp-site in better
    condition than you found it). Accordingly, when performing
    user-specified updates, while we are 'there', we have the option/ability
    to add typing to a module/class/function - just as we might perform
    other "refactoring" tasks (one 'green-thumb' I know, referred to it as 'gardening').


    Evidently, the OP introduced typing into his/her code-base with the
    likes of List*. Thereafter, added the Optional, er, option. Now, we're
    talking about forward-references. Plus alluding to more recent
    developments (many of which are version-dependent!).

    Accordingly, we see another attribute of a gradual-introduction policy -
    the practitioner learning and becoming confident that (s)he has mastered
    basic techniques, before striding onwards to 'the next level'!


    * and for the above reason, I wondered, belatedly, if earlier advice to 'graduate' to "list", might be premature.


    PS and on a personal note, this policy is the one I'm following. So,
    given that we-two are on the same track, we must be "correct" - and also
    the best Python programmers in the world!
    (pardon me, I seem over-taken by a coughing fit...)

    YMMV!
    --
    Regards =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico on Mon Oct 31 13:50:03 2022
    On 31/10/2022 11.44, Chris Angelico wrote:
    On Mon, 31 Oct 2022 at 09:39, dn <PythonList@danceswithmice.info> wrote:

    On 31/10/2022 06.06, Stefan Ram wrote:
    Paulo da Silva <p_d_a_s_i_l_v_a_ns@nonetnoaddress.pt> writes:
    Is there anything to do without loosing my script structure and usual
    practice?

    to lose (losing): to stop having something
    to loose (loosing): to let or make loose (see next line)
    loose (adj.): not firmly attached/tied/fastened/controlled
    to loosen: similar to "to loose"


    Hay, your write*!

    Well done. There's many a native-speaker who doesn't know the
    distinction, or doesn't care about accuracy.


    I'm curious to what extent sloppy English correlates with sloppy code.
    Do people care about learning proper Python but not about proper
    English, or do they think there's no such thing as proper English just because there's no English Steering Council?

    A lot of people seem to treat English the way web browsers treat HTML
    - as long as you can make some sense out of it, it's good enough. Some
    nerds treat English the way the W3C treats HTML - there actually is a standard and everything has defined rules. I know which camp I prefer
    to communicate with.


    There are two distinctions to make: what is "correct", and how correctly
    we practice!

    Various languages do have a 'standards body', eg French and the group
    known as "l'Académie (française)". However, no matter how much they try
    to push-back against the encroachment of words from other languages (eg
    "le weekend"), even they admit that it is a losing battle (see also:
    King Canute).

    English is, and has long-been, an "acquisitive language". It takes words
    from other languages, often as attempted-homophones, and makes them
    "English": verandah, foreign, algebra, ... (and seeing I mentioned
    French: "maitre d'" because it makes the restaurant sound 'posh';
    champagne because you can then charge more for the bubbles, and
    omelet/omelette because I'm feeling hungry...). Indeed yous-Australians
    are also manipulators of the language, eg "tradies" for
    tradesmen/trades-people (see also: "They're a Weird Mob" - in case you
    haven't read that hilarious piece of Aussie Kulcha).

    There have been various attempts at standardising English. Indeed for
    our Internet-based training courses and courseware, I went looking for
    an 'international English'. There is no such thing. The closest is more
    to do with accent than text, ie speaking the Queen's/King's English, is
    really a euphemism for a (plummy) Oxford accent (or BBC accent - also
    fading into the past). A good starting-point: https://www.cambridge.org/highereducation/books/the-cambridge-encyclopedia-of-the-english-language/2B10AC8766B73D09955C899572C1E7EC#overview
    - a tome compiled by a man living in Wales (go figure!).

    The earliest attempts would include Samuel Johnson's Dictionary of the
    English Language (which preceded 'your' Lewis Carroll's playing with
    language by about half a century). Around-about one-century after that
    came the OED (Oxford English Dictionary), which is the closest thing to
    an idea of 'standard spelling'. (and at times differs significantly from alternate tomes describing American-English).

    As for grammar, I must admit deferring (and devolving?) such to style
    manuals, such as The Times of London, Strunk and White, etc. (but
    perhaps only later and lesser: Kernighan and Plauger's similarly named "Elements of Programming Style"). In this case, my multi-cultural
    education (or lack of application to my school-work?) has caused me many
    a stumble. Certainly, I've never taught the subject. Perhaps someone is better-acquainted with works used by The British Council, et al, in
    their English as a Second Language (and related) courses?


    The other side of this topic, that of accuracy and precision, involves
    aspects which were driven into us at school - that is, those of us with Optional[grey] hair! These days, teaching good-grammar, spelling, and
    so-on, are deemed unnecessarily restrictive, perhaps even cruel, but
    certainly far too boring (see also: "joined-up" hand-writing). "Drill"
    (aka "deliberate practice") is rarely employed as a teaching/learning
    technique in schools. Cue "amo, amas, amat, amamus, amatis, amant"
    (Latin - although quite why, as six-year olds, the teachers ("Masters")
    thought we should be speaking of love escapes me) and "Je suis, tu es,
    il est, ..." (French - which always reminds me of Rodin's sculpture and Descartes exclamation)*

    I've even (as an adult) had a (school) Department Head reply to such
    criticism with "but you understood me, didn't you?". So, with teachers
    like that, the kids are 'on a hiding to nothing'. The prevailing-theory
    seems to be that 'you'll pick it up as you go-along'. However, empirical evidence suggests otherwise. I've even met voracious readers who admit
    that their spelling is at the lousy-end of any metric, busting that myth well-and-truly!


    Traditionally 'computer people' have been assumed to need a good
    grounding in math[s]. Although, I haven't met anyone recently whose
    computing degree includes delving into Numerical Analysis - which
    explains the two recent threads (here and/or Tutor) asking why
    floating-point numbers are not always accurate/precise. Indeed, it's not
    hard to find ComSc graduates who don't know that 1 + 1 = 10 (binary) nor
    octal, nor hex[adecimal]...
    (cue: (timely) joke about not knowing the difference between Halloween
    and Christmas)

    There are observations (regret: have failed to lift-out a paper or a
    web.ref, but will keep an eye out...) that a better preparation for
    programming might well be human-language courses. Even the experience of grappling with a non-native language, both the learning and the
    execution, are readily transferable to computing. Plus, appreciating the subtleties of language (see elsewhere, list ~= stack) prepares one for
    the task of communicating both to human and machine, concurrently!

    If not [in the] right, the teacher, mentioned earlier, was correct: I
    did understand him. However, even basic communication theory illustrates
    that his lack of effort in 'transmitting' required extra effort from the 'receiver'. A computer/compiler will not invest (much) "extra" - despite
    the herculean efforts to improve Traceback explanations in recent Python releases. Many thanks to those involved!). In source-code, precision is 'rewarded'; but lack of precision is quickly and decisively 'punished'.

    Doesn't the compiler enforce a discipline upon us? Does that mean that accepting such discipline is a (necessary) early step towards the
    profession? Indeed, perhaps the constant mental struggle against an
    implacable machine; which regularly, and almost gleefully, tells us 'you
    are wrong'; is a reason why so many leave the profession - frustrated,
    angry, disappointed, mentally-exhausted, ego-dented, ...
    (sadly, not the only (sensible) reason for leaving!)

    Also, programming is something of a team-sport. We regularly come-across correspondents to this list asking questions without suitable and
    sufficient background information. Being able to ask a question and
    describe a problem is a skill - as much as describing the solution in
    Python. Indeed the famous push-back for such deficit is "Rubber Duck
    Problem Solving", and the phenomenon that the process of organising
    one's thoughts in order to best express them to another, is likely to
    throw-up a/the solution. When that doesn't work, the quality of the
    question and its communication will directly affect the (speed and)
    quality of an answer - as well as the 'cost' of the distraction to the 'helper'. Our common understanding of the problem domain, is key to communication. (and a generator of jargon, or extensions to the language!)


    When it comes to CVs/resumés (see what I did there?), I must admit that
    the most egregious of errors in spelling or grammar do ensure that an applicant's 'work' is quickly routed to "file 13" (an American-English
    term, many other English-speakers will not have heard previously).

    IMHO, I prefer someone who'll *do* the work, over someone who'll make me
    work. YMMV! Surely someone who mis-types and/or misspells, and has to
    'take a second run at it' after Python objects, will take longer to
    complete the same task as someone who is accurate and 'gets it right first-time'?

    (indeed, would better construction of that sentence read: "Surely
    someone who mis-types and/or misspells, and suffering objections from
    Python, has to 'take a second run at it', will take longer...")

    Alternately, I'm just an old f...?


    * that said, the languages I've learned since-school have all been
    through "immersion" in another culture; which I'd suggest is a more
    effective method (yet has its own dimension of "cruel"!) - but perhaps
    so, only because I had the 'base' (or the tools?) inculcated through my schooling (such as it was). Contrarily, my (somewhat younger)
    brother-in-law never studied languages at school, and struggled (and
    suffered) when he went to work in Germany - and was disgusted (envious)
    when I arrived and appeared to absorb the language 'by osmosis' (and a preparedness to make a fool of myself - something also learned at
    school, and impressed upon me by the Masters, without any trace of
    irony, but sometimes using impress-ively 'heavy weapons'...)

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to PythonList@DancesWithMice.info on Mon Oct 31 11:49:54 2022
    dn <PythonList@DancesWithMice.info> writes:
    * which may say something unfortunate about my coding/design, or may
    simply show that SODD (Stack Overflow Driven Development - or the GitHub >equivalent) leaves much to be desired. Hence the gold-plated advice:
    never copy-paste code without understanding it first!

    I wanted to write a chat program for my classroom with a GUI
    in tkinter. I never really learned tkinter, but using Web
    search engines and learning from programming Q&A sites and other
    Web publications, I was able to make it work in just a few hours.

    I am very grateful for the Web search engines and the Web sites
    to help me do this! I can still remember how much harder
    programming was in the pre-Web days.

    I had no time for learning tkinter properly nor reviewing the
    code. But now, later, I indeed found the time to read a tutorial
    about tkinter and also review and refactor the code of my chat
    program (the refactoring now is a work in progress).

    The chat program allows people to chat with each other who
    may not be able to exchange data via TCP/IP but can share
    a directory as in a LAN. One needs to enter that directory
    into the source code of the chat server (see below), then
    everyone starts one instance on his machine and then people
    can exchange chat messages via a file (I think of it as a
    "hidden file") in that common LAN directory.

    You also could use it as a note logger on a single machine
    as it will label each new entry with a time stamp. You could
    run two instances on a single machine to see how they share
    messages.

    Feel free to try to run my LAN chat program after configuring
    it via the configuration section in the code below!

    # first line
    #
    # License: Copyright (c) 2022 Stefan Ram <ram@zedat.fu-berlin.de>.
    # You may not redistribute modified versions of this program,
    # but you may use this program as is, modify it and use the
    # modifed version, or you may redistribute this unmodified
    # version from "first line" to "last line", and there's no warranty.
    #
    # User Manual:
    # Type the message into the text field in the bottom.
    # It may be a multi-line message.
    # Use the "send" button or press Ctrl-Enter to send the message.
    # To exit, send "exit" or close the window.
    # To configure, see the code section just below the imports.

    import datetime
    import io
    import math
    import os
    import pathlib
    import re
    import socket
    import sys
    import threading
    import time
    import tkinter
    import tkinter.messagebox
    import tkinter.font
    import tkinter.scrolledtext

    #u to configure this app, you can make changes in the following section:

    #u *** Begin of configuration section ***

    #u This is a chat program for users who can share directories,
    #u for example, via a local-area network. The file with the
    #u chat is stored in a shared directory.

    shared_directory_pathname = r"C:\example"

    #u The file with the chat should have a name that is not likely
    #u to collide with any other file in that directory.

    file_name = r"\chatfile_fvmchmpqtx.txt"

    #u *** End of configuration section ***

    progname = "Stefan Ram's LAN chat"

    #p Development started approximately on 2020-09-11T19:19:58+02:00.
    #p Then, there was a two-year break.
    versionname = progname +" (Version 2020-09-14/--24)"
    versionname = progname +" (Version 2020-09-14/2022-10-16T18:41:29+01:00)"

    def follow( filepath, stream_pos, encoding="utf_8" ):
    '''
    This is a yield function (generator). It returns
    complete '\n'-terminated lines just added to the
    end of a text file, by opening that text file and
    waiting for appendings of lines to that file.
    This is similar to the "tail -f" command.

    filepath: Path to the text file. Should be an object
    that can be passed to "open" as its first argument.

    stream_pos: The position of the text file from which
    the lines should be taken.

    encoding: The encoding of the text file.

    Result: Returns immediately with an empty string
    if there are no new data, otherwise it returns the
    next new line read from the file.
    '''
    # based on "tail_F", attributed to Raymond Hettinger
    with open( filepath, encoding=encoding ) as input:
    input.seek( stream_pos, io.SEEK_SET )
    buffer = input.read() # last line might be incomplete
    while True:
    if '\n' not in buffer:
    buffer += input.read()
    if '\n' not in buffer: # no complete line in buffer yet
    yield '' # yield '' to signal "no new data avaible"
    if not os.path.isfile( filepath ): break
    continue
    # '\n' is in latest_data, so we have read at least one
    # complete line now:
    # get the lines from the buffer, the last line may be
    # incomplete
    lines = buffer.split( '\n' )
    if buffer[ -1 ]== '\n':
    # if the last line is complete, fill the buffer
    # from the file.
    buffer = input.read()
    else:
    # if the last line is incomplete, fill the buffer
    # from the last incomplete line.
    buffer = lines[ -1 ]
    # return the complete lines from the list, one line
    # per "yield".
    for line in lines[ :-1 ]:
    yield line + '\n'

    def wait_and_follow( filepath, stream_pos, encoding="utf_8", timeout=10*366*24*60*60 ):
    '''
    Like "follow" (above), but if the file does not exist, will
    wait until the file exists or <timeout> seconds have passed.
    '''
    while True:
    try:
    yield from follow( filepath, stream_pos, encoding )
    except OSError as oserror:
    if oserror.errno == 2: # No such file or directory
    if timeout < 3:
    raise TimeoutError
    time.sleep( 3 )
    timeout-=3

    def filepath():
    '''
    Return the path of the file with chat messages
    '''
    #p Make sure the shared directory really does exist.
    shared_directory_path = pathlib.Path( shared_directory_pathname )
    if not shared_directory_path.is_dir():
    tkinter.messagebox.showerror( progname, f'There is no directory "{shared_directory_pathname}"! I\'m exiting.' )
    sys.exit( 99 )
    filepath = shared_directory_pathname + file_name
    return filepath

    class application_class():
    __slots__ = 'filepath', 'root', 'listbox', 'entrybox', 'stream_pos', 'exiting'

    def __init__( self ):
    self.filepath=filepath()
    self.setup_root_window()
    self.stream_pos = 0
    self.exiting = False
    self.insert_old_messages_from_file_into_the_GUI()
    self.establish_thread_to_update_titlebar()
    self.establish_thread_to_update_GUI_from_file()
    self.root.deiconify() # make root window visible, must go before mainloop()
    tkinter.mainloop()

    def setup_root_window( self ):

    def create_messagelist_frame( root ):

    def add_listbox( frame ):
    small_font = tkinter.font.nametofont( "TkFixedFont" )
    small_font.configure( size=20, weight="bold" )
    listbox = tkinter.Listbox( frame, height=1, width=1, selectmode=tkinter.EXTENDED, font=small_font )
    listbox.pack( side=tkinter.LEFT, expand=tkinter.YES, fill=tkinter.BOTH )
    return listbox

    def add_scrollbar( frame ):
    scrollbar = tkinter.Scrollbar( frame )
    scrollbar.pack( side=tkinter.RIGHT, fill=tkinter.Y )
    return scrollbar

    def connect_listbox_with_scrollbar( listbox, scrollbar ):
    scrollbar.config( command=listbox.yview ) # call listbox.yview when I move
    listbox.config( yscrollcommand=scrollbar.set ) # call scrollbar.set when I move

    frame = tkinter.Frame( root )
    listbox = add_listbox( frame )
    scrollbar = add_scrollbar( frame )
    connect_listbox_with_scrollbar( listbox, scrollbar )
    frame.pack( expand=tkinter.YES, fill=tkinter.BOTH )
    return listbox

    def create_entryframe( root, entryframe_send_event ):

    def create_entrybox( frame ):
    entrybox = tkinter.scrolledtext.ScrolledText( frame, height=5 )
    entrybox.bind( "<Control-KeyPress-Return>", lambda event: "break" )# suppress default behavior
    entrybox.bind( "<Control-KeyRelease-Return>", self.entryframe_send_event )
    entrybox.pack( side=tkinter.TOP, expand=tkinter.YES, fill=tkinter.BOTH )
    return entrybox

    def create_sendbutton( frame ):
    sendbutton = tkinter.Button( frame, text="Send", command=lambda:self.entryframe_send_event(None) )
    sendbutton.pack( side=tkinter.TOP, expand=tkinter.YES, fill=tkinter.X )
    return sendbutton

    frame = tkinter.Frame( root )
    entrybox = create_entrybox( frame )
    sendbutton = create_sendbutton( frame )
    frame.pack( fill=tkinter.BOTH )
    entrybox.focus_set()
    return entrybox

    self.root = tkinter.Tk()
    self.root.withdraw() # now we can manipulate it without distracting the user
    self.root.geometry( "512x383" )
    self.root.title( versionname )
    self.establish_icon()
    self.listbox = create_messagelist_frame( self.root )
    self.entrybox = create_entryframe( self.root, self.entryframe_send_event )
    self.root.protocol( "WM_DELETE_WINDOW", self.on_closing_situation )
    return

    def establish_icon( self ):
    height = 16
    width = 16
    image = tkinter.PhotoImage( height=16, width=width )
    image.blank()
    for x in range( width ):
    for y in range( height ):
    image.put( "#ffffff",( x, y ))
    for x in range( width ):
    for y in range( 11, 14 ):
    image.put( "#000000",( x, y ))
    self.root.wm_iconphoto( 'True', image )

    def insert_old_messages_from_file_into_the_GUI( self ):
    self.stream_pos = 0
    # on the main thread, to suppress screen updating
    try:
    with open( self.filepath, encoding="utf_8" ) as input:
    latest_data = input.read()
    self.stream_pos = input.tell()
    latest_lines = latest_data.split( '\n' )
    self.root.config( cursor="wait" )
    for line in latest_lines[:-1]:
    self.listbox.insert( tkinter.END, line )
    self.listbox.yview( tkinter.END )
    if re.match( r"^\d\d\d\d-\d\d-\d\dT.*", line ):
    self.listbox.itemconfig( tkinter.END, bg='lightgray' )
    self.root.config( cursor="" )
    except OSError as oserror:
    pass
    self.exiting = False

    def establish_thread_to_update_titlebar( self ):
    # establish a background thread to update the titlebar every second
    freceive_thread = threading.Thread( target=self.every_second_thread )
    freceive_thread.start()

    def establish_thread_to_update_GUI_from_file( self ):
    receive_thread = threading.Thread( target=self.receive_thread )
    receive_thread.start()

    # app commands

    def app_cut_text_from_entry_field( self ):
    # cut the text from the entry box
    msg = self.entrybox.get( "1.0", "end-1c" )
    self.entrybox.delete( "1.0", tkinter.END )
    return msg

    def app_append_text_to_file( self, msg ):
    # append to the file: 1st a time stamp, 2nd the text from the entry box
    try:
    with open( self.filepath, "a", encoding="utf_8" ) as output:
    output.write( datetime.datetime.now( datetime.timezone.utc ).astimezone().isoformat( 'T' ) + "\n" )
    output.write( msg + "\n" )
    except exception as e:
    print( tkinter.END, "\nentrybox_send: append failed." )

    def app_interpret( self, msg ):
    if msg == "exit":
    self.on_closing_situation()

    # events

    def entryframe_send_event( self, event ):
    '''
    The behavior for when the user has pressed the button "send" or equivalent conditions.
    '''
    msg = self.app_cut_text_from_entry_field()
    self.app_append_text_to_file( msg )
    self.app_interpret( msg )
    return "break"

    # situations

    def on_closing_situation( self ):
    self.exiting = True
    self.root.destroy()

    # threads

    def every_second_thread( self ):
    while not self.exiting:
    self.root.title( versionname + " " + datetime.datetime.now( datetime.timezone.utc ).astimezone().isoformat( 'T' ))
    time.sleep( 1 )

    def receive_thread( self ):
    for msg in wait_and_follow( self.filepath, self.stream_pos ):
    if self.exiting: return
    if msg == "":
    if self.exiting: return
    self.root.config( cursor="" )
    time.sleep( 1 )
    else:
    self.root.config( cursor="wait" )
    try:
    if self.exiting: return
    self.listbox.insert( tkinter.END, msg )
    self.listbox.yview( tkinter.END )
    if re.match( r"^\d\d\d\d-\d\d-\d\dT.*", msg ):
    self.listbox.itemconfig( tkinter.END, bg='lightgray' )
    except OSError as oserror:
    print( oserror )
    break

    application = application_class() # returns only after application has ended!

    # last line

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to PythonList@DancesWithMice.info on Mon Oct 31 12:56:22 2022
    dn <PythonList@DancesWithMice.info> writes:
    On 31/10/2022 11.44, Chris Angelico wrote:
    ...
    I'm curious to what extent sloppy English correlates with sloppy code.
    ...
    When it comes to CVs/resumés (see what I did there?), I must admit that
    the most egregious of errors in spelling or grammar do ensure that an >applicant's 'work' is quickly routed to "file 13" (an American-English
    term, many other English-speakers will not have heard previously).

    This discussion reminds me of something Eric Raymond said:

    |While sloppy writing does not invariably mean sloppy thinking,
    |we've generally found the correlation to be strong -- and we
    |have no use for sloppy thinkers. If you can't yet write
    |competently, learn to.
    Eric Raymond

    . Other relevant quotations are:

    |Besides a mathematical inclination, an exceptionally good
    |mastery of one's native tongue is the most vital asset of a
    |competent programmer.
    Edsgar Dijkstra

    |I've found that some of the best [Software ]developers
    |of all are English majors. They'll often graduate with
    |no programming experience at all, and certainly without
    |a clue about the difference between DRAM and EPROM.
    |
    |But they can write. That's the art of conveying
    |information concisely and clearly. Software development
    |and writing are both the art of knowing what you're going
    |to do, and then lucidly expressing your ideas.
    |
    Jack Ganssle

    |The narrative measures of conjunction use, event
    |content, perspective shift, and mental state reference
    |were significantly predictive of later Math scores.
    "Evidence of a Relation between Early Narrative and ..." (2004)
    - DK O’Neill

    |I have never, ever, ever seen a great software developer
    |who does not have amazing attention to detail.
    (2006-08-20) - Rob Walling

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Stefan Ram on Tue Nov 1 08:23:19 2022
    On 01/11/2022 01.56, Stefan Ram wrote:
    dn <PythonList@DancesWithMice.info> writes:
    On 31/10/2022 11.44, Chris Angelico wrote:
    ...
    I'm curious to what extent sloppy English correlates with sloppy code.
    ...
    When it comes to CVs/resumés (see what I did there?), I must admit that
    the most egregious of errors in spelling or grammar do ensure that an
    applicant's 'work' is quickly routed to "file 13" (an American-English
    term, many other English-speakers will not have heard previously).

    This discussion reminds me of something Eric Raymond said:

    |While sloppy writing does not invariably mean sloppy thinking,
    |we've generally found the correlation to be strong -- and we
    |have no use for sloppy thinkers. If you can't yet write
    |competently, learn to.
    Eric Raymond

    . Other relevant quotations are:

    |Besides a mathematical inclination, an exceptionally good
    |mastery of one's native tongue is the most vital asset of a
    |competent programmer.
    Edsgar Dijkstra

    |I've found that some of the best [Software ]developers
    |of all are English majors. They'll often graduate with
    |no programming experience at all, and certainly without
    |a clue about the difference between DRAM and EPROM.
    |
    |But they can write. That's the art of conveying
    |information concisely and clearly. Software development
    |and writing are both the art of knowing what you're going
    |to do, and then lucidly expressing your ideas.
    |
    Jack Ganssle

    |The narrative measures of conjunction use, event
    |content, perspective shift, and mental state reference
    |were significantly predictive of later Math scores.
    "Evidence of a Relation between Early Narrative and ..." (2004)
    - DK O’Neill

    |I have never, ever, ever seen a great software developer
    |who does not have amazing attention to detail.
    (2006-08-20) - Rob Walling

    +1 Thanks for these!
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter J. Holzer@21:1/5 to Peter J. Holzer on Mon Oct 31 22:08:46 2022
    On 2022-10-30 11:26:56 +0100, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    The funny thing is that if I replace foos by Foos it works because it gets known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me.

    But is it even true?

    I just tried to reproduce it (should have done that before answering)
    with mypy 0.942 (included in Ubuntu 22.04 LTS):

    ----[p1]---------------------------------------------------------------
    from typing import List, Optional

    class GLOBALS:
    foos: Optional[Foos]=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE

    def __init__(self):
    pass

    GLOBALS.foos=Foos() -----------------------------------------------------------------------

    ----[p2]---------------------------------------------------------------
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE

    def __init__(self):
    pass

    GLOBALS.Foos=Foos() -----------------------------------------------------------------------

    --- p1 2022-10-31 21:59:49.639869922 +0100
    +++ p2 2022-10-31 21:58:19.815830677 +0100
    @@ -1,7 +1,7 @@
    from typing import List, Optional

    class GLOBALS:
    - foos: Optional[Foos]=None
    + Foos: Optional[Foos]=None

    class Foo:

    @@ -15,4 +15,4 @@
    def __init__(self):
    pass

    -GLOBALS.foos=Foos()
    +GLOBALS.Foos=Foos()

    So the only difference is the capitalization of foos. And mypy accepts
    both (as it probably should):

    % mypy p1
    Success: no issues found in 1 source file
    % mypy p2
    Success: no issues found in 1 source file


    If you did something different, please explain what you did.

    hp

    --
    _ | Peter J. Holzer | Story must make more sense than reality.
    |_|_) | |
    | | | hjp@hjp.at | -- Charles Stross, "Creative writing
    __/ | http://www.hjp.at/ | challenge!"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEETtJbRjyPwVTYGJ5k8g5IURL+KF0FAmNgOVkACgkQ8g5IURL+ KF31HQ/9HKZJ7hVg+F8mt0YN/XU3+EEvvP2UFNcHZVETAvX0x8pUc
  • From Peter J. Holzer@21:1/5 to Peter Otten on Mon Oct 31 22:15:47 2022
    On 2022-10-30 20:43:23 +0100, Peter Otten wrote:
    On 30/10/2022 14:37, Peter J. Holzer wrote:
    On 2022-10-30 09:23:27 -0400, Thomas Passin wrote:
    On 10/30/2022 6:26 AM, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    The funny thing is that if I replace foos by Foos it works because it gets
    known by the initial initialization :-) !
    [...]

    Yes. I was referring to the code as written. Why does that work? I don't think it should.

    For me it makes sense. I think mypy should refrain from trying to figure
    out order of execution.

    I was unclear, sorry. What I meant was "why does replacing foos by Foos
    make the error disappear?" not "why do forward references work?". But
    may have misunderstood what Paulo meant as I cannot reproduce his
    results. So maybe the behaviour I don't understand (and would consider
    buggy) doesn't actually exist.

    hp

    --
    _ | Peter J. Holzer | Story must make more sense than reality.
    |_|_) | |
    | | | hjp@hjp.at | -- Charles Stross, "Creative writing
    __/ | http://www.hjp.at/ | challenge!"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEETtJbRjyPwVTYGJ5k8g5IURL+KF0FAmNgOwMACgkQ8g5IURL+ KF3xjQ/+Jpb4SwheiZ4lO0yuCuK8weaX8RUWAToZ52NHE23Mj8ec0O+q/L9jJtwV wufQLY2FoejeUdq6GqA/puy1kXC8E0bdNWnbzU9p7K4j9+3XBBG83XN0RETqQ4tA 57CEspJzs8sYCiyal5mPdgLVTksuMFDUcoeeFebW2W7ii4NTAGMVRC4fep9fNtq1 KfG+kW2n5kPtrJheX+XPAUcLiRH8SSJj+FwZ8519N7l7SnRu1sYGPqmy/J4LeAa+ oWXIbkZ1e4RQKi51M471a85QEnrT5SNvrwAfxgwLo+jfUGhc+KMuLwZ1TPf8lqQ7 4BXsOZqD1brzh2UA3efBAblvM1xIBILQ55uKUqfZwRGKrb06oK3is4cVT2wbmtyr pTBG/W8CRX8evsO0ZuRJ0rtjnHptxwpC9MqdS45F2vbGzIUrR7x7XiQOtlbKQG0q V855YtdZpCMAcjLBxLJv05JwQIrqFOyDbKw3dIAQ+SFghFp1XBMXdQM9F4+3T5SE K4SIFvDAUgvgjwSxbo4HHXvWtYOLqazVNqsCw6Chgv5nBpzgJISOiioNEqaTxMO9 fga6UKWepOfp7cin15bxYavFFqgl914AUdy/HWvWYRCUDwj+QqVQgS8ynuNZ0dGz s98lVknxUdNb2mT0PBYOT0jNKENng0EtMzd3GKk
  • From Paulo da Silva@21:1/5 to All on Tue Nov 1 02:04:47 2022
    Às 21:08 de 31/10/22, Peter J. Holzer escreveu:
    On 2022-10-30 11:26:56 +0100, Peter J. Holzer wrote:
    On 2022-10-29 23:59:44 +0100, Paulo da Silva wrote:
    The funny thing is that if I replace foos by Foos it works because it gets >>> known by the initial initialization :-) !

    ________________________
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None
    [...]
    class Foos:

    That seems like a bug to me.

    But is it even true?

    I just tried to reproduce it (should have done that before answering)
    with mypy 0.942 (included in Ubuntu 22.04 LTS):

    ----[p1]---------------------------------------------------------------
    from typing import List, Optional

    class GLOBALS:
    foos: Optional[Foos]=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE

    def __init__(self):
    pass

    GLOBALS.foos=Foos() -----------------------------------------------------------------------

    ----[p2]---------------------------------------------------------------
    from typing import List, Optional

    class GLOBALS:
    Foos: Optional[Foos]=None

    class Foo:

    def __init__(self):
    pass

    class Foos:
    Foos: List[Foo]=[]
    # SOME GLOBALS ARE USED HERE

    def __init__(self):
    pass

    GLOBALS.Foos=Foos() -----------------------------------------------------------------------

    --- p1 2022-10-31 21:59:49.639869922 +0100
    +++ p2 2022-10-31 21:58:19.815830677 +0100
    @@ -1,7 +1,7 @@
    from typing import List, Optional

    class GLOBALS:
    - foos: Optional[Foos]=None
    + Foos: Optional[Foos]=None

    class Foo:

    @@ -15,4 +15,4 @@
    def __init__(self):
    pass

    -GLOBALS.foos=Foos()
    +GLOBALS.Foos=Foos()

    So the only difference is the capitalization of foos. And mypy accepts
    both (as it probably should):

    % mypy p1
    Success: no issues found in 1 source file
    % mypy p2
    Success: no issues found in 1 source file


    If you did something different, please explain what you did.

    Yes for mypy.
    Try to run them (python3 <your script name>).

    Paulo

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