Skip to content

Commit

Permalink
Merge pull request #361 from doronz88/refactor/remove-python38-support
Browse files Browse the repository at this point in the history
remove python3.8 support
  • Loading branch information
doronz88 authored Oct 10, 2024
2 parents 2c86ba5 + 121ea24 commit f6fae38
Show file tree
Hide file tree
Showing 36 changed files with 147 additions and 162 deletions.
8 changes: 1 addition & 7 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: [ 3.8, 3.9, "3.10", 3.11, 3.12 ]
python-version: [ 3.9, "3.10", 3.11, 3.12 ]

steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -106,9 +106,6 @@ jobs:
strategy:
matrix:
include:
- os: macos-latest
arch: arm64
python-version: "3.8"
- os: macos-latest
arch: arm64
python-version: "3.9"
Expand All @@ -122,9 +119,6 @@ jobs:
arch: arm64
python-version: "3.12"

- os: macos-latest
arch: x86_64
python-version: "3.8"
- os: macos-latest
arch: x86_64
python-version: "3.9"
Expand Down
3 changes: 1 addition & 2 deletions src/rpcclient/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "rpcclient"
description = "rpcclient for connecting with the rpcserver"
readme = "README.md"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = { text = "GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007" }
keywords = ["ios", "macos", "linux", "automation", "remote-shell", "remote-control", "ipython"]
authors = [
Expand All @@ -19,7 +19,6 @@ classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand Down
12 changes: 6 additions & 6 deletions src/rpcclient/rpcclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from collections import namedtuple
from pathlib import Path
from select import select
from typing import Any
from typing import Any, Optional

import IPython
from traitlets.config import Config
Expand Down Expand Up @@ -164,7 +164,7 @@ def dlsym(self, lib: int, symbol_name: str):
response = self._sock.send_recv(command)
return response.ptr

def call(self, address: int, argv: typing.List[int] = None, return_float64=False, return_float32=False,
def call(self, address: int, argv: list[int] = None, return_float64=False, return_float32=False,
return_raw=False, va_list_index: int = 0xffff) -> typing.Union[float, Symbol, Any]:
""" call a remote function and retrieve its return value as Symbol object """
args = []
Expand Down Expand Up @@ -245,7 +245,7 @@ def listdir(self, filename: str):
stat=stat))
return entries

