1- """This module provides static function to handle multiple sessions of SAP.
1+ """This module provides static functions to handle multiple sessions of SAP.
22Using this module you can spawn multiple sessions and automatically execute
33a function in parallel on the sessions."""
44
55import time
66import threading
7+ import math
78from typing import Callable
9+
810import pythoncom
911import win32com .client
1012import win32gui
1113
1214def run_with_session (session_index :int , func :Callable , args :tuple ) -> None :
13- """Run a function in a sepcific session based on the sessions index.
14- This function is meant to be run inside a seperate thread.
15+ """Run a function in a specific session based on the sessions index.
16+ This function is meant to be run inside a separate thread.
1517 The function must take a session object as its first argument.
1618 Note that this function will not spawn the sessions before running,
1719 use spawn_sessions to do that.
1820 """
1921
2022 pythoncom .CoInitialize ()
2123
22- SAP = win32com .client .GetObject ("SAPGUI" )
23- app = SAP .GetScriptingEngine
24+ sap = win32com .client .GetObject ("SAPGUI" )
25+ app = sap .GetScriptingEngine
2426 connection = app .Connections (0 )
2527 session = connection .Sessions (session_index )
2628
2729 func (session , * args )
2830
2931 pythoncom .CoUninitialize ()
3032
33+
3134def run_batch (func :Callable , args :tuple [tuple ], num_sessions = 6 ) -> None :
3235 """Run a function in parallel sessions.
3336 The function will be run {num_sessions} times with args[i] as input.
@@ -40,7 +43,7 @@ def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
4043 for i in range (num_sessions ):
4144 t = ExThread (target = run_with_session , args = (i , func , args [i ]))
4245 threads .append (t )
43-
46+
4447 for t in threads :
4548 t .start ()
4649 for t in threads :
@@ -49,6 +52,7 @@ def run_batch(func:Callable, args:tuple[tuple], num_sessions=6) -> None:
4952 if t .error :
5053 raise t .error
5154
55+
5256def run_batches (func :Callable , args :tuple [tuple ], num_sessions = 6 ):
5357 """Run a function in parallel batches.
5458 This function runs the input function for each set of arguments in args.
@@ -62,16 +66,26 @@ def run_batches(func:Callable, args:tuple[tuple], num_sessions=6):
6266 batch = args [b :b + num_sessions ]
6367 run_batch (func , args , len (batch ))
6468
65- def spawn_sessions (num_sessions = 6 ) -> list :
69+
70+ def spawn_sessions (num_sessions = 6 ) -> tuple :
6671 """A function to spawn multiple sessions of SAP.
6772 This function will attempt to spawn the desired number of sessions.
68- If the current number of open sessions exceeds the desired number of sessions
73+ If the current number of already open sessions exceeds the desired number of sessions
6974 the already open sessions will not be closed to match the desired number.
7075 The number of sessions must be between 1 and 6.
71- Returns a list of all open sessions.
76+
77+ Args:
78+ num_sessions: The number of sessions desired. Defaults to 6.
79+
80+ Raises:
81+ ValueError: If the number of sessions is not between 1 and 6.
82+
83+ Returns:
84+ tuple: A tuple of all currently open sessions.
7285 """
73- SAP = win32com .client .GetObject ("SAPGUI" )
74- app = SAP .GetScriptingEngine
86+
87+ sap = win32com .client .GetObject ("SAPGUI" )
88+ app = sap .GetScriptingEngine
7589 connection = app .Connections (0 )
7690 session = connection .Sessions (0 )
7791
@@ -82,25 +96,17 @@ def spawn_sessions(num_sessions=6) -> list:
8296
8397 for _ in range (num_sessions - connection .Sessions .count ):
8498 session .CreateSession ()
85-
99+
86100 # Wait for the sessions to spawn
87101 while connection .Sessions .count < num_sessions :
88102 time .sleep (0.1 )
89103
90- sessions = list (connection .Sessions )
104+ sessions = tuple (connection .Sessions )
91105 num_sessions = len (sessions )
92106
93- if num_sessions == 1 :
94- c = 1
95- elif num_sessions <= 4 :
96- c = 2
97- elif num_sessions <= 6 :
98- c = 3
99-
100- if num_sessions < 3 :
101- r = 1
102- else :
103- r = 2
107+ # Calculate number of columns and rows
108+ c = math .ceil (math .sqrt (num_sessions ))
109+ r = math .ceil (num_sessions / c )
104110
105111 w , h = 1920 // c , 1040 // r
106112
@@ -111,20 +117,22 @@ def spawn_sessions(num_sessions=6) -> list:
111117 x = i % c * w
112118 y = i // c * h
113119 win32gui .MoveWindow (hwnd , x , y , w , h , True )
114-
120+
115121 return sessions
116122
117- def get_all_SAP_sessions () -> tuple :
123+
124+ def get_all_SAP_sessions () -> tuple : # pylint: disable=invalid-name
118125 """Returns a tuple of all open SAP sessions (on connection index 0).
119126
120127 Returns:
121128 tuple: A tuple of SAP GuiSession objects.
122129 """
123- SAP = win32com .client .GetObject ("SAPGUI" )
124- app = SAP .GetScriptingEngine
130+ sap = win32com .client .GetObject ("SAPGUI" )
131+ app = sap .GetScriptingEngine
125132 connection = app .Connections (0 )
126133 return tuple (connection .Sessions )
127134
135+
128136class ExThread (threading .Thread ):
129137 """A thread with a handle to get an exception raised inside the thread: ExThread.error"""
130138 def __init__ (self , * args , ** kwargs ):
@@ -136,5 +144,3 @@ def run(self):
136144 self ._target (* self ._args , ** self ._kwargs )
137145 except Exception as e : # pylint: disable=broad-exception-caught
138146 self .error = e
139-
140-
0 commit comments