Coverage for pygeodesy/interns.py: 97%
444 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-08-23 12:10 -0400
« prev ^ index » next coverage.py v7.2.2, created at 2023-08-23 12:10 -0400
1# -*- coding: utf-8 -*-
3u'''Single C{str}ing constants, C{intern}'ed across C{pygeodesy}
4modules and function L{pygeodesy.machine}.
5'''
6import sys as _sys
8_COMMASPACE_ = ', ' # overriden below
9_pl2List = [] # cached _platform2 lists
10_Py3List = [] # cached _pythonarchine lists
13class _Dash(str):
14 '''(INTERNAL) Extended C{str} for prefix_DASH_.
15 '''
16 def __call__(self, *args):
17 '''Join C{self} plus all B{C{args}} like C{'-'.join((self,) + B{args})}.
18 '''
19 return _DASH_(self, *args) # re-callable
22class _Int(int):
23 '''(INTERNAL) Unique C{int}.
24 '''
25 pass
28class Str_(str):
29 '''Extended, I{callable} C{str} class, not nameable.
31 @see: Nameable and callable class L{pygeodesy.Str}.
32 '''
33 def join_(self, *args):
34 '''Join all positional B{C{args}} like C{self.join(B{args})}.
36 @return: All B{C{args}} joined by this instance (L{Str_}).
38 @note: An other L{Str_} instance is returned to make the
39 result re-callable.
40 '''
41 return Str_(str.join(self, map(str, args))) # re-callable
43 __call__ = join_
45NN = Str_('') # PYCHOK Nomen Nescio <https://Wiktionary.org/wiki/N.N.>
48class _Prefix(Str_):
49 '''(INTERNAL) Extended C{str} for prefix.
50 '''
51 def __call__(self, *args):
52 '''Join C{self} plus all B{C{args}} like C{" ".join((self,) + B{args})}.
53 '''
54 return _SPACE_.join_(self, *args) # re-callable
57class _PyPy__(str): # overwritten by singleton below
58 '''(INTERNAL) Extended C{str} for C{"PyPy"} and version.
59 '''
60 def __call__(self, version=NN):
61 '''Return C{"PyPy <version>"} or C{NN}.
62 '''
63 v = version or _sys.version
64 if _PyPy__ in v:
65 v = v.split(_PyPy__)[1].split(None, 1)[0]
66 return NN(_PyPy__, v)
67 else:
68 return NN
71class _Python_(str): # overwritten by singleton below
72 '''(INTERNAL) Extended C{str} for C{"Python"} and version.
73 '''
74 def __call__(self, version=NN):
75 '''Return C{"Python <version>"}.
76 '''
77 v = version or _sys.version
78 return _SPACE_(self, v.split(None, 1)[0])
81class _Range(str):
82 '''(INTERNAL) Extended C{str} for C{range} strings.
83 '''
84 def __call__(self, lo, hi, lopen=False, ropen=False,
85 prec=0, sep=_COMMASPACE_):
86 '''Return the range as C{"(lo, hi)"}, C{"(lo, hi]"},
87 C{"[lo, hi)"} or C{"[lo, hi]"}.
88 '''
89 from pygeodesy.streprs import Fmt
90 r = NN(Fmt.f(lo, prec=prec), sep,
91 Fmt.f(hi, prec=prec))
92 f = (Fmt.PAREN if ropen else Fmt.LOPEN) if lopen else \
93 (Fmt.ROPEN if ropen else Fmt.SQUARE)
94 return f(r)
97class _Slicer(str):
98 '''(INTERNAL) String slicer C{.fromX} or C{.tillY}.
99 '''
100 def __getattr__(self, name): # .fromX, .tillY
101 if name.startswith(_till_):
102 i = self.find(name[len(_till_):])
103 if 0 < i < len(self):
104 return _Slicer(self[:i + 1])
105 elif name.startswith(_from_):
106 i = self.find(name[len(_from_):])
107 if 0 < (i + 1) < len(self):
108 return _Slicer(self[i:])
109 else: # PYCHOK no cover
110 return getattr(str, name)
111 return self
114class MISSING(object):
115 '''(INTERNAL) Singleton C{str}.
116 '''
117 def toRepr(self, **unused):
118 return self.__class__.__name__
120 __repr__ = __str__ = toStr = toRepr
122MISSING = MISSING() # PYCHOK singleton
123MISSING.__name__ = str(MISSING)
125# __DUNDER__-style names would get mangled in classes
126_0_ = '0' # PYCHOK 'zero'
127_0to9_ = '0123456789' # PYCHOK OK
128_1_ = '1' # PYCHOK OK
129_2_ = '2' # PYCHOK OK
130_3_ = '3' # PYCHOK OK
131_4_ = '4' # PYCHOK OK
132_a_ = 'a' # PYCHOK OK
133_A_ = 'A' # PYCHOK OK
134_a12_ = 'a12' # PYCHOK OK
135_area_ = 'area' # PYCHOK OK
136_Airy1830_ = 'Airy1830' # PYCHOK OK
137_AiryModified_ = 'AiryModified' # PYCHOK OK
138_ambiguous_ = 'ambiguous' # PYCHOK OK
139_AMPERSAND_ = Str_('&') # PYCHOK OK
140_an_ = 'an' # PYCHOK OK
141_and_ = 'and' # PYCHOK OK
142# _AND_ = _AMPERSAND_ # PYCHOK OK
143_angle_ = 'angle' # PYCHOK OK
144_antipodal_ = 'antipodal' # PYCHOK OK
145_areaOf_ = 'areaOf' # PYCHOK OK
146_arg_ = 'arg' # PYCHOK OK
147_at_ = 'at' # PYCHOK OK
148_AT_ = Str_('@') # PYCHOK OK
149_AtoZnoIO_ = _Slicer('ABCDEFGHJKLMNPQRSTUVWXYZ') # PYCHOK in C{gars}, C{mgrs} and C{wgrs}
150_attribute_ = 'attribute' # PYCHOK OK
151_azi1_ = 'azi1' # PYCHOK OK
152_azi12_ = 'azi12' # PYCHOK OK
153_azi2_ = 'azi2' # PYCHOK OK
154_azimuth_ = 'azimuth' # PYCHOK OK
155_b_ = 'b' # PYCHOK OK
156_B_ = 'B' # PYCHOK OK
157_BACKSLASH_ = Str_('\\') # PYCHOK OK
158_band_ = 'band' # PYCHOK OK
159_BANG_ = Str_('!') # PYCHOK OK
160_BAR_ = Str_('|') # PYCHOK OK
161_bearing_ = 'bearing' # PYCHOK OK
162_Bessel1841_ = 'Bessel1841' # PYCHOK OK
163_beta_ = 'beta' # PYCHOK OK
164_by_ = 'by' # PYCHOK OK
165_c_ = 'c' # PYCHOK OK
166_C_ = 'C' # PYCHOK OK
167_cartesian_ = 'cartesian' # PYCHOK OK
168_center_ = 'center' # PYCHOK OK
169# _CIRCUMFLEX_ = '^' # PYCHOK OK
170_Clarke1866_ = 'Clarke1866' # PYCHOK OK
171_Clarke1880IGN_ = 'Clarke1880IGN' # PYCHOK OK
172_clip_ = 'clip' # PYCHOK OK
173_clipid_ = 'clipid' # PYCHOK OK
174_coincident_ = 'coincident' # PYCHOK OK
175_colinear_ = 'colinear' # PYCHOK OK
176_COLON_ = Str_(':') # PYCHOK OK
177_COLONSPACE_ = Str_(': ') # PYCHOK OK
178_COMMA_ = Str_(',') # PYCHOK OK
179_COMMASPACE_ = Str_(_COMMASPACE_) # PYCHOK OK
180_composite_ = 'composite' # PYCHOK OK
181_concentric_ = 'concentric' # PYCHOK OK
182_convergence_ = _Prefix('convergence') # PYCHOK OK
183_conversion_ = 'conversion' # PYCHOK OK
184_convex_ = 'convex' # PYCHOK OK
185_cubic_ = 'cubic' # PYCHOK OK
186_d_ = 'd' # PYCHOK OK
187_D_ = 'D' # PYCHOK OK
188_DASH_ = Str_('-') # PYCHOK == _MINUS_
189_datum_ = 'datum' # PYCHOK OK
190_decode3_ = 'decode3' # PYCHOK OK
191_deg_ = 'deg' # PYCHOK OK
192_degrees_ = 'degrees' # PYCHOK OK
193_degrees2_ = 'degrees2' # PYCHOK SQUARED
194_delta_ = 'delta' # PYCHOK OK
195_DEPRECATED_ = 'DEPRECATED' # PYCHOK OK
196_DEQUALSPACED_ = Str_(' == ') # PYCHOK OK
197_distance_ = 'distance' # PYCHOK OK
198_distant_ = _Prefix('distant') # PYCHOK OK
199_doesn_t_exist_ = "doesn't exist" # PYCHOK OK
200_DOT_ = Str_('.') # PYCHOK OK
201_down_ = 'down' # PYCHOK OK
202_e_ = 'e' # PYCHOK OK
203_E_ = 'E' # PYCHOK OK
204_earth_ = 'earth' # PYCHOK OK
205_east_ = 'east' # PYCHOK OK
206_easting_ = 'easting' # PYCHOK OK
207_ecef_ = 'ecef' # PYCHOK OK
208_edge_ = 'edge' # PYCHOK OK
209_elevation_ = 'elevation' # PYCHOK OK
210_ELLIPSIS_ = Str_('...') # PYCHOK OK
211_ELLIPSIS4_ = Str_('....') # PYCHOK OK
212# _ELLIPSISPACED_ = Str_(' ... ') # PYCHOK <https://www.ThePunctuationGuide.com/ellipses.html>
213_ellipsoid_ = 'ellipsoid' # PYCHOK OK
214_ellipsoidal_ = 'ellipsoidal' # PYCHOK OK
215_enabled_ = 'enabled' # PYCHOK OK
216_encode_ = 'encode' # PYCHOK OK
217_end_ = 'end' # PYCHOK OK
218_epoch_ = 'epoch' # PYCHOK OK
219_eps_ = 'eps' # PYCHOK OK
220_EQUAL_ = Str_('=') # PYCHOK OK
221_EQUALSPACED_ = Str_(' = ') # PYCHOK OK
222_Error_ = 'Error' # PYCHOK OK
223_exceed_PI_radians_ = 'exceed PI radians' # PYCHOK OK
224_exceeds_ = _Prefix('exceeds') # PYCHOK OK
225# _EXCLAMATION_ = _BANG_ # PYCHOK OK
226_exists_ = 'exists' # PYCHOK OK
227_f_ = 'f' # PYCHOK OK
228_F_ = 'F' # PYCHOK OK
229_feet_ = 'feet' # PYCHOK OK
230_few_ = 'few' # PYCHOK OK
231_fi_ = 'fi' # PYCHOK OK
232_finite_ = 'finite' # PYCHOK OK
233_from_ = 'from' # PYCHOK OK
234_g_ = 'g' # PYCHOK OK
235_gamma_ = 'gamma' # PYCHOK OK
236_GRS80_ = 'GRS80' # PYCHOK OK
237_h_ = 'h' # PYCHOK OK
238_H_ = 'H' # PYCHOK OK
239_HASH_ = '#' # PYCHOK OK
240_height_ = 'height' # PYCHOK OK
241_hemipole_ = 'hemipole' # PYCHOK OK
242_i_ = 'i' # PYCHOK OK
243_iadd_op_ = '+=' # PYCHOK OK
244_immutable_ = 'immutable' # PYCHOK OK
245_in_ = 'in' # PYCHOK OK
246_incompatible_ = 'incompatible' # PYCHOK OK
247_INF_ = 'INF' # PYCHOK OK
248_infinite_ = 'infinite' # PYCHOK _not_finite_
249_initial_ = 'initial' # PYCHOK OK
250_inside_ = 'inside' # PYCHOK OK
251_insufficient_ = 'insufficient' # PYCHOK OK
252_intersection_ = 'intersection' # PYCHOK OK
253_Intl1924_ = 'Intl1924' # PYCHOK OK
254_invalid_ = 'invalid' # PYCHOK OK
255_isclockwise_ = 'isclockwise' # PYCHOK OK
256_ispolar_ = 'ispolar' # PYCHOK OK
257_j_ = 'j' # PYCHOK OK
258_k0_ = 'k0' # PYCHOK OK
259_kind_ = 'kind' # PYCHOK OK
260_knots_ = 'knots' # PYCHOK OK
261_Krassovski1940_ = 'Krassovski1940' # PYCHOK OK
262_Krassowsky1940_ = 'Krassowsky1940' # PYCHOK OK
263_LANGLE_ = '<' # PYCHOK OK
264_lam_ = 'lam' # PYCHOK OK
265_lat_ = 'lat' # PYCHOK OK
266_lat0_ = 'lat0' # PYCHOK OK
267_lat1_ = 'lat1' # PYCHOK OK
268_lat2_ = 'lat2' # PYCHOK OK
269_latlon_ = 'latlon' # PYCHOK OK
270_LatLon_ = 'LatLon' # PYCHOK OK
271_LCURLY_ = '{' # PYCHOK LBRACE
272_len_ = 'len' # PYCHOK OK
273_limit_ = 'limit' # PYCHOK OK
274_line_ = 'line' # PYCHOK OK
275_linear_ = 'linear' # PYCHOK OK
276_LPAREN_ = '(' # PYCHOK OK
277_lon_ = 'lon' # PYCHOK OK
278_lon0_ = 'lon0' # PYCHOK OK
279_lon1_ = 'lon1' # PYCHOK OK
280_lon2_ = 'lon2' # PYCHOK OK
281_low_ = 'low' # PYCHOK OK
282_LSQUARE_ = '[' # PYCHOK LBRACK
283_ltp_ = 'ltp' # PYCHOK OK
284_m_ = 'm' # PYCHOK OK
285_M_ = 'M' # PYCHOK OK
286_m12_ = 'm12' # PYCHOK OK
287_M12_ = 'M12' # PYCHOK OK
288_M21_ = 'M21' # PYCHOK OK
289_MANT_DIG_ = 'MANT_DIG' # PYCHOK OK
290_MAX_ = 'MAX' # PYCHOK OK
291_mean_ = 'mean' # PYCHOK OK
292_meanOf_ = 'meanOf' # PYCHOK OK
293_meridional_ = 'meridional' # PYCHOK OK
294_meter_ = 'meter' # PYCHOK OK
295_meter2_ = 'meter2' # PYCHOK SQUARED
296_MGRS_ = 'MGRS' # PYCHOK OK
297_MIN_ = 'MIN' # PYCHOK OK
298_MINUS_ = _DASH_ # PYCHOK OK
299_module_ = 'module' # PYCHOK OK
300_n_ = 'n' # PYCHOK OK
301_N_ = 'N' # PYCHOK OK
302_n_a_ = 'n/a' # PYCHOK OK
303_N_A_ = 'N/A' # PYCHOK OK
304_NAD27_ = 'NAD27' # PYCHOK OK
305_NAD83_ = 'NAD83' # PYCHOK OK
306_name_ = 'name' # PYCHOK OK
307_NAN_ = 'NAN' # PYCHOK OK
308_near_ = _Dash('near') # PYCHOK OK
309_nearestOn2_ = 'nearestOn2' # PYCHOK OK
310_negative_ = 'negative' # PYCHOK OK
311_NL_ = Str_('\n') # PYCHOK OK
312_NLATvar_ = Str_(_NL_ + '@var ') # PYCHOK OK
313_NLHASH_ = Str_(_NL_ + '# ') # PYCHOK OK
314# _NLNL_ = _DNL_ # PYCHOK OK
315_NN_ = 'NN' # PYCHOK OK
316_no_ = _Prefix('no') # PYCHOK OK
317_north_ = 'north' # PYCHOK OK
318_northing_ = 'northing' # PYCHOK OK
319_NorthPole_ = 'NorthPole' # PYCHOK OK
320_not_ = _Prefix('not') # PYCHOK OK
321_NOTEQUAL_ = _BANG_ + _EQUAL_ # PYCHOK OK
322_not_finite_ = 'not finite' # PYCHOK _not_(_finite_), _infinite_
323_not_scalar_ = 'not scalar' # PYCHOK _not_(_scalar_)
324_NTF_ = 'NTF' # PYCHOK OK
325_null_ = 'null' # PYCHOK OK
326_number_ = 'number' # PYCHOK OK
327_numpy_ = 'numpy' # PYCHOK OK
328_Nv00_ = 'Nv00' # PYCHOK OK
329_of_ = 'of' # PYCHOK OK
330_on_ = 'on' # PYCHOK OK
331_opposite_ = 'opposite' # PYCHOK OK
332_or_ = 'or' # PYCHOK OK
333_other_ = 'other' # PYCHOK OK
334_outside_ = 'outside' # PYCHOK OK
335_overlap_ = 'overlap' # PYCHOK OK
336_parallel_ = 'parallel' # PYCHOK OK
337_PERCENT_ = '%' # PYCHOK OK
338_PERCENTDOTSTAR_ = '%.*' # PYCHOK _DOT_(_PERCENT_, _STAR_)
339_phi_ = 'phi' # PYCHOK OK
340_PLUS_ = Str_('+') # PYCHOK OK
341_PLUSMINUS_ = _PLUS_ + _MINUS_ # PYCHOK OK
342_point_ = 'point' # PYCHOK OK
343_points_ = 'points' # PYCHOK OK
344_pole_ = 'pole' # PYCHOK OK
345_precision_ = 'precision' # PYCHOK OK
346_prime_vertical_ = 'prime_vertical' # PYCHOK OK
347_pygeodesy_ = 'pygeodesy' # PYCHOK OK
348_pygeodesy_abspath_ = 'pygeodesy_abspath' # PYCHOK OK
349_PyPy__ = _PyPy__('PyPy ') # PYCHOK + _SPACE_
350_Python_ = _Python_('Python') # PYCHOK singleton
351_python_ = 'python' # PYCHOK OK
352_QUOTE1_ = "'" # PYCHOK OK
353_QUOTE2_ = '"' # PYCHOK OK
354# _QUOTE3_ = "'''" # PYCHOK OK
355# _QUOTE6_ = '"""' # PYCHOK OK
356_R_ = 'R' # PYCHOK OK
357_radians_ = 'radians' # PYCHOK OK
358_radians2_ = 'radians2' # PYCHOK SQUARED
359_radius_ = 'radius' # PYCHOK OK
360_radius1_ = 'radius1' # PYCHOK OK
361_radius2_ = 'radius2' # PYCHOK OK
362_range_ = _Range('range') # PYCHOK OK
363_RANGLE_ = '>' # PYCHOK OK
364_RCURLY_ = '}' # PYCHOK RBRACE
365_reciprocal_ = 'reciprocal' # PYCHOK OK
366_reframe_ = 'reframe' # PYCHOK OK
367_resolution_ = 'resolution' # PYCHOK OK
368_rIn_ = 'rIn' # PYCHOK OK
369_RPAREN_ = ')' # PYCHOK OK
370_RSQUARE_ = ']' # PYCHOK RBRACK
371_s_ = 's' # PYCHOK OK
372_S_ = 'S' # PYCHOK OK
373_s12_ = 's12' # PYCHOK OK
374_S12_ = 'S12' # PYCHOK OK
375_scalar_ = 'scalar' # PYCHOK OK
376_scale_ = 'scale' # PYCHOK OK
377_scale0_ = 'scale0' # PYCHOK OK
378_scipy_ = 'scipy' # PYCHOK OK
379_semi_circular_ = 'semi-circular' # PYCHOK OK
380_sep_ = 'sep' # PYCHOK OK
381_singular_ = 'singular' # PYCHOK OK
382_SLASH_ = Str_('/') # PYCHOK OK
383_small_ = 'small' # PYCHOK OK
384_Sphere_ = 'Sphere' # PYCHOK OK
385_spherical_ = 'spherical' # PYCHOK OK
386_SouthPole_ = 'SouthPole' # PYCHOK OK
387_SPACE_ = Str_(' ') # PYCHOK OK
388_specified_ = 'specified' # PYCHOK OK
389_STAR_ = Str_('*') # PYCHOK OK
390_start_ = 'start' # PYCHOK OK
391_std_ = 'std' # PYCHOK OK
392_stdev_ = 'stdev' # PYCHOK OK
393_supported_ = 'supported' # PYCHOK OK
394_sx_ = 'sx' # PYCHOK OK
395_sy_ = 'sy' # PYCHOK OK
396_sz_ = 'sz' # PYCHOK OK
397_tbd_ = 'tbd' # PYCHOK OK
398_TILDE_ = '~' # PYCHOK OK
399_till_ = 'till' # PYCHOK OK
400_to_ = 'to' # PYCHOK OK
401_tolerance_ = _Prefix('tolerance') # PYCHOK OK
402_too_ = _Prefix('too') # PYCHOK OK
403_transform_ = 'transform' # PYCHOK OK
404_tx_ = 'tx' # PYCHOK OK
405_ty_ = 'ty' # PYCHOK OK
406_tz_ = 'tz' # PYCHOK OK
407_UNDER_ = Str_('_') # PYCHOK OK
408_units_ = 'units' # PYCHOK OK
409_UNUSED_ = 'UNUSED' # PYCHOK OK
410_up_ = 'up' # PYCHOK OK
411_UPS_ = 'UPS' # PYCHOK OK
412_utf_8_ = 'utf-8' # PYCHOK OK
413_UTM_ = 'UTM' # PYCHOK OK
414_V_ = 'V' # PYCHOK OK
415_valid_ = 'valid' # PYCHOK OK
416_value_ = 'value' # PYCHOK OK
417_version_ = 'version' # PYCHOK OK
418_vs_ = 'vs' # PYCHOK OK
419_W_ = 'W' # PYCHOK OK
420_WGS72_ = 'WGS72' # PYCHOK OK
421_WGS84_ = 'WGS84' # PYCHOK OK
422_width_ = 'width' # PYCHOK OK
423_with_ = 'with' # PYCHOK OK
424_x_ = 'x' # PYCHOK OK
425_X_ = 'X' # PYCHOK OK
426_xyz_ = 'xyz' # PYCHOK OK
427_y_ = 'y' # PYCHOK OK
428_Y_ = 'Y' # PYCHOK OK
429_z_ = 'z' # PYCHOK OK
430_Z_ = 'Z' # PYCHOK OK
431_zone_ = 'zone' # PYCHOK OK
433_EW_ = _E_ + _W_ # PYCHOK common cardinals
434_NE_ = _N_ + _E_ # PYCHOK positive ones
435_NS_ = _N_ + _S_ # PYCHOK OK
436_NSEW_ = _NS_ + _EW_ # PYCHOK OK
437_NW_ = _N_ + _W_ # PYCHOK OK
438_SE_ = _S_ + _E_ # PYCHOK OK
439_SW_ = _S_ + _W_ # PYCHOK negative ones
440# _NESW_ = _NE_ + _SW_ # PYCHOK clockwise
442_DDOT_ = Str_(_DOT_ * 2) # PYCHOK OK
443# _DEQUAL_ = Str_(_EQUAL_ * 2) # PYCHOK OK
444_DNL_ = Str_(_NL_ * 2) # PYCHOK OK
445# _DSLASH_ = Str_(_SLASH_ * 2) # PYCHOK OK
446# _DSTAR_ = Str_(_STAR_ * 2) # PYCHOK OK
447_DUNDER_ = Str_(_UNDER_ * 2) # PYCHOK OK
449_LR_PAIRS = {_LANGLE_: _RANGLE_,
450 _LCURLY_: _RCURLY_,
451 _LPAREN_: _RPAREN_,
452 _LSQUARE_: _RSQUARE_} # PYCHOK OK
455def _dunder_nameof(inst, *dflt):
456 '''(INTERNAL) Get the double_underscore __name__ attr.
457 '''
458 try:
459 return inst.__name__
460 except AttributeError:
461 pass
462 return dflt[0] if dflt else inst.__class__.__name__
465def _enquote(strs, quote=_QUOTE2_): # in .basics, .solveBase
466 '''(INTERNAL) Enquote a string containing whitespace.
467 '''
468 if len(strs.split()) > 1:
469 strs = NN(quote, strs, quote)
470 return strs
473def _is(a, b): # PYCHOK no cover
474 '''(INTERNAL) Is C{a is b}? in C{PyPy}
475 '''
476 return (a == b) if _isPyPy() else (a is b)
479def _isPyPy():
480 '''(INTERNAL) Is this C{PyPy}?
481 '''
482 # platform.python_implementation() == 'PyPy'
483 return _pythonarchine()[0].startswith(_PyPy__)
486def _load_lib(name):
487 '''(INTERNAL) Load a C{dylib}, B{C{name}} must startwith('lib').
488 '''
489 # macOS 11+ (aka 10.16) no longer provides direct loading of
490 # system libraries, instead it installs the library after a
491 # low-level dlopen(name) call where name is the library base
492 # name. As a result, ctypes.util.find_library can not find
493 # any library not previously dlopen'ed.
494 from ctypes import CDLL
495 from ctypes.util import find_library
497 ns = find_library(name), name
498 if _sys.platform[:6] == 'darwin': # and os.name == 'posix'
499 from ctypes import _dlopen, DEFAULT_MODE
500 from os.path import join
501 ns += (_DOT_(name, 'dylib'),
502 _DOT_(name, 'framework'), join(
503 _DOT_(name, 'framework'), name))
504 else: # non-macOS
505 DEFAULT_MODE = 0
507 def _dlopen(*unused):
508 return True
510 for n in ns:
511 try:
512 if n and _dlopen(n, DEFAULT_MODE): # pre-load handle
513 lib = CDLL(n) # == ctypes.cdll.LoadLibrary(n)
514 if lib._name: # has a qualified name
515 return lib
516 except (AttributeError, OSError):
517 pass
519 return None # raise OSError
522def machine():
523 '''Return standard C{platform.machine}, but distinguishing Intel I{native}
524 from Intel I{emulation} on Apple Silicon (on macOS only).
526 @return: Machine C{'arm64'} for Apple Silicon I{native}, C{'x86_64'}
527 for Intel I{native}, C{"arm64_x86_64"} for Intel I{emulation},
528 etc. (C{str} with C{comma}s replaced by C{underscore}s).
529 '''
530 return _platform2()[1]
533def _platform2(sep=NN):
534 '''(INTERNAL) Get platform architecture and machine as C{2-list} or C{str}.
535 '''
536 if not _pl2List:
537 import platform
538 m = platform.machine() # ARM64, arm64, x86_64, iPhone13,2, etc.
539 m = m.replace(_COMMA_, _UNDER_)
540 if m.lower() == 'x86_64': # on Intel or Rosetta2 ...
541 v = platform.mac_ver() # ... and only on macOS ...
542 if v and _version2(v[0]) > (10, 15): # ... 11+ aka 10.16
543 # <https://Developer.Apple.com/forums/thread/659846>
544 if _sysctl_uint('sysctl.proc_translated') == 1: # and \
545# _sysctl_uint('hw.optional.arm64') == 1: # PYCHOK indent
546 m = _UNDER_('arm64', m) # Apple Si emulating Intel x86-64
547 _pl2List[:] = [platform.architecture()[0], # bits
548 m] # arm64, arm64_x86_64, x86_64, etc.
549 return sep.join(_pl2List) if sep else _pl2List # 2-list()
552def _pythonarchine(sep=NN): # in test/bases.py versions
553 '''(INTERNAL) Get PyPy and Python versions and C{_platform2} as C{3- or 4-list} or C{str}.
554 '''
555 if not _Py3List:
556 v = _sys.version
557 _Py3List[:] = [_Python_(v)] + _platform2()
558 pypy = _PyPy__(v)
559 if pypy: # see _isPyPy, test/bases.py
560 _Py3List.insert(0, pypy)
561 return sep.join(_Py3List) if sep else _Py3List # 3- or 4-list
564def _splituple(strs, *sep_splits): # in .basics, .mgrs
565 '''(INTERNAL) Split a C{comma}- or C{whitespace}-separated
566 string into a C{tuple} of stripped strings.
567 '''
568 t = (strs.split(*sep_splits) if sep_splits else
569 strs.replace(_COMMA_, _SPACE_).split()) if strs else ()
570 return tuple(s.strip() for s in t if s)
573def _sysctl_uint(name):
574 '''(INTERNAL) Get an unsigned int sysctl item by name, use on macOS ONLY!
575 '''
576 libc = _load_lib('libc')
577 if libc: # <https://StackOverflow.com/questions/759892/python-ctypes-and-sysctl>
578 from ctypes import byref, c_char_p, c_size_t, c_uint, sizeof # get_errno
579 n = name if str is bytes else bytes(name, _utf_8_) # PYCHOK isPython2 = str is bytes
580 u = c_uint(0)
581 z = c_size_t(sizeof(u))
582 r = libc.sysctlbyname(c_char_p(n), byref(u), byref(z), None, c_size_t(0))
583 else: # could find or load 'libc'
584 r = -2
585 return int(r if r else u.value) # -1 ENOENT error, -2 no libc
588def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
589 '''(INTERNAL) Prefix C{name} with I{underscore}.
590 '''
591 return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
594def _usage(file_py, *args): # in .etm
595 '''(INTERNAL) Build "usage: python -m ..." cmd line for module B{C{file_py}}.
596 '''
597 import os
598 m = os.path.dirname(file_py).replace(os.getcwd(), _ELLIPSIS_) \
599 .replace(os.sep, _DOT_).strip()
600 b, x = os.path.splitext(os.path.basename(file_py))
601 if x == '.py' and b != '__main__':
602 m = _DOT_(m or _pygeodesy_, b)
603 p = NN(_python_, _sys.version_info[0])
604 return NN('usage', _SPACE_(_COLON_, p, '-m', _enquote(m), *args))
607def _version2(version, n=2):
608 '''(INTERNAL) Split C{B{version} str} into a C{1-, 2- or 3-tuple} of C{int}s.
609 '''
610 def _int(v):
611 try:
612 return int(v)
613 except (TypeError, ValueError):
614 pass
616 t = tuple(map(_int, _splituple(version, _DOT_, 2)))
617 if len(t) < n:
618 t += (0,) * n
619 return t[:n]
622__all__ = (_NN_, # not MISSING!
623 Str_.__name__, # classes
624 machine.__name__) # in .lazily
625__version__ = '23.08.23'
627if __name__ == '__main__':
629 from pygeodesy import itemsorted, printf
631 t = b = 0
632 for n, v in itemsorted(locals(), asorted=False, reverse=True):
633 if n.endswith(_UNDER_) and n.startswith(_UNDER_) and \
634 not n.startswith(_DUNDER_):
635 t += 1
636 b += len(v)
637 m = n[1:-1]
638 if m != v and m.replace(_UNDER_, _SPACE_) != v:
639 printf('%4d: %s = %r', t, n, v)
640 n = len(locals())
641 printf('%4d (%d) names, %s chars total, %.2f chars avg', t, n, b, float(b) / t, nl=1)
643# **) MIT License
644#
645# Copyright (C) 2016-2023 -- mrJean1 at Gmail -- All Rights Reserved.
646#
647# Permission is hereby granted, free of charge, to any person obtaining a
648# copy of this software and associated documentation files (the "Software"),
649# to deal in the Software without restriction, including without limitation
650# the rights to use, copy, modify, merge, publish, distribute, sublicense,
651# and/or sell copies of the Software, and to permit persons to whom the
652# Software is furnished to do so, subject to the following conditions:
653#
654# The above copyright notice and this permission notice shall be included
655# in all copies or substantial portions of the Software.
656#
657# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
658# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
659# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
660# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
661# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
662# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
663# OTHER DEALINGS IN THE SOFTWARE.