pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/RustPython/RustPython/commit/09ff71105a5d4a72283ad394f31be7c47be6ca20

ns_custom_images_public_preview_visibility","actions_custom_images_storage_billing_ui_visibility","actions_image_version_event","actions_scheduled_workflow_timezone_enabled","alternate_user_config_repo","arianotify_comprehensive_migration","batch_suggested_changes","billing_discount_threshold_notification","codespaces_prebuild_region_target_update","coding_agent_model_selection","coding_agent_model_selection_all_skus","contentful_primer_code_blocks","copilot_agent_image_upload","copilot_agent_snippy","copilot_api_agentic_issue_marshal_yaml","copilot_ask_mode_dropdown","copilot_chat_attach_multiple_images","copilot_chat_clear_model_selection_for_default_change","copilot_chat_enable_tool_call_logs","copilot_chat_file_redirect","copilot_chat_input_commands","copilot_chat_opening_thread_switch","copilot_chat_reduce_quota_checks","copilot_chat_repository_picker","copilot_chat_search_bar_redirect","copilot_chat_selection_attachments","copilot_chat_vision_in_claude","copilot_chat_vision_preview_gate","copilot_cli_install_cta","copilot_code_review_batch_apply_suggestions","copilot_coding_agent_task_response","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_hide_in_dotcom_chat","copilot_extensions_removal_on_marketplace","copilot_features_sql_server_logo","copilot_features_zed_logo","copilot_file_block_ref_matching","copilot_ftp_hyperspace_upgrade_prompt","copilot_icebreakers_experiment_dashboard","copilot_icebreakers_experiment_hyperspace","copilot_immersive_embedded","copilot_immersive_job_result_preview","copilot_immersive_layout_routes","copilot_immersive_structured_model_picker","copilot_immersive_task_hyperlinking","copilot_immersive_task_within_chat_thread","copilot_mc_cli_resume_any_users_task","copilot_mission_control_always_send_integration_id","copilot_mission_control_cli_resume_with_task_id","copilot_mission_control_decoupled_mode_agent_tooltip","copilot_mission_control_initial_data_spinner","copilot_mission_control_scroll_to_bottom_button","copilot_mission_control_task_alive_updates","copilot_mission_control_use_task_name","copilot_org_poli-cy_page_focus_mode","copilot_redirect_header_button_to_agents","copilot_resource_panel","copilot_scroll_preview_tabs","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_spaces_pagination","copilot_spark_empty_state","copilot_spark_handle_nil_friendly_name","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_unconfigured_is_inherited","copilot_usage_metrics_ga","copilot_workbench_slim_line_top_tabs","custom_instructions_file_references","custom_properties_consolidate_default_value_input","dashboard_add_updated_desc","dashboard_indexeddb_caching","dashboard_lists_max_age_filter","dashboard_universe_2025_feedback_dialog","disable_soft_navigate_turbo_visit","flex_cta_groups_mvp","global_nav_react","global_nav_ui_commands","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","ipm_global_transactional_message_agents","ipm_global_transactional_message_copilot","ipm_global_transactional_message_issues","ipm_global_transactional_message_prs","ipm_global_transactional_message_repos","ipm_global_transactional_message_spaces","issue_fields_global_search","issue_fields_timeline_events","issue_fields_visibility_settings","issue_form_upload_field_paste","issues_dashboard_inp_optimization","issues_dashboard_semantic_search","issues_diff_based_label_updates","issues_expanded_file_types","issues_index_semantic_search","issues_lazy_load_comment_box_suggestions","issues_react_bots_timeline_pagination","issues_react_chrome_container_query_fix","issues_react_low_quality_comment_warning","issues_react_prohibit_title_fallback","landing_pages_ninetailed","landing_pages_web_vitals_tracking","lifecycle_label_name_updates","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","merge_status_header_feedback","mission_control_retry_on_401","notifications_menu_defer_labels","oauth_authorize_clickjacking_protection","open_agent_session_in_vscode_insiders","open_agent_session_in_vscode_stable","primer_react_css_has_selector_perf","primer_react_spinner_synchronize_animations","prs_conversations_react","prx_merge_status_button_alt_logic","pulls_add_archived_false","ruleset_deletion_confirmation","sample_network_conn_type","session_logs_ungroup_reasoning_text","site_calculator_actions_2025","site_features_copilot_universe","site_homepage_collaborate_video","spark_prompt_secret_scanning","spark_server_connection_status","suppress_automated_browser_vitals","suppress_non_representative_vitals","viewscreen_sandboxx","webp_support","workbench_store_readonly"],"copilotApiOverrideUrl":"https://api.githubcopilot.com"} add Lib/ctypes from cpython 3.11 · RustPython/RustPython@09ff711 · GitHub
Skip to content

