25
25
@author Martin Landa <landa.martin gmail.com>
26
26
"""
27
27
28
+ from __future__ import annotations
29
+
30
+ import errno
31
+ import locale
28
32
import os
33
+ import signal
34
+ import subprocess
29
35
import sys
30
36
import time
31
- import errno
32
- import signal
33
37
import traceback
34
- import locale
35
- import subprocess
36
38
from threading import Thread
37
- import wx
39
+ from typing import TYPE_CHECKING , TextIO
38
40
41
+ import wx
39
42
from core .debug import Debug
40
43
from core .globalvar import SCT_EXT
41
44
44
47
45
48
is_mswindows = sys .platform == "win32"
46
49
if is_mswindows :
50
+ import msvcrt
51
+
47
52
from win32file import ReadFile , WriteFile
48
53
from win32pipe import PeekNamedPipe
49
- import msvcrt
50
54
else :
51
- import select
52
55
import fcntl
56
+ import select
57
+
58
+ if TYPE_CHECKING :
59
+ from io import TextIOWrapper
53
60
54
61
55
62
def DecodeString (string ):
@@ -298,7 +305,7 @@ def _recv(self, which, maxsize):
298
305
message = "Other end disconnected!"
299
306
300
307
301
- def recv_some (p , t = 0.1 , e = 1 , tr = 5 , stderr = 0 ):
308
+ def recv_some (p , t = 0.1 , e = 1 , tr = 5 , stderr = 0 ) -> str : # TODO: use LiteralString on 3.11+
302
309
tr = max (tr , 1 )
303
310
x = time .time () + t
304
311
y = []
@@ -342,7 +349,7 @@ def __init__(
342
349
stdin = None ,
343
350
verbose = None ,
344
351
wait = True ,
345
- rerr = False ,
352
+ rerr : bool | None = False ,
346
353
stdout = None ,
347
354
stderr = None ,
348
355
):
@@ -482,7 +489,7 @@ def __ProcessStdErr(self):
482
489
type = "WARNING"
483
490
elif "GRASS_INFO_ERROR" in line : # error
484
491
type = "ERROR"
485
- elif "GRASS_INFO_END" : # end of message
492
+ elif "GRASS_INFO_END" in line : # end of message
486
493
msg .append ((type , content ))
487
494
type = None
488
495
content = ""
@@ -510,7 +517,14 @@ class CommandThread(Thread):
510
517
"""Create separate thread for command. Used for commands launched
511
518
on the background."""
512
519
513
- def __init__ (self , cmd , env = None , stdin = None , stdout = sys .stdout , stderr = sys .stderr ):
520
+ def __init__ (
521
+ self ,
522
+ cmd ,
523
+ env = None ,
524
+ stdin : TextIOWrapper | None = None ,
525
+ stdout : TextIO = sys .stdout ,
526
+ stderr : TextIO = sys .stderr ,
527
+ ) -> None :
514
528
"""
515
529
:param cmd: command (given as list)
516
530
:param env: environmental variables
@@ -522,11 +536,11 @@ def __init__(self, cmd, env=None, stdin=None, stdout=sys.stdout, stderr=sys.stde
522
536
523
537
self .cmd = cmd
524
538
self .stdin = stdin
525
- self .stdout = stdout
526
- self .stderr = stderr
539
+ self .stdout : TextIO = stdout
540
+ self .stderr : TextIO = stderr
527
541
self .env = env
528
542
529
- self .module = None
543
+ self .module : Popen | None = None
530
544
self .error = ""
531
545
532
546
self ._want_abort = False
@@ -584,7 +598,7 @@ def run(self):
584
598
print (e , file = sys .stderr )
585
599
return 1
586
600
587
- if self .stdin : # read stdin if requested ...
601
+ if self .stdin and self . module . stdin is not None : # read stdin if requested...
588
602
self .module .stdin .write (self .stdin )
589
603
self .module .stdin .close ()
590
604
@@ -593,34 +607,35 @@ def run(self):
593
607
594
608
def _redirect_stream (self ):
595
609
"""Redirect stream"""
596
- if self .stdout :
610
+ if self .stdout and self . module is not None and self . module . stdout is not None :
597
611
# make module stdout/stderr non-blocking
598
612
out_fileno = self .module .stdout .fileno ()
599
613
if not is_mswindows :
600
614
flags = fcntl .fcntl (out_fileno , fcntl .F_GETFL )
601
615
fcntl .fcntl (out_fileno , fcntl .F_SETFL , flags | os .O_NONBLOCK )
602
616
603
- if self .stderr :
617
+ if self .stderr and self . module is not None and self . module . stderr is not None :
604
618
# make module stdout/stderr non-blocking
605
619
out_fileno = self .module .stderr .fileno ()
606
620
if not is_mswindows :
607
621
flags = fcntl .fcntl (out_fileno , fcntl .F_GETFL )
608
622
fcntl .fcntl (out_fileno , fcntl .F_SETFL , flags | os .O_NONBLOCK )
609
623
610
624
# wait for the process to end, sucking in stuff until it does end
611
- while self .module .poll () is None :
612
- if self ._want_abort : # abort running process
613
- self .module .terminate ()
614
- self .aborted = True
615
- return
616
- if self .stdout :
617
- line = recv_some (self .module , e = 0 , stderr = 0 )
618
- self .stdout .write (line )
619
- if self .stderr :
620
- line = recv_some (self .module , e = 0 , stderr = 1 )
621
- self .stderr .write (line )
622
- if len (line ) > 0 :
623
- self .error = line
625
+ if self .module is not None :
626
+ while self .module .poll () is None :
627
+ if self ._want_abort : # abort running process
628
+ self .module .terminate ()
629
+ self .aborted = True
630
+ return
631
+ if self .stdout :
632
+ line = recv_some (self .module , e = 0 , stderr = 0 )
633
+ self .stdout .write (line )
634
+ if self .stderr :
635
+ line = recv_some (self .module , e = 0 , stderr = 1 )
636
+ self .stderr .write (line )
637
+ if len (line ) > 0 :
638
+ self .error = line
624
639
625
640
# get the last output
626
641
if self .stdout :
@@ -632,12 +647,12 @@ def _redirect_stream(self):
632
647
if len (line ) > 0 :
633
648
self .error = line
634
649
635
- def abort (self ):
650
+ def abort (self ) -> None :
636
651
"""Abort running process, used by main thread to signal an abort"""
637
652
self ._want_abort = True
638
653
639
654
640
- def _formatMsg (text ) :
655
+ def _formatMsg (text : str ) -> str :
641
656
"""Format error messages for dialogs"""
642
657
message = ""
643
658
for line in text .splitlines ():
@@ -660,14 +675,14 @@ def _formatMsg(text):
660
675
def RunCommand (
661
676
prog ,
662
677
flags = "" ,
663
- overwrite = False ,
664
- quiet = False ,
665
- verbose = False ,
678
+ overwrite : bool = False ,
679
+ quiet : bool = False ,
680
+ verbose : bool = False ,
666
681
parent = None ,
667
- read = False ,
682
+ read : bool = False ,
668
683
parse = None ,
669
- stdin = None ,
670
- getErrorMsg = False ,
684
+ stdin : TextIO | None = None ,
685
+ getErrorMsg : bool = False ,
671
686
env = None ,
672
687
** kwargs ,
673
688
):
@@ -717,7 +732,7 @@ def RunCommand(
717
732
718
733
ps = grass .start_command (prog , flags , overwrite , quiet , verbose , env = env , ** kwargs )
719
734
720
- if stdin :
735
+ if stdin and ps . stdin :
721
736
ps .stdin .write (encode (stdin ))
722
737
ps .stdin .close ()
723
738
ps .stdin = None
@@ -764,7 +779,7 @@ def RunCommand(
764
779
return stdout , _formatMsg (stderr )
765
780
766
781
767
- def GetDefaultEncoding (forceUTF8 = False ):
782
+ def GetDefaultEncoding (forceUTF8 : bool = False ) -> str :
768
783
"""Get default system encoding
769
784
770
785
:param bool forceUTF8: force 'UTF-8' if encoding is not defined
@@ -786,4 +801,4 @@ def GetDefaultEncoding(forceUTF8=False):
786
801
return enc
787
802
788
803
789
- _enc = GetDefaultEncoding () # define as global variable
804
+ _enc : str = GetDefaultEncoding () # define as global variable
0 commit comments