def spawn(self, argv: typing.List[str] = None, envp: typing.List[str] = None, stdin: io_or_str = sys.stdin,
def spawn(self, argv: list[str] = None, envp: list[str] = None, stdin: io_or_str = sys.stdin,
stdout=sys.stdout, raw_tty=False, background=False) -> SpawnResult:
"""
spawn a new process and forward its stdin, stdout & stderr
Expand Down Expand Up @@ -317,7 +317,7 @@ def last_error(self):
return f'[{self.errno}] {err_str}'

@property
def environ(self) -> typing.List[str]:
def environ(self) -> list[str]:
result = []
environ = self.symbols.environ[0]
i = 0
Expand Down Expand Up @@ -363,7 +363,7 @@ def freeing(self, symbol):
if symbol:
self.symbols.free(symbol)

def interactive(self, additional_namespace: typing.Mapping = None):
def interactive(self, additional_namespace: Optional[dict] = None):
""" Start an interactive shell """
sys.argv = ['a']
c = Config()
Expand Down Expand Up @@ -451,7 +451,7 @@ def reconnect(self):
# new clients are handled in new processes so all symbols may reside in different addresses
self._init_process_specific()

def _execute(self, argv: typing.List[str], envp: typing.List[str], background=False) -> int:
def _execute(self, argv: list[str], envp: list[str], background=False) -> int:
command = CmdExec(background=background, argv=argv, envp=envp)
try:
return self._sock.send_recv(command).pid
Expand Down
8 changes: 4 additions & 4 deletions src/rpcclient/rpcclient/darwin/cfpreferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, client):
self._client = client

def get_keys(self, application_id: str, username: str = kCFPreferencesCurrentUser,
hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[typing.List[str]]:
hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[list[str]]:
""" wrapper for CFPreferencesCopyKeyList """
application_id = self._client.cf(application_id)
username = self._client.cf(username)
Expand All @@ -43,7 +43,7 @@ def get_value(self, key: str, application_id: str, username: str = kCFPreference
return self._client.symbols.CFPreferencesCopyValue(key, application_id, username, hostname).py()

def get_dict(self, application_id: str, username: str = kCFPreferencesCurrentUser,
hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[typing.Mapping]:
hostname: str = kCFPreferencesCurrentHost) -> typing.Optional[dict]:
""" get a dictionary representation of given preference """
result = {}
key_list = self.get_keys(application_id, username, hostname)
Expand All @@ -67,14 +67,14 @@ def remove(self, key: str, application_id: str, username: str = kCFPreferencesCu
self._client.cf(application_id), self._client.cf(username),
self._client.cf(hostname))

def set_dict(self, d: typing.Mapping, application_id: str, username: str = kCFPreferencesCurrentUser,
def set_dict(self, d: dict, application_id: str, username: str = kCFPreferencesCurrentUser,
hostname: str = kCFPreferencesCurrentHost):
""" set entire preference dictionary (erase first if exists) """
with suppress(NoSuchPreferenceError):
self.clear(application_id, username, hostname)
self.update_dict(d, application_id, username, hostname)

def update_dict(self, d: typing.Mapping, application_id: str, username: str = kCFPreferencesCurrentUser,
def update_dict(self, d: dict, application_id: str, username: str = kCFPreferencesCurrentUser,
hostname: str = kCFPreferencesCurrentHost):
""" update preference dictionary """
for k, v in d.items():
Expand Down
15 changes: 7 additions & 8 deletions src/rpcclient/rpcclient/darwin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from collections import namedtuple
from dataclasses import dataclass
from functools import lru_cache
from typing import Mapping

from cached_property import cached_property
from tqdm import tqdm
Expand Down Expand Up @@ -75,7 +74,7 @@ def __init__(self, sock, sysname: str, arch, create_socket_cb: typing.Callable):
super().__init__(sock, sysname, arch, create_socket_cb, dlsym_global_handle=RTLD_GLOBAL)

def _init_process_specific(self):
super(DarwinClient, self)._init_process_specific()
super()._init_process_specific()

if 0 == self.dlopen('/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation', RTLD_NOW):
raise MissingLibraryError('failed to load CoreFoundation')
Expand All @@ -100,7 +99,7 @@ def _init_process_specific(self):
self._NSPropertyListSerialization = self.symbols.objc_getClass('NSPropertyListSerialization')
self._CFNullTypeID = self.symbols.CFNullGetTypeID()

def interactive(self, additional_namespace: typing.Mapping = None):
def interactive(self, additional_namespace: typing.Optional[dict] = None):
if additional_namespace is None:
additional_namespace = {}
additional_namespace['CFSTR'] = self.cf
Expand All @@ -119,7 +118,7 @@ def errno(self, value: int) -> None:
p_error[0] = value

@property
def images(self) -> typing.List[DyldImage]:
def images(self) -> list[DyldImage]:
m = []
for i in range(self.symbols._dyld_image_count()):
module_name = self.symbols._dyld_get_image_name(i).peek_str()
Expand All @@ -140,19 +139,19 @@ def is_idevice(self):
return self.uname.machine.startswith('i')

@property
def roots(self) -> typing.List[str]:
def roots(self) -> list[str]:
""" get a list of all accessible darwin roots when used for lookup of files/preferences/... """
return ['/', '/var/root']

def showobject(self, object_address: Symbol) -> Mapping:
def showobject(self, object_address: Symbol) -> dict:
response = self._sock.send_recv(CmdShowObject(address=object_address))
return json.loads(response.description)

def showclass(self, class_address: Symbol) -> Mapping:
def showclass(self, class_address: Symbol) -> dict:
response = self._sock.send_recv(CmdShowClass(address=class_address))
return json.loads(response.description)

def get_class_list(self) -> typing.Mapping[str, objective_c_class.Class]:
def get_class_list(self) -> dict[str, objective_c_class.Class]:
result = {}
command = CmdGetClassList()
response = self._sock.send_recv(command)
Expand Down
4 changes: 2 additions & 2 deletions src/rpcclient/rpcclient/darwin/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, List, Mapping, Tuple, Union
from typing import Any, Union

CfSerializable = Union[
Mapping[str, Any], List, Tuple[Any, ...], str, bool, float, bytes, datetime, None]
tuple[str, Any], list, tuple[Any, ...], str, bool, float, bytes, datetime, None]
3 changes: 1 addition & 2 deletions src/rpcclient/rpcclient/darwin/crash_reports.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from pathlib import Path
from typing import List

from pycrashreport.crash_report import CrashReportBase, get_crash_report_from_buf

Expand All @@ -21,7 +20,7 @@ def set_symbolicated(self, enabled: bool = True):
# bugfix: at some point, this setting was moved to "com.apple.osanalytics" bundle identifier
self._client.preferences.cf.set('SymbolicateCrashes', enabled, 'com.apple.osanalytics', 'root')

def list(self, prefixed='') -> List[CrashReportBase]:
def list(self, prefixed='') -> list[CrashReportBase]:
""" get a list of all crash reports as CrashReport parsed objects """
result = []
for root in self._client.roots:
Expand Down
3 changes: 1 addition & 2 deletions src/rpcclient/rpcclient/darwin/darwin_lief.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import plistlib
import struct
from typing import Mapping

import lief
from parameter_decorators import path_to_str
Expand All @@ -12,7 +11,7 @@

class DarwinLief(Lief):
@path_to_str('path')
def get_entitlements(self, path: str) -> Mapping:
def get_entitlements(self, path: str) -> dict:
with self._client.fs.open(path, 'r') as f:
buf = f.read()
parsed = lief.parse(buf)
Expand Down
6 changes: 2 additions & 4 deletions src/rpcclient/rpcclient/darwin/fs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import List, Mapping

from parameter_decorators import path_to_str

from rpcclient.darwin.structs import stat64, statfs64
Expand Down Expand Up @@ -52,7 +50,7 @@ def removexattr(self, path: str, name: str):
self._client.raise_errno_exception(f'failed to removexattr(): {path}')

@path_to_str('path')
def listxattr(self, path: str) -> List[str]:
def listxattr(self, path: str) -> list[str]:
""" list extended attribute names """
max_buf_len = 1024
with self._client.safe_malloc(max_buf_len) as xattributes_names:
Expand All @@ -72,7 +70,7 @@ def getxattr(self, path: str, name: str) -> bytes:
return value.peek(count)

@path_to_str('path')
def dictxattr(self, path: str) -> Mapping[str, bytes]:
def dictxattr(self, path: str) -> dict[str, bytes]:
""" get a dictionary of all extended attributes """
result = {}
for k in self.listxattr(path):
Expand Down
8 changes: 3 additions & 5 deletions src/rpcclient/rpcclient/darwin/ioregistry.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Mapping

from rpcclient.allocated import Allocated
from rpcclient.darwin.consts import MACH_PORT_NULL, kCFAllocatorDefault, kIOServicePlane
from rpcclient.darwin.structs import io_name_t, io_object_t, mach_port_t
Expand All @@ -22,7 +20,7 @@ def name(self) -> str:
return name.peek_str()

@property
def properties(self) -> Mapping:
def properties(self) -> dict:
with self._client.safe_malloc(8) as p_properties:
if self._client.symbols.IORegistryEntryCreateCFProperties(self._service, p_properties,
kCFAllocatorDefault, 0):
Expand All @@ -42,7 +40,7 @@ def __iter__(self):
s = IOService(self._client, child)
yield s

def set(self, properties: Mapping):
def set(self, properties: dict):
self._client.symbols.IORegistryEntrySetCFProperties(self._service, self._client.cf(properties))

def get(self, key: str):
Expand All @@ -58,7 +56,7 @@ def __repr__(self):

class BacklightControlService(IOService):
@property
def display_parameters(self) -> Mapping:
def display_parameters(self) -> dict:
return self.get('IODisplayParameters')

@property
Expand Down
15 changes: 7 additions & 8 deletions src/rpcclient/rpcclient/darwin/keychain.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
from typing import List, Mapping

from rpcclient.exceptions import BadReturnValueError, RpcPermissionError
from rpcclient.symbol import Symbol
Expand All @@ -24,25 +23,25 @@ def add_internet_password(self, account: str, server: str, password: str):
if err != 0:
raise BadReturnValueError(f'SecItemAdd() returned: {err}')

def query_apple_share_passwords(self) -> List[Mapping]:
def query_apple_share_passwords(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassAppleSharePassword)

def query_internet_passwords(self) -> List[Mapping]:
def query_internet_passwords(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassInternetPassword)

def query_generic_passwords(self) -> List[Mapping]:
def query_generic_passwords(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassGenericPassword)

def query_identities(self) -> List[Mapping]:
def query_identities(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassIdentity)

def query_certificates(self) -> List[Mapping]:
def query_certificates(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassCertificate)

def query_keys(self) -> List[Mapping]:
def query_keys(self) -> list[dict]:
return self._query(self._client.symbols.kSecClassKey)

def _query(self, class_type: Symbol) -> List[Mapping]:
def _query(self, class_type: Symbol) -> list[dict]:
with self._client.safe_malloc(8) as p_result:
p_result[0] = 0

Expand Down
4 changes: 2 additions & 2 deletions src/rpcclient/rpcclient/darwin/location.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from enum import Enum
from typing import Mapping, Optional
from typing import Optional

from rpcclient.exceptions import MissingLibraryError, RpcPermissionError
from rpcclient.structs.consts import RTLD_NOW
Expand Down Expand Up @@ -61,7 +61,7 @@ def authorization_status(self) -> CLAuthorizationStatus:
return CLAuthorizationStatus.from_value(self._location_manager.objc_call('authorizationStatus'))

@property
def last_sample(self) -> Optional[Mapping]:
def last_sample(self) -> Optional[dict]:
""" last taken location sample (or None if there isn't any) """
location = self._location_manager.objc_call('location')
if not location:
Expand Down
3 changes: 1 addition & 2 deletions src/rpcclient/rpcclient/darwin/media.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import struct
from enum import Enum
from typing import List

from parameter_decorators import path_to_str

Expand Down Expand Up @@ -158,7 +157,7 @@ def record_permission(self):
return struct.pack('<I', self._session.objc_call('recordPermission'))[::-1].decode()

@property
def available_categories(self) -> List[str]:
def available_categories(self) -> list[str]:
return self._session.objc_call('availableCategories').py()


Expand Down
3 changes: 1 addition & 2 deletions src/rpcclient/rpcclient/darwin/network.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import sqlite3
from typing import Mapping

from rpcclient.network import Network
from rpcclient.structs.consts import SIGKILL
Expand All @@ -15,7 +14,7 @@ def __init__(self, client):
super().__init__(client)

@property
def proxy_settings(self) -> Mapping:
def proxy_settings(self) -> dict:
return self._client.symbols.CFNetworkCopySystemProxySettings().py()

def set_http_proxy(self, ip: str, port: int) -> None:
Expand Down
3 changes: 1 addition & 2 deletions src/rpcclient/rpcclient/darwin/objc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from collections import namedtuple
from dataclasses import dataclass, field
from typing import Mapping

from objc_types_decoder.decode import decode as decode_type
from objc_types_decoder.decode import decode_with_tail
Expand Down Expand Up @@ -49,7 +48,7 @@ class Method:
args_types: list = field(compare=False)

@staticmethod
def from_data(data: Mapping, client):
def from_data(data: dict, client):
"""
Create Method object from raw data.
:param data: Data as loaded from get_objectivec_symbol_data.m.
Expand Down
Loading

0 comments on commit f6fae38

Please sign in to comment.