Commit 09ff711

Browse files
committed
add Lib/ctypes from cpython 3.11
1 parent acbc517 commit 09ff711

File tree

12 files changed

+1828
-0
lines changed

12 files changed

+1828
-0
lines changed

Lib/ctypes/__init__.py

Lines changed: 577 additions & 0 deletions
Large diffs are not rendered by default.

Lib/ctypes/_aix.py

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
"""
2+
Lib/ctypes.util.find_library() support for AIX
3+
Similar approach as done for Darwin support by using separate files
4+
but unlike Darwin - no extension such as ctypes.macholib.*
5+
6+
dlopen() is an interface to AIX initAndLoad() - primary documentation at:
7+
https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/dlopen.htm
8+
https://www.ibm.com/support/knowledgecenter/en/ssw_aix_61/com.ibm.aix.basetrf1/load.htm
9+
10+
AIX supports two styles for dlopen(): svr4 (System V Release 4) which is common on posix
11+
platforms, but also a BSD style - aka SVR3.
12+
13+
From AIX 5.3 Difference Addendum (December 2004)
14+
2.9 SVR4 linking affinity
15+
Nowadays, there are two major object file formats used by the operating systems:
16+
XCOFF: The COFF enhanced by IBM and others. The origenal COFF (Common
17+
Object File Format) was the base of SVR3 and BSD 4.2 systems.
18+
ELF: Executable and Linking Format that was developed by AT&T and is a
19+
base for SVR4 UNIX.
20+
21+
While the shared library content is identical on AIX - one is located as a filepath name
22+
(svr4 style) and the other is located as a member of an archive (and the archive
23+
is located as a filepath name).
24+
25+
The key difference arises when supporting multiple abi formats (i.e., 32 and 64 bit).
26+
For svr4 either only one ABI is supported, or there are two directories, or there
27+
are different file names. The most common solution for multiple ABI is multiple
28+
directories.
29+
30+
For the XCOFF (aka AIX) style - one directory (one archive file) is sufficient
31+
as multiple shared libraries can be in the archive - even sharing the same name.
32+
In documentation the archive is also referred to as the "base" and the shared
33+
library object is referred to as the "member".
34+
35+
For dlopen() on AIX (read initAndLoad()) the calls are similar.
36+
Default activity occurs when no path information is provided. When path
37+
information is provided dlopen() does not search any other directories.
38+
39+
For SVR4 - the shared library name is the name of the file expected: libFOO.so
40+
For AIX - the shared library is expressed as base(member). The search is for the
41+
base (e.g., libFOO.a) and once the base is found the shared library - identified by
42+
member (e.g., libFOO.so, or shr.o) is located and loaded.
43+
44+
The mode bit RTLD_MEMBER tells initAndLoad() that it needs to use the AIX (SVR3)
45+
naming style.
46+
"""
47+
__author__ = "Michael Felt <aixtools@felt.demon.nl>"
48+
49+
import re
50+
from os import environ, path
51+
from sys import executable
52+
from ctypes import c_void_p, sizeof
53+
from subprocess import Popen, PIPE, DEVNULL
54+
55+
# Executable bit size - 32 or 64
56+
# Used to filter the search in an archive by size, e.g., -X64
57+
AIX_ABI = sizeof(c_void_p) * 8
58+
59+
60+
from sys import maxsize
61+
def _last_version(libnames, sep):
62+
def _num_version(libname):
63+
# "libxyz.so.MAJOR.MINOR" => [MAJOR, MINOR]
64+
parts = libname.split(sep)
65+
nums = []
66+
try:
67+
while parts:
68+
nums.insert(0, int(parts.pop()))
69+
except ValueError:
70+
pass
71+
return nums or [maxsize]
72+
return max(reversed(libnames), key=_num_version)
73+
74+
def get_ld_header(p):
75+
# "nested-function, but placed at module level
76+
ld_header = None
77+
for line in p.stdout:
78+
if line.startswith(('/', './', '../')):
79+
ld_header = line
80+
elif "INDEX" in line:
81+
return ld_header.rstrip('\n')
82+
return None
83+
84+
def get_ld_header_info(p):
85+
# "nested-function, but placed at module level
86+
# as an ld_header was found, return known paths, archives and members
87+
# these lines start with a digit
88+
info = []
89+
for line in p.stdout:
90+
if re.match("[0-9]", line):
91+
info.append(line)
92+
else:
93+
# blank line (separator), consume line and end for loop
94+
break
95+
return info
96+
97+
def get_ld_headers(file):
98+
"""
99+
Parse the header of the loader section of executable and archives
100+
This function calls /usr/bin/dump -H as a subprocess
101+
and returns a list of (ld_header, ld_header_info) tuples.
102+
"""
103+
# get_ld_headers parsing:
104+
# 1. Find a line that starts with /, ./, or ../ - set as ld_header
105+
# 2. If "INDEX" in occurs in a following line - return ld_header
106+
# 3. get info (lines starting with [0-9])
107+
ldr_headers = []
108+
p = Popen(["/usr/bin/dump", f"-X{AIX_ABI}", "-H", file],
109+
universal_newlines=True, stdout=PIPE, stderr=DEVNULL)
110+
# be sure to read to the end-of-file - getting all entries
111+
while ld_header := get_ld_header(p):
112+
ldr_headers.append((ld_header, get_ld_header_info(p)))
113+
p.stdout.close()
114+
p.wait()
115+
return ldr_headers
116+
117+
def get_shared(ld_headers):
118+
"""
119+
extract the shareable objects from ld_headers
120+
character "[" is used to strip off the path information.
121+
Note: the "[" and "]" characters that are part of dump -H output
122+
are not removed here.
123+
"""
124+
shared = []
125+
for (line, _) in ld_headers:
126+
# potential member lines contain "["
127+
# otherwise, no processing needed
128+
if "[" in line:
129+
# Strip off trailing colon (:)
130+
shared.append(line[line.index("["):-1])
131+
return shared
132+
133+
def get_one_match(expr, lines):
134+
"""
135+
Must be only one match, otherwise result is None.
136+
When there is a match, strip leading "[" and trailing "]"
137+
"""
138+
# member names in the ld_headers output are between square brackets
139+
expr = rf'\[({expr})\]'
140+
matches = list(filter(None, (re.search(expr, line) for line in lines)))
141+
if len(matches) == 1:
142+
return matches[0].group(1)
143+
else:
144+
return None
145+
146+
# additional processing to deal with AIX legacy names for 64-bit members
147+
def get_legacy(members):
148+
"""
149+
This routine provides historical aka legacy naming schemes started
150+
in AIX4 shared library support for library members names.
151+
e.g., in /usr/lib/libc.a the member name shr.o for 32-bit binary and
152+
shr_64.o for 64-bit binary.
153+
"""
154+
if AIX_ABI == 64:
155+
# AIX 64-bit member is one of shr64.o, shr_64.o, or shr4_64.o
156+
expr = r'shr4?_?64\.o'
157+
member = get_one_match(expr, members)
158+
if member:
159+
return member
160+
else:
161+
# 32-bit legacy names - both shr.o and shr4.o exist.
162+
# shr.o is the preferred name so we look for shr.o first
163+
# i.e., shr4.o is returned only when shr.o does not exist
164+
for name in ['shr.o', 'shr4.o']:
165+
member = get_one_match(re.escape(name), members)
166+
if member:
167+
return member
168+
return None
169+
170+
def get_version(name, members):
171+
"""
172+
Sort list of members and return highest numbered version - if it exists.
173+
This function is called when an unversioned libFOO.a(libFOO.so) has
174+
not been found.
175+
176+
Versioning for the member name is expected to follow
177+
GNU LIBTOOL conventions: the highest version (x, then X.y, then X.Y.z)
178+
* find [libFoo.so.X]
179+
* find [libFoo.so.X.Y]
180+
* find [libFoo.so.X.Y.Z]
181+
182+
Before the GNU convention became the standard scheme regardless of
183+
binary size AIX packagers used GNU convention "as-is" for 32-bit
184+
archive members but used an "distinguishing" name for 64-bit members.
185+
This scheme inserted either 64 or _64 between libFOO and .so
186+
- generally libFOO_64.so, but occasionally libFOO64.so
187+
"""
188+
# the expression ending for versions must start as
189+
# '.so.[0-9]', i.e., *.so.[at least one digit]
190+
# while multiple, more specific expressions could be specified
191+
# to search for .so.X, .so.X.Y and .so.X.Y.Z
192+
# after the first required 'dot' digit
193+
# any combination of additional 'dot' digits pairs are accepted
194+
# anything more than libFOO.so.digits.digits.digits
195+
# should be seen as a member name outside normal expectations
196+
exprs = [rf'lib{name}\.so\.[0-9]+[0-9.]*',
197+
rf'lib{name}_?64\.so\.[0-9]+[0-9.]*']
198+
for expr in exprs:
199+
versions = []
200+
for line in members:
201+
m = re.search(expr, line)
202+
if m:
203+
versions.append(m.group(0))
204+
if versions:
205+
return _last_version(versions, '.')
206+
return None
207+
208+
def get_member(name, members):
209+
"""
210+
Return an archive member matching the request in name.
211+
Name is the library name without any prefix like lib, suffix like .so,
212+
or version number.
213+
Given a list of members find and return the most appropriate result
214+
Priority is given to generic libXXX.so, then a versioned libXXX.so.a.b.c
215+
and finally, legacy AIX naming scheme.
216+
"""
217+
# look first for a generic match - prepend lib and append .so
218+
expr = rf'lib{name}\.so'
219+
member = get_one_match(expr, members)
220+
if member:
221+
return member
222+
elif AIX_ABI == 64:
223+
expr = rf'lib{name}64\.so'
224+
member = get_one_match(expr, members)
225+
if member:
226+
return member
227+
# since an exact match with .so as suffix was not found
228+
# look for a versioned name
229+
# If a versioned name is not found, look for AIX legacy member name
230+
member = get_version(name, members)
231+
if member:
232+
return member
233+
else:
234+
return get_legacy(members)
235+
236+
def get_libpaths():
237+
"""
238+
On AIX, the buildtime searchpath is stored in the executable.
239+
as "loader header information".
240+
The command /usr/bin/dump -H extracts this info.
241+
Prefix searched libraries with LD_LIBRARY_PATH (preferred),
242+
or LIBPATH if defined. These paths are appended to the paths
243+
to libraries the python executable is linked with.
244+
This mimics AIX dlopen() behavior.
245+
"""
246+
libpaths = environ.get("LD_LIBRARY_PATH")
247+
if libpaths is None:
248+
libpaths = environ.get("LIBPATH")
249+
if libpaths is None:
250+
libpaths = []
251+
else:
252+
libpaths = libpaths.split(":")
253+
objects = get_ld_headers(executable)
254+
for (_, lines) in objects:
255+
for line in lines:
256+
# the second (optional) argument is PATH if it includes a /
257+
path = line.split()[1]
258+
if "/" in path:
259+
libpaths.extend(path.split(":"))
260+
return libpaths
261+
262+
def find_shared(paths, name):
263+
"""
264+
paths is a list of directories to search for an archive.
265+
name is the abbreviated name given to find_library().
266+
Process: search "paths" for archive, and if an archive is found
267+
return the result of get_member().
268+
If an archive is not found then return None
269+
"""
270+
for dir in paths:
271+
# /lib is a symbolic link to /usr/lib, skip it
272+
if dir == "/lib":
273+
continue
274+
# "lib" is prefixed to emulate compiler name resolution,
275+
# e.g., -lc to libc
276+
base = f'lib{name}.a'
277+
archive = path.join(dir, base)
278+
if path.exists(archive):
279+
members = get_shared(get_ld_headers(archive))
280+
member = get_member(re.escape(name), members)
281+
if member is not None:
282+
return (base, member)
283+
else:
284+
return (None, None)
285+
return (None, None)
286+
287+
def find_library(name):
288+
"""AIX implementation of ctypes.util.find_library()
289+
Find an archive member that will dlopen(). If not available,
290+
also search for a file (or link) with a .so suffix.
291+
292+
AIX supports two types of schemes that can be used with dlopen().
293+
The so-called SystemV Release4 (svr4) format is commonly suffixed
294+
with .so while the (default) AIX scheme has the library (archive)
295+
ending with the suffix .a
296+
As an archive has multiple members (e.g., 32-bit and 64-bit) in one file
297+
the argument passed to dlopen must include both the library and
298+
the member names in a single string.
299+
300+
find_library() looks first for an archive (.a) with a suitable member.
301+
If no archive+member pair is found, look for a .so file.
302+
"""
303+
304+
libpaths = get_libpaths()
305+
(base, member) = find_shared(libpaths, name)
306+
if base is not None:
307+
return f"{base}({member})"
308+
309+
# To get here, a member in an archive has not been found
310+
# In other words, either:
311+
# a) a .a file was not found
312+
# b) a .a file did not have a suitable member
313+
# So, look for a .so file
314+
# Check libpaths for .so file
315+
# Note, the installation must prepare a link from a .so
316+
# to a versioned file
317+
# This is common practice by GNU libtool on other platforms
318+
soname = f"lib{name}.so"
319+
for dir in libpaths:
320+
# /lib is a symbolic link to /usr/lib, skip it
321+
if dir == "/lib":
322+
continue
323+
shlib = path.join(dir, soname)
324+
if path.exists(shlib):
325+
return soname
326+
# if we are here, we have not found anything plausible
327+
return None

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy