1010import pythoncom
1111import win32com .client
1212import win32gui
13+ import win32api
1314
14- def run_with_session (session_index :int , func :Callable , args :tuple ) -> None :
15+
16+ def run_with_session (session_index : int , func : Callable , args : tuple ) -> None :
1517 """Run a function in a specific session based on the sessions index.
1618 This function is meant to be run inside a separate thread.
1719 The function must take a session object as its first argument.
1820 Note that this function will not spawn the sessions before running,
1921 use spawn_sessions to do that.
2022 """
21-
2223 pythoncom .CoInitialize ()
2324
2425 sap = win32com .client .GetObject ("SAPGUI" )
@@ -31,17 +32,24 @@ def run_with_session(session_index:int, func:Callable, args:tuple) -> None:
3132 pythoncom .CoUninitialize ()
3233
3334
34- def run_batch (func :Callable , args :tuple [tuple ], num_sessions = 6 ) -> None :
35+ def run_batch (func : Callable , args : tuple [tuple ]) -> None :
3536 """Run a function in parallel sessions.
36- The function will be run {num_sessions} times with args[i] as input .
37+ A number of threads equal to the length of args will be spawned .
3738 The function must take a session object as its first argument.
3839 Note that this function will not spawn the sessions before running,
3940 use spawn_sessions to do that.
41+
42+ Args:
43+ func: A callable function to run in the threads.
44+ args: A tuple of tuples containing arguments to be passed to func.
45+
46+ Raises:
47+ Exception: Any exception raised in any of the threads.
4048 """
4149
4250 threads = []
43- for i in range ( num_sessions ):
44- t = ExThread (target = run_with_session , args = (i , func , args [ i ] ))
51+ for i , arg in enumerate ( args ):
52+ t = ExThread (target = run_with_session , args = (i , func , arg ))
4553 threads .append (t )
4654
4755 for t in threads :
@@ -53,7 +61,7 @@ def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
5361 raise t .error
5462
5563
56- def run_batches (func :Callable , args :tuple [tuple ], num_sessions = 6 ) :
64+ def run_batches (func : Callable , args : tuple [tuple ], num_sessions : int = 6 ) -> None :
5765 """Run a function in parallel batches.
5866 This function runs the input function for each set of arguments in args.
5967 The function will be run in parallel batches of size {num_sessions}.
@@ -64,7 +72,7 @@ def run_batches(func:Callable, args:tuple[tuple], num_sessions=6):
6472
6573 for b in range (0 , len (args ), num_sessions ):
6674 batch = args [b :b + num_sessions ]
67- run_batch (func , args , len ( batch ) )
75+ run_batch (func , batch )
6876
6977
7078def spawn_sessions (num_sessions = 6 ) -> list :
@@ -100,14 +108,39 @@ def spawn_sessions(num_sessions=6) -> list:
100108 while connection .Sessions .count < num_sessions :
101109 time .sleep (0.1 )
102110
103- sessions = tuple (connection .Sessions )
111+ arrange_sessions ()
112+
113+ return tuple (connection .Sessions )
114+
115+
116+ def get_all_sap_sessions () -> tuple :
117+ """Returns a tuple of all open SAP sessions (on connection index 0).
118+
119+ Returns:
120+ tuple: A tuple of SAP GuiSession objects.
121+ """
122+ sap = win32com .client .GetObject ("SAPGUI" )
123+ app = sap .GetScriptingEngine
124+ connection = app .Connections (0 )
125+ return tuple (connection .Sessions )
126+
127+
128+ def arrange_sessions ():
129+ """Take all toplevel windows of currently open SAP sessions
130+ and arrange them equally on the screen.
131+ """
132+ sessions = get_all_sap_sessions ()
104133 num_sessions = len (sessions )
105134
106135 # Calculate number of columns and rows
107136 c = math .ceil (math .sqrt (num_sessions ))
108137 r = math .ceil (num_sessions / c )
109138
110- w , h = 1920 // c , 1040 // r
139+ screen_width = win32api .GetSystemMetrics (0 )
140+ screen_height = win32api .GetSystemMetrics (1 )
141+
142+ w = screen_width // c
143+ h = screen_height // r
111144
112145 for i , session in enumerate (sessions ):
113146 window = session .findById ("wnd[0]" )
@@ -117,20 +150,6 @@ def spawn_sessions(num_sessions=6) -> list:
117150 y = i // c * h
118151 win32gui .MoveWindow (hwnd , x , y , w , h , True )
119152
120- return sessions
121-
122-
123- def get_all_sap_sessions () -> tuple :
124- """Returns a tuple of all open SAP sessions (on connection index 0).
125-
126- Returns:
127- tuple: A tuple of SAP GuiSession objects.
128- """
129- sap = win32com .client .GetObject ("SAPGUI" )
130- app = sap .GetScriptingEngine
131- connection = app .Connections (0 )
132- return tuple (connection .Sessions )
133-
134153
135154class ExThread (threading .Thread ):
136155 """A thread with a handle to get an exception raised inside the thread: ExThread.error"""
@@ -141,5 +160,5 @@ def __init__(self, *args, **kwargs):
141160 def run (self ):
142161 try :
143162 self ._target (* self ._args , ** self ._kwargs )
144- except Exception as e : # pylint: disable=broad-exception-caught
163+ except Exception as e : # pylint: disable=broad-exception-caught
145164 self .error = e
0 commit comments