Skip to content

Commit be51520

Browse files
chore: Use proper type declarations for methods returning self instances (appium#1039)
1 parent e4b40ae commit be51520

19 files changed

+116
-151
lines changed

Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ types-python-dateutil = "~=2.9"
2020

2121
[packages]
2222
selenium = "~=4.24"
23+
typing-extensions = "~=4.12.2"

appium/webdriver/extensions/action_helpers.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@
1919
from selenium.webdriver.common.actions.action_builder import ActionBuilder
2020
from selenium.webdriver.common.actions.mouse_button import MouseButton
2121
from selenium.webdriver.common.actions.pointer_input import PointerInput
22+
from typing_extensions import Self
2223

2324
from appium.webdriver.webelement import WebElement
2425

2526
if TYPE_CHECKING:
27+
# noinspection PyUnresolvedReferences
2628
from appium.webdriver.webdriver import WebDriver
2729

2830

2931
class ActionHelpers:
30-
def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Optional[int] = None) -> 'WebDriver':
32+
def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Optional[int] = None) -> Self:
3133
"""Scrolls from one element to another
3234
3335
Args:
@@ -48,7 +50,7 @@ def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Op
4850

4951
touch_input = PointerInput(interaction.POINTER_TOUCH, 'touch')
5052

51-
actions = ActionChains(self)
53+
actions = ActionChains(cast('WebDriver', self))
5254
actions.w3c_actions = ActionBuilder(self, mouse=touch_input)
5355

5456
# https://github.com/SeleniumHQ/selenium/blob/3c82c868d4f2a7600223a1b3817301d0b04d28e4/py/selenium/webdriver/common/actions/pointer_actions.py#L83
@@ -59,11 +61,9 @@ def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Op
5961
actions.w3c_actions.pointer_action.move_to(destination_el)
6062
actions.w3c_actions.pointer_action.release()
6163
actions.perform()
62-
return cast('WebDriver', self)
64+
return self
6365

64-
def drag_and_drop(
65-
self, origin_el: WebElement, destination_el: WebElement, pause: Optional[float] = None
66-
) -> 'WebDriver':
66+
def drag_and_drop(self, origin_el: WebElement, destination_el: WebElement, pause: Optional[float] = None) -> Self:
6767
"""Drag the origin element to the destination element
6868
6969
Args:
@@ -74,17 +74,17 @@ def drag_and_drop(
7474
Returns:
7575
Union['WebDriver', 'ActionHelpers']: Self instance
7676
"""
77-
actions = ActionChains(self)
77+
actions = ActionChains(cast('WebDriver', self))
7878
# 'mouse' pointer action
7979
actions.w3c_actions.pointer_action.click_and_hold(origin_el)
8080
if pause is not None and pause > 0:
8181
actions.w3c_actions.pointer_action.pause(pause)
8282
actions.w3c_actions.pointer_action.move_to(destination_el)
8383
actions.w3c_actions.pointer_action.release()
8484
actions.perform()
85-
return cast('WebDriver', self)
85+
return self
8686

87-
def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None) -> 'WebDriver':
87+
def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None) -> Self:
8888
"""Taps on an particular place with up to five fingers, holding for a
8989
certain time
9090
@@ -100,7 +100,7 @@ def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None)
100100
Union['WebDriver', 'ActionHelpers']: Self instance
101101
"""
102102
if len(positions) == 1:
103-
actions = ActionChains(self)
103+
actions = ActionChains(cast('WebDriver', self))
104104
actions.w3c_actions = ActionBuilder(self, mouse=PointerInput(interaction.POINTER_TOUCH, 'touch'))
105105
x = positions[0][0]
106106
y = positions[0][1]
@@ -114,7 +114,7 @@ def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None)
114114
actions.perform()
115115
else:
116116
finger = 0
117-
actions = ActionChains(self)
117+
actions = ActionChains(cast('WebDriver', self))
118118
actions.w3c_actions.devices = []
119119

120120
for position in positions:
@@ -132,9 +132,9 @@ def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None)
132132
new_input.create_pause(0.1)
133133
new_input.create_pointer_up(MouseButton.LEFT)
134134
actions.perform()
135-
return cast('WebDriver', self)
135+
return self
136136

137-
def swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: int = 0) -> 'WebDriver':
137+
def swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: int = 0) -> Self:
138138
"""Swipe from one point to another point, for an optional duration.
139139
140140
Args:
@@ -152,7 +152,7 @@ def swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: in
152152
"""
153153
touch_input = PointerInput(interaction.POINTER_TOUCH, 'touch')
154154

155-
actions = ActionChains(self)
155+
actions = ActionChains(cast('WebDriver', self))
156156
actions.w3c_actions = ActionBuilder(self, mouse=touch_input)
157157
actions.w3c_actions.pointer_action.move_to_location(start_x, start_y)
158158
actions.w3c_actions.pointer_action.pointer_down()
@@ -161,9 +161,9 @@ def swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: in
161161
actions.w3c_actions.pointer_action.move_to_location(end_x, end_y)
162162
actions.w3c_actions.pointer_action.release()
163163
actions.perform()
164-
return cast('WebDriver', self)
164+
return self
165165

166-
def flick(self, start_x: int, start_y: int, end_x: int, end_y: int) -> 'WebDriver':
166+
def flick(self, start_x: int, start_y: int, end_x: int, end_y: int) -> Self:
167167
"""Flick from one point to another point.
168168
169169
Args:
@@ -178,11 +178,11 @@ def flick(self, start_x: int, start_y: int, end_x: int, end_y: int) -> 'WebDrive
178178
Returns:
179179
Union['WebDriver', 'ActionHelpers']: Self instance
180180
"""
181-
actions = ActionChains(self)
181+
actions = ActionChains(cast('WebDriver', self))
182182
actions.w3c_actions = ActionBuilder(self, mouse=PointerInput(interaction.POINTER_TOUCH, 'touch'))
183183
actions.w3c_actions.pointer_action.move_to_location(start_x, start_y)
184184
actions.w3c_actions.pointer_action.pointer_down()
185185
actions.w3c_actions.pointer_action.move_to_location(end_x, end_y)
186186
actions.w3c_actions.pointer_action.release()
187187
actions.perform()
188-
return cast('WebDriver', self)
188+
return self

appium/webdriver/extensions/android/common.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,18 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
from typing import TYPE_CHECKING, cast
1514

1615
from selenium.common.exceptions import UnknownMethodException
16+
from typing_extensions import Self
1717

1818
from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands
1919
from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts
2020
from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
2121
from appium.webdriver.mobilecommand import MobileCommand as Command
2222

23-
if TYPE_CHECKING:
24-
from appium.webdriver.webdriver import WebDriver
25-
2623

2724
class Common(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence):
28-
def open_notifications(self) -> 'WebDriver':
25+
def open_notifications(self) -> Self:
2926
"""Open notification shade in Android (API Level 18 and above)
3027
3128
Returns:
@@ -37,7 +34,7 @@ def open_notifications(self) -> 'WebDriver':
3734
except UnknownMethodException:
3835
# TODO: Remove the fallback
3936
self.mark_extension_absence(ext_name).execute(Command.OPEN_NOTIFICATIONS, {})
40-
return cast('WebDriver', self)
37+
return self
4138

4239
@property
4340
def current_package(self) -> str:

appium/webdriver/extensions/android/gsm.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import TYPE_CHECKING, cast
16-
1715
from selenium.common.exceptions import UnknownMethodException
16+
from typing_extensions import Self
1817

1918
from appium.common.helper import extract_const_attributes
2019
from appium.common.logger import logger
@@ -23,9 +22,6 @@
2322
from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
2423
from appium.webdriver.mobilecommand import MobileCommand as Command
2524

26-
if TYPE_CHECKING:
27-
from appium.webdriver.webdriver import WebDriver
28-
2925

3026
class GsmCallActions:
3127
CALL = 'call'
@@ -53,7 +49,7 @@ class GsmVoiceState:
5349

5450

5551
class Gsm(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence):
56-
def make_gsm_call(self, phone_number: str, action: str) -> 'WebDriver':
52+
def make_gsm_call(self, phone_number: str, action: str) -> Self:
5753
"""Make GSM call (Emulator only)
5854
5955
Android only.
@@ -82,9 +78,9 @@ def make_gsm_call(self, phone_number: str, action: str) -> 'WebDriver':
8278
except UnknownMethodException:
8379
# TODO: Remove the fallback
8480
self.mark_extension_absence(ext_name).execute(Command.MAKE_GSM_CALL, args)
85-
return cast('WebDriver', self)
81+
return self
8682

87-
def set_gsm_signal(self, strength: int) -> 'WebDriver':
83+
def set_gsm_signal(self, strength: int) -> Self:
8884
"""Set GSM signal strength (Emulator only)
8985
9086
Android only.
@@ -113,9 +109,9 @@ def set_gsm_signal(self, strength: int) -> 'WebDriver':
113109
self.mark_extension_absence(ext_name).execute(
114110
Command.SET_GSM_SIGNAL, {'signalStrength': strength, 'signalStrengh': strength}
115111
)
116-
return cast('WebDriver', self)
112+
return self
117113

118-
def set_gsm_voice(self, state: str) -> 'WebDriver':
114+
def set_gsm_voice(self, state: str) -> Self:
119115
"""Set GSM voice state (Emulator only)
120116
121117
Android only.
@@ -143,7 +139,7 @@ def set_gsm_voice(self, state: str) -> 'WebDriver':
143139
except UnknownMethodException:
144140
# TODO: Remove the fallback
145141
self.mark_extension_absence(ext_name).execute(Command.SET_GSM_VOICE, args)
146-
return cast('WebDriver', self)
142+
return self
147143

148144
def _add_commands(self) -> None:
149145
# noinspection PyProtectedMember,PyUnresolvedReferences

appium/webdriver/extensions/android/network.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import TYPE_CHECKING, cast
16-
1715
from selenium.common.exceptions import UnknownMethodException
16+
from typing_extensions import Self
1817

1918
from appium.common.helper import extract_const_attributes
2019
from appium.common.logger import logger
@@ -23,9 +22,6 @@
2322
from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
2423
from appium.webdriver.mobilecommand import MobileCommand as Command
2524

26-
if TYPE_CHECKING:
27-
from appium.webdriver.webdriver import WebDriver
28-
2925

3026
class NetSpeed:
3127
GSM = 'gsm' # GSM/CSD (up: 14.4(kbps), down: 14.4(kbps))
@@ -114,7 +110,7 @@ def set_network_connection(self, connection_type: int) -> int:
114110
Command.SET_NETWORK_CONNECTION, {'parameters': {'type': connection_type}}
115111
)['value']
116112

117-
def toggle_wifi(self) -> 'WebDriver':
113+
def toggle_wifi(self) -> Self:
118114
"""Toggle the wifi on the device, Android only.
119115
This API only works reliably on emulators (any version) and real devices
120116
since API level 31.
@@ -129,9 +125,9 @@ def toggle_wifi(self) -> 'WebDriver':
129125
)
130126
except UnknownMethodException:
131127
self.mark_extension_absence(ext_name).execute(Command.TOGGLE_WIFI, {})
132-
return cast('WebDriver', self)
128+
return self
133129

134-
def set_network_speed(self, speed_type: str) -> 'WebDriver':
130+
def set_network_speed(self, speed_type: str) -> Self:
135131
"""Set the network speed emulation.
136132
137133
Android Emulator only.
@@ -158,7 +154,7 @@ def set_network_speed(self, speed_type: str) -> 'WebDriver':
158154
except UnknownMethodException:
159155
# TODO: Remove the fallback
160156
self.mark_extension_absence(ext_name).execute(Command.SET_NETWORK_SPEED, {'netspeed': speed_type})
161-
return cast('WebDriver', self)
157+
return self
162158

163159
def _add_commands(self) -> None:
164160
# noinspection PyProtectedMember,PyUnresolvedReferences

appium/webdriver/extensions/android/power.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,19 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import TYPE_CHECKING, cast
16-
1715
from selenium.common.exceptions import UnknownMethodException
16+
from typing_extensions import Self
1817

1918
from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands
2019
from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts
2120
from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
2221
from appium.webdriver.mobilecommand import MobileCommand as Command
2322

24-
if TYPE_CHECKING:
25-
from appium.webdriver.webdriver import WebDriver
26-
2723

2824
class Power(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence):
2925
AC_OFF, AC_ON = 'off', 'on'
3026

31-
def set_power_capacity(self, percent: int) -> 'WebDriver':
27+
def set_power_capacity(self, percent: int) -> Self:
3228
"""Emulate power capacity change on the connected emulator.
3329
3430
Android only.
@@ -49,9 +45,9 @@ def set_power_capacity(self, percent: int) -> 'WebDriver':
4945
except UnknownMethodException:
5046
# TODO: Remove the fallback
5147
self.mark_extension_absence(ext_name).execute(Command.SET_POWER_CAPACITY, args)
52-
return cast('WebDriver', self)
48+
return self
5349

54-
def set_power_ac(self, ac_state: str) -> 'WebDriver':
50+
def set_power_ac(self, ac_state: str) -> Self:
5551
"""Emulate power state change on the connected emulator.
5652
5753
Android only.
@@ -73,7 +69,7 @@ def set_power_ac(self, ac_state: str) -> 'WebDriver':
7369
except UnknownMethodException:
7470
# TODO: Remove the fallback
7571
self.mark_extension_absence(ext_name).execute(Command.SET_POWER_AC, args)
76-
return cast('WebDriver', self)
72+
return self
7773

7874
def _add_commands(self) -> None:
7975
# noinspection PyProtectedMember,PyUnresolvedReferences

appium/webdriver/extensions/android/sms.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,17 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import TYPE_CHECKING, cast
16-
1715
from selenium.common.exceptions import UnknownMethodException
16+
from typing_extensions import Self
1817

1918
from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands
2019
from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts
2120
from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence
2221
from appium.webdriver.mobilecommand import MobileCommand as Command
2322

24-
if TYPE_CHECKING:
25-
from appium.webdriver.webdriver import WebDriver
26-
2723

2824
class Sms(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence):
29-
def send_sms(self, phone_number: str, message: str) -> 'WebDriver':
25+
def send_sms(self, phone_number: str, message: str) -> Self:
3026
"""Emulate send SMS event on the connected emulator.
3127
3228
Android only.
@@ -48,7 +44,7 @@ def send_sms(self, phone_number: str, message: str) -> 'WebDriver':
4844
except UnknownMethodException:
4945
# TODO: Remove the fallback
5046
self.mark_extension_absence(ext_name).execute(Command.SEND_SMS, args)
51-
return cast('WebDriver', self)
47+
return self
5248

5349
def _add_commands(self) -> None:
5450
# noinspection PyProtectedMember,PyUnresolvedReferences

0 commit comments

Comments
 (0)