pygeodesy 24.5.8__py2.py3-none-any.whl → 24.5.24__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/METADATA +2 -2
- PyGeodesy-24.5.24.dist-info/RECORD +116 -0
- pygeodesy/__init__.py +16 -12
- pygeodesy/__main__.py +9 -10
- pygeodesy/albers.py +42 -42
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +7 -10
- pygeodesy/auxilats/auxAngle.py +32 -31
- pygeodesy/auxilats/auxLat.py +81 -51
- pygeodesy/azimuthal.py +123 -124
- pygeodesy/basics.py +165 -176
- pygeodesy/booleans.py +14 -15
- pygeodesy/cartesianBase.py +25 -23
- pygeodesy/clipy.py +3 -3
- pygeodesy/constants.py +8 -6
- pygeodesy/css.py +50 -42
- pygeodesy/datums.py +50 -48
- pygeodesy/dms.py +6 -6
- pygeodesy/ecef.py +27 -27
- pygeodesy/elevations.py +2 -2
- pygeodesy/ellipsoidalBase.py +28 -27
- pygeodesy/ellipsoidalBaseDI.py +8 -7
- pygeodesy/ellipsoidalNvector.py +11 -12
- pygeodesy/ellipsoids.py +41 -35
- pygeodesy/elliptic.py +12 -10
- pygeodesy/epsg.py +4 -3
- pygeodesy/errors.py +35 -13
- pygeodesy/etm.py +62 -53
- pygeodesy/fmath.py +48 -41
- pygeodesy/formy.py +93 -65
- pygeodesy/frechet.py +117 -102
- pygeodesy/fstats.py +52 -46
- pygeodesy/fsums.py +169 -145
- pygeodesy/gars.py +10 -9
- pygeodesy/geodesicw.py +32 -30
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +4 -4
- pygeodesy/geodesicx/gx.py +40 -32
- pygeodesy/geodesicx/gxarea.py +15 -12
- pygeodesy/geodesicx/gxbases.py +3 -4
- pygeodesy/geodesicx/gxline.py +6 -8
- pygeodesy/geodsolve.py +28 -26
- pygeodesy/geohash.py +47 -44
- pygeodesy/geoids.py +37 -35
- pygeodesy/hausdorff.py +112 -99
- pygeodesy/heights.py +136 -129
- pygeodesy/internals.py +576 -0
- pygeodesy/interns.py +6 -207
- pygeodesy/iters.py +22 -19
- pygeodesy/karney.py +18 -15
- pygeodesy/ktm.py +31 -24
- pygeodesy/latlonBase.py +12 -11
- pygeodesy/lazily.py +140 -218
- pygeodesy/lcc.py +24 -25
- pygeodesy/ltp.py +83 -71
- pygeodesy/ltpTuples.py +7 -5
- pygeodesy/mgrs.py +5 -4
- pygeodesy/named.py +136 -49
- pygeodesy/namedTuples.py +33 -25
- pygeodesy/nvectorBase.py +10 -9
- pygeodesy/osgr.py +14 -12
- pygeodesy/points.py +13 -13
- pygeodesy/props.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +3 -2
- pygeodesy/rhumb/solve.py +2 -2
- pygeodesy/solveBase.py +8 -7
- pygeodesy/sphericalTrigonometry.py +5 -5
- pygeodesy/streprs.py +8 -7
- pygeodesy/trf.py +8 -8
- pygeodesy/triaxials.py +67 -63
- pygeodesy/units.py +48 -50
- pygeodesy/unitsBase.py +24 -11
- pygeodesy/ups.py +7 -6
- pygeodesy/utily.py +4 -4
- pygeodesy/utm.py +53 -52
- pygeodesy/utmupsBase.py +11 -8
- pygeodesy/vector2d.py +6 -7
- pygeodesy/vector3d.py +16 -17
- pygeodesy/vector3dBase.py +5 -5
- PyGeodesy-24.5.8.dist-info/RECORD +0 -115
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/top_level.txt +0 -0
pygeodesy/internals.py
ADDED
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
|
|
4
|
+
'''
|
|
5
|
+
# from pygeodesy.basics import isiterablen # _MODS
|
|
6
|
+
# from pygeodesy.errors import _AttributeError, _error_init, _UnexpectedError, _xError2 # _MODS
|
|
7
|
+
from pygeodesy.interns import NN, _COLON_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
|
|
8
|
+
_immutable_, _NL_, _pygeodesy_, _PyPy__, _python_, \
|
|
9
|
+
_QUOTE1_, _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_, _utf_8_
|
|
10
|
+
from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
|
|
11
|
+
# from pygeodesy.streprs import anstr, pairs, unstr # _MODS
|
|
12
|
+
|
|
13
|
+
import os as _os # in .lazily, ...
|
|
14
|
+
import os.path as _os_path
|
|
15
|
+
# import sys as _sys # from .interns
|
|
16
|
+
|
|
17
|
+
_0_0 = 0.0 # PYCHOK in .basics, .constants
|
|
18
|
+
_arm64_ = 'arm64'
|
|
19
|
+
_iOS_ = 'iOS'
|
|
20
|
+
_macOS_ = 'macOS'
|
|
21
|
+
_Windows_ = 'Windows'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _dunder_nameof(inst, *dflt):
|
|
25
|
+
'''(INTERNAL) Get the double_underscore __name__ attr.
|
|
26
|
+
'''
|
|
27
|
+
try:
|
|
28
|
+
return inst.__name__
|
|
29
|
+
except AttributeError:
|
|
30
|
+
pass
|
|
31
|
+
return dflt[0] if dflt else inst.__class__.__name__
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _Property_RO(method):
|
|
35
|
+
'''(INTERNAL) Can't Irecursively import L{props.property_RO}.
|
|
36
|
+
'''
|
|
37
|
+
name = _dunder_nameof(method)
|
|
38
|
+
|
|
39
|
+
def _del(inst, attr): # PYCHOK no cover
|
|
40
|
+
delattr(inst, attr) # force error
|
|
41
|
+
|
|
42
|
+
def _get(inst, **unused): # PYCHOK 2 vs 3 args
|
|
43
|
+
try: # to get the cached value immediately
|
|
44
|
+
v = inst.__dict__[name]
|
|
45
|
+
except (AttributeError, KeyError):
|
|
46
|
+
# cache the value in the instance' __dict__
|
|
47
|
+
inst.__dict__[name] = v = method(inst)
|
|
48
|
+
return v
|
|
49
|
+
|
|
50
|
+
def _set(inst, val): # PYCHOK no cover
|
|
51
|
+
setattr(inst, name, val) # force error
|
|
52
|
+
|
|
53
|
+
return property(_get, _set, _del)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class _ALL_MODS_Base(object):
|
|
57
|
+
'''(INTERNAL) Base-class for C{lazily._ALL_MODS}.
|
|
58
|
+
'''
|
|
59
|
+
def __delattr__(self, attr): # PYCHOK no cover
|
|
60
|
+
self.__dict__.pop(attr, None)
|
|
61
|
+
|
|
62
|
+
def __setattr__(self, attr, value): # PYCHOK no cover
|
|
63
|
+
m = _MODS.errors
|
|
64
|
+
t = _EQUALSPACED_(self._DOT_(attr), repr(value))
|
|
65
|
+
raise m._AttributeError(_immutable_, txt=t)
|
|
66
|
+
|
|
67
|
+
@_Property_RO
|
|
68
|
+
def bits_machine2(self):
|
|
69
|
+
'''Get platform 2-list C{[bits, machine]}, I{once}.
|
|
70
|
+
'''
|
|
71
|
+
import platform as p
|
|
72
|
+
|
|
73
|
+
m = p.machine() # ARM64, arm64, x86_64, iPhone13,2, etc.
|
|
74
|
+
m = m.replace(_COMMA_, _UNDER_)
|
|
75
|
+
if m.lower() == 'x86_64': # PYCHOK on Intel or Rosetta2 ...
|
|
76
|
+
v = p.mac_ver()[0] # ... and only on macOS ...
|
|
77
|
+
if v and _version2(v) > (10, 15): # ... 11+ aka 10.16
|
|
78
|
+
# <https://Developer.Apple.com/forums/thread/659846>
|
|
79
|
+
# _sysctl_uint('hw.optional.arm64') and \
|
|
80
|
+
if _sysctl_uint('sysctl.proc_translated'):
|
|
81
|
+
m = _UNDER_(_arm64_, m) # Apple Si emulating Intel x86-64
|
|
82
|
+
return [p.architecture()[0], # bits
|
|
83
|
+
m] # arm64, arm64_x86_64, x86_64, etc.
|
|
84
|
+
|
|
85
|
+
@_Property_RO
|
|
86
|
+
def ctypes3(self):
|
|
87
|
+
'''Get 3-tuple C{(ctypes.CDLL, ._dlopen, .util.findlibrary)}, I{once}.
|
|
88
|
+
'''
|
|
89
|
+
if _ismacOS():
|
|
90
|
+
from ctypes import CDLL, DEFAULT_MODE, _dlopen
|
|
91
|
+
|
|
92
|
+
def dlopen(name):
|
|
93
|
+
return _dlopen(name, DEFAULT_MODE)
|
|
94
|
+
else: # PYCHOK no cover
|
|
95
|
+
from ctypes import CDLL
|
|
96
|
+
dlopen = _passarg
|
|
97
|
+
|
|
98
|
+
from ctypes.util import find_library
|
|
99
|
+
return CDLL, dlopen, find_library
|
|
100
|
+
|
|
101
|
+
@_Property_RO
|
|
102
|
+
def ctypes5(self):
|
|
103
|
+
'''Get 5-tuple C{(ctypes.byref, .c_char_p, .c_size_t, .c_uint, .sizeof)}, I{once}.
|
|
104
|
+
'''
|
|
105
|
+
from ctypes import byref, c_char_p, c_size_t, c_uint, sizeof # get_errno
|
|
106
|
+
return byref, c_char_p, c_size_t, c_uint, sizeof
|
|
107
|
+
|
|
108
|
+
def _DOT_(self, name): # PYCHOK no cover
|
|
109
|
+
return _DOT_(self.name, name)
|
|
110
|
+
|
|
111
|
+
@_Property_RO
|
|
112
|
+
def errors(self):
|
|
113
|
+
'''Get module C{pygeodesy.errors}, I{once}.
|
|
114
|
+
'''
|
|
115
|
+
from pygeodesy import errors # DON'T _lazy_import2
|
|
116
|
+
return errors
|
|
117
|
+
|
|
118
|
+
def ios_ver(self):
|
|
119
|
+
'''Mimick C{platform.xxx_ver} for C{iOS}.
|
|
120
|
+
'''
|
|
121
|
+
try: # Pythonista only
|
|
122
|
+
from platform import iOS_ver
|
|
123
|
+
return iOS_ver()
|
|
124
|
+
except (AttributeError, ImportError):
|
|
125
|
+
return NN, (NN, NN, NN), NN
|
|
126
|
+
|
|
127
|
+
@_Property_RO
|
|
128
|
+
def libc(self):
|
|
129
|
+
'''Load C{libc.dll|dylib}, I{once}.
|
|
130
|
+
'''
|
|
131
|
+
return _load_lib('libc')
|
|
132
|
+
|
|
133
|
+
@_Property_RO
|
|
134
|
+
def name(self):
|
|
135
|
+
'''Get this name (C{str}).
|
|
136
|
+
'''
|
|
137
|
+
return _dunder_nameof(self.__class__)
|
|
138
|
+
|
|
139
|
+
@_Property_RO
|
|
140
|
+
def nix2(self): # PYCHOK no cover
|
|
141
|
+
'''Get Linux 2-list C{[distro, version]}, I{once}.
|
|
142
|
+
'''
|
|
143
|
+
import platform as p
|
|
144
|
+
|
|
145
|
+
n, v = p.uname()[0], NN
|
|
146
|
+
if n.lower() == 'linux':
|
|
147
|
+
try: # use distro only for Linux, not macOS, etc.
|
|
148
|
+
import distro # <https://PyPI.org/project/distro>
|
|
149
|
+
_a = _MODS.streprs.anstr
|
|
150
|
+
v = _a(distro.version()) # first
|
|
151
|
+
n = _a(distro.id()) # .name()?
|
|
152
|
+
except (AttributeError, ImportError):
|
|
153
|
+
pass # v = str(_0_0)
|
|
154
|
+
n = n.capitalize()
|
|
155
|
+
return n, v
|
|
156
|
+
|
|
157
|
+
def nix_ver(self): # PYCHOK no cover
|
|
158
|
+
'''Mimick C{platform.xxx_ver} for C{*nix}.
|
|
159
|
+
'''
|
|
160
|
+
_, v = _MODS.nix2
|
|
161
|
+
t = _version2(v, n=3) if v else (NN, NN, NN)
|
|
162
|
+
return v, t, machine()
|
|
163
|
+
|
|
164
|
+
@_Property_RO
|
|
165
|
+
def osversion2(self):
|
|
166
|
+
'''Get 2-list C{[OS, release]}, I{once}.
|
|
167
|
+
'''
|
|
168
|
+
import platform as p
|
|
169
|
+
|
|
170
|
+
_Nix, _ = _MODS.nix2
|
|
171
|
+
# - mac_ver() returns ('10.12.5', ..., 'x86_64') on
|
|
172
|
+
# macOS and ('10.3.3', ..., 'iPad4,2') on iOS
|
|
173
|
+
# - win32_ver is ('XP', ..., 'SP3', ...) on Windows XP SP3
|
|
174
|
+
# - platform() returns 'Darwin-16.6.0-x86_64-i386-64bit'
|
|
175
|
+
# on macOS and 'Darwin-16.6.0-iPad4,2-64bit' on iOS
|
|
176
|
+
# - sys.platform is 'darwin' on macOS, 'ios' on iOS,
|
|
177
|
+
# 'win32' on Windows and 'cygwin' on Windows/Gygwin
|
|
178
|
+
# - distro.id() and .name() return 'Darwin' on macOS
|
|
179
|
+
for n, v in ((_iOS_, _MODS.ios_ver),
|
|
180
|
+
(_macOS_, p.mac_ver),
|
|
181
|
+
(_Windows_, p.win32_ver),
|
|
182
|
+
(_Nix, _MODS.nix_ver),
|
|
183
|
+
('Java', p.java_ver),
|
|
184
|
+
('uname', p.uname)):
|
|
185
|
+
v = v()[0]
|
|
186
|
+
if v and n:
|
|
187
|
+
break
|
|
188
|
+
else:
|
|
189
|
+
n = v = NN # XXX AssertioError?
|
|
190
|
+
return [n, v]
|
|
191
|
+
|
|
192
|
+
@_Property_RO
|
|
193
|
+
def Pythonarchine(self):
|
|
194
|
+
'''Get 3- or 4-list C{[PyPy, Python, bits, machine]}, I{once}.
|
|
195
|
+
'''
|
|
196
|
+
v = _sys.version
|
|
197
|
+
l3 = [_Python_(v)] + self.bits_machine2
|
|
198
|
+
pypy = _PyPy__(v)
|
|
199
|
+
if pypy: # PYCHOK no cover
|
|
200
|
+
l3.insert(0, pypy)
|
|
201
|
+
return l3
|
|
202
|
+
|
|
203
|
+
@_Property_RO
|
|
204
|
+
def streprs(self):
|
|
205
|
+
'''Get module C{pygeodesy.streprs}, I{once}.
|
|
206
|
+
'''
|
|
207
|
+
from pygeodesy import streprs # DON'T _lazy_import2
|
|
208
|
+
return streprs
|
|
209
|
+
|
|
210
|
+
_MODS = _ALL_MODS_Base() # PYCHOK overwritten by .lazily
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _caller3(up): # in .lazily, .named
|
|
214
|
+
'''(INTERNAL) Get 3-tuple C{(caller name, file name, line number)}
|
|
215
|
+
for the caller B{C{up}} stack frames in the Python call stack.
|
|
216
|
+
'''
|
|
217
|
+
# sys._getframe(1) ... 'importlib._bootstrap' line 1032,
|
|
218
|
+
# may throw a ValueError('call stack not deep enough')
|
|
219
|
+
f = _sys._getframe(up + 1)
|
|
220
|
+
return (f.f_code.co_name, # caller name
|
|
221
|
+
_os_path.basename(f.f_code.co_filename), # file name
|
|
222
|
+
f.f_lineno) # line number
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _dunder_ismain(name):
|
|
226
|
+
'''(INTERNAL) Return C{name == '__main__'}.
|
|
227
|
+
'''
|
|
228
|
+
return name == '__main__'
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _enquote(strs, quote=_QUOTE2_, white=NN): # in .basics, .solveBase
|
|
232
|
+
'''(INTERNAL) Enquote a string containing whitespace or replace
|
|
233
|
+
whitespace by C{white} if specified.
|
|
234
|
+
'''
|
|
235
|
+
if strs:
|
|
236
|
+
t = strs.split()
|
|
237
|
+
if len(t) > 1:
|
|
238
|
+
strs = white.join(t if white else (quote, strs, quote))
|
|
239
|
+
return strs
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _headof(name):
|
|
243
|
+
'''(INTERNAL) Get the head name of qualified C{name} or the C{name}.
|
|
244
|
+
'''
|
|
245
|
+
i = name.find(_DOT_)
|
|
246
|
+
return name if i < 0 else name[:i]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# def _is(a, b): # PYCHOK no cover
|
|
250
|
+
# '''(INTERNAL) C{a is b}? in C{PyPy}
|
|
251
|
+
# '''
|
|
252
|
+
# return (a == b) if _isPyPy() else (a is b)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _isAppleM():
|
|
256
|
+
'''(INTERNAL) Is this C{Apple Silicon}? (C{bool})
|
|
257
|
+
'''
|
|
258
|
+
return _ismacOS() and machine().startswith(_arm64_)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _isiOS(): # in test/bases.py
|
|
262
|
+
'''(INTERNAL) Is this C{iOS}? (C{bool})
|
|
263
|
+
'''
|
|
264
|
+
return _MODS.osversion2[0] is _iOS_
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _ismacOS(): # in test/bases.py
|
|
268
|
+
'''(INTERNAL) Is this C{macOS}? (C{bool})
|
|
269
|
+
'''
|
|
270
|
+
return _sys.platform[:6] == 'darwin' and \
|
|
271
|
+
_MODS.osversion2[0] is _macOS_ # and os.name == 'posix'
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def _isNix(): # in test/bases.py
|
|
275
|
+
'''(INTERNAL) Is this a C{Linux} distro? (C{str} or L{NN})
|
|
276
|
+
'''
|
|
277
|
+
return _MODS.nix2[0]
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _isPyPy(): # in test/bases.py
|
|
281
|
+
'''(INTERNAL) Is this C{PyPy}? (C{bool})
|
|
282
|
+
'''
|
|
283
|
+
# platform.python_implementation() == 'PyPy'
|
|
284
|
+
return _MODS.Pythonarchine[0].startswith(_PyPy__)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _isWindows(): # in test/bases.py
|
|
288
|
+
'''(INTERNAL) Is this C{Windows}? (C{bool})
|
|
289
|
+
'''
|
|
290
|
+
return _sys.platform[:3] == 'win' and \
|
|
291
|
+
_MODS.osversion2[0] is _Windows_
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _load_lib(name):
|
|
295
|
+
'''(INTERNAL) Load a C{dylib}, B{C{name}} must startwith('lib').
|
|
296
|
+
'''
|
|
297
|
+
# macOS 11+ (aka 10.16) no longer provides direct loading of
|
|
298
|
+
# system libraries. As a result, C{ctypes.util.find_library}
|
|
299
|
+
# will not find any library, unless previously installed by a
|
|
300
|
+
# low-level dlopen(name) call (with the library base C{name}).
|
|
301
|
+
CDLL, dlopen, find_lib = _MODS.ctypes3
|
|
302
|
+
|
|
303
|
+
ns = find_lib(name), name
|
|
304
|
+
if dlopen is not _passarg: # _ismacOS()
|
|
305
|
+
ns += (_DOT_(name, 'dylib'),
|
|
306
|
+
_DOT_(name, 'framework'), _os_path.join(
|
|
307
|
+
_DOT_(name, 'framework'), name))
|
|
308
|
+
for n in ns:
|
|
309
|
+
try:
|
|
310
|
+
if n and dlopen(n): # pre-load handle
|
|
311
|
+
lib = CDLL(n) # == ctypes.cdll.LoadLibrary(n)
|
|
312
|
+
if lib._name: # has a qualified name
|
|
313
|
+
return lib
|
|
314
|
+
except (AttributeError, OSError):
|
|
315
|
+
pass
|
|
316
|
+
|
|
317
|
+
return None # raise OSError
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def machine():
|
|
321
|
+
'''Return standard C{platform.machine}, but distinguishing Intel I{native}
|
|
322
|
+
from Intel I{emulation} on Apple Silicon (on macOS only).
|
|
323
|
+
|
|
324
|
+
@return: Machine C{'arm64'} for Apple Silicon I{native}, C{'x86_64'}
|
|
325
|
+
for Intel I{native}, C{"arm64_x86_64"} for Intel I{emulation},
|
|
326
|
+
etc. (C{str} with C{comma}s replaced by C{underscore}s).
|
|
327
|
+
'''
|
|
328
|
+
return _MODS.bits_machine2[1]
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _name_version(pkg):
|
|
332
|
+
'''(INTERNAL) Return C{pskg.__name__ + ' ' + .__version__}.
|
|
333
|
+
'''
|
|
334
|
+
return _SPACE_(pkg.__name__, pkg.__version__)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _osversion2(sep=NN): # in .lazily, test/bases.versions
|
|
338
|
+
'''(INTERNAL) Get the O/S name and release as C{2-list} or C{str}.
|
|
339
|
+
'''
|
|
340
|
+
l2 = _MODS.osversion2
|
|
341
|
+
return sep.join(l2) if sep else l2 # 2-list()
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _passarg(arg):
|
|
345
|
+
'''(INTERNAL) Helper, no-op.
|
|
346
|
+
'''
|
|
347
|
+
return arg
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _passargs(*args):
|
|
351
|
+
'''(INTERNAL) Helper, no-op.
|
|
352
|
+
'''
|
|
353
|
+
return args
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def _plural(noun, n):
|
|
357
|
+
'''(INTERNAL) Return C{noun}['s'] or C{NN}.
|
|
358
|
+
'''
|
|
359
|
+
return NN(noun, _s_) if n > 1 else (noun if n else NN)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def print_(*args, **nl_nt_prec_prefix__end_file_flush_sep_kwds): # PYCHOK no cover
|
|
363
|
+
'''Python 3+ C{print}-like formatting and printing.
|
|
364
|
+
|
|
365
|
+
@arg args: Values to be converted to C{str} and joined by B{C{sep}},
|
|
366
|
+
all positional.
|
|
367
|
+
|
|
368
|
+
@see: Function L{printf} for further details.
|
|
369
|
+
'''
|
|
370
|
+
return printf(NN, *args, **nl_nt_prec_prefix__end_file_flush_sep_kwds)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def printf(fmt, *args, **nl_nt_prec_prefix__end_file_flush_sep_kwds):
|
|
374
|
+
'''C{Printf-style} and Python 3+ C{print}-like formatting and printing.
|
|
375
|
+
|
|
376
|
+
@arg fmt: U{Printf-style<https://Docs.Python.org/3/library/stdtypes.html#
|
|
377
|
+
printf-style-string-formatting>} format specification (C{str}).
|
|
378
|
+
@arg args: Arguments to be formatted (any C{type}, all positional).
|
|
379
|
+
@kwarg nl_nt_prec_prefix__end_file_flush_sep_kwds: Optional keyword arguments
|
|
380
|
+
C{B{nl}=0} for the number of leading blank lines (C{int}), C{B{nt}=0}
|
|
381
|
+
the number of trailing blank lines (C{int}), C{B{prefix}=NN} to be
|
|
382
|
+
inserted before the formatted text (C{str}) and Python 3+ C{print}
|
|
383
|
+
keyword arguments C{B{end}}, C{B{sep}}, C{B{file}} and C{B{flush}}.
|
|
384
|
+
Any remaining C{B{kwds}} are C{printf-style} name-value pairs to be
|
|
385
|
+
formatted, I{iff no B{C{args}} are present} using C{B{prec}=6} for
|
|
386
|
+
the number of decimal digits (C{int}).
|
|
387
|
+
|
|
388
|
+
@return: Number of bytes written.
|
|
389
|
+
'''
|
|
390
|
+
b, e, f, fl, p, s, kwds = _print7(**nl_nt_prec_prefix__end_file_flush_sep_kwds)
|
|
391
|
+
try:
|
|
392
|
+
if args:
|
|
393
|
+
t = (fmt % args) if fmt else s.join(map(str, args))
|
|
394
|
+
elif kwds:
|
|
395
|
+
t = (fmt % kwds) if fmt else s.join(
|
|
396
|
+
_MODS.streprs.pairs(kwds, prec=p))
|
|
397
|
+
else:
|
|
398
|
+
t = fmt
|
|
399
|
+
except Exception as x:
|
|
400
|
+
_E, s = _MODS.errors._xError2(x)
|
|
401
|
+
unstr = _MODS.streprs.unstr
|
|
402
|
+
t = unstr(printf, fmt, *args, **nl_nt_prec_prefix__end_file_flush_sep_kwds)
|
|
403
|
+
raise _E(s, txt=t, cause=x)
|
|
404
|
+
try:
|
|
405
|
+
n = f.write(NN(b, t, e))
|
|
406
|
+
except UnicodeEncodeError: # XXX only Windows
|
|
407
|
+
t = t.replace('\u2032', _QUOTE1_).replace('\u2033', _QUOTE2_)
|
|
408
|
+
n = f.write(NN(b, t, e))
|
|
409
|
+
if fl: # PYCHOK no cover
|
|
410
|
+
f.flush()
|
|
411
|
+
return n
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _print7(nl=0, nt=0, prec=6, prefix=NN, sep=_SPACE_, file=_sys.stdout,
|
|
415
|
+
end=_NL_, flush=False, **kwds):
|
|
416
|
+
'''(INTERNAL) Unravel the C{printf} and remaining keyword arguments.
|
|
417
|
+
'''
|
|
418
|
+
if nl > 0:
|
|
419
|
+
prefix = NN(_NL_ * nl, prefix)
|
|
420
|
+
if nt > 0:
|
|
421
|
+
end = NN(end, _NL_ * nt)
|
|
422
|
+
return prefix, end, file, flush, prec, sep, kwds
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def _Pythonarchine(sep=NN): # in .lazily, test/bases.py versions
|
|
426
|
+
'''(INTERNAL) Get PyPy and Python versions, bit and machine as C{3- or 4-list} or C{str}.
|
|
427
|
+
'''
|
|
428
|
+
l3 = _MODS.Pythonarchine
|
|
429
|
+
return sep.join(l3) if sep else l3 # 3- or 4-list
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def _sizeof(obj):
|
|
433
|
+
'''(INTERNAL) Recursively size an C{obj}ect.
|
|
434
|
+
|
|
435
|
+
@return: The C{obj} size in bytes (C{int}),
|
|
436
|
+
ignoring class attributes and
|
|
437
|
+
counting duplicates only once or
|
|
438
|
+
C{None}.
|
|
439
|
+
|
|
440
|
+
@note: With C{PyPy}, the size is always C{None}.
|
|
441
|
+
'''
|
|
442
|
+
try:
|
|
443
|
+
_zB = _sys.getsizeof
|
|
444
|
+
_zD = _zB(None) # some default
|
|
445
|
+
except TypeError: # PyPy3.10
|
|
446
|
+
return None
|
|
447
|
+
|
|
448
|
+
_isiterablen = _MODS.basics.isiterablen
|
|
449
|
+
|
|
450
|
+
def _zR(s, iterable):
|
|
451
|
+
z, _s = 0, s.add
|
|
452
|
+
for o in iterable:
|
|
453
|
+
i = id(o)
|
|
454
|
+
if i not in s:
|
|
455
|
+
_s(i)
|
|
456
|
+
z += _zB(o, _zD)
|
|
457
|
+
if isinstance(o, dict):
|
|
458
|
+
z += _zR(s, o.keys())
|
|
459
|
+
z += _zR(s, o.values())
|
|
460
|
+
elif _isiterablen(o): # not map, ...
|
|
461
|
+
z += _zR(s, o)
|
|
462
|
+
else:
|
|
463
|
+
try: # size instance' attr values only
|
|
464
|
+
z += _zR(s, o.__dict__.values())
|
|
465
|
+
except AttributeError: # None, int, etc.
|
|
466
|
+
pass
|
|
467
|
+
return z
|
|
468
|
+
|
|
469
|
+
return _zR(set(), (obj,))
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _sysctl_uint(name):
|
|
473
|
+
'''(INTERNAL) Get an unsigned int sysctl item by name, use on macOS ONLY!
|
|
474
|
+
'''
|
|
475
|
+
libc = _MODS.libc
|
|
476
|
+
if libc: # <https://StackOverflow.com/questions/759892/python-ctypes-and-sysctl>
|
|
477
|
+
byref, char_p, size_t, uint, sizeof = _MODS.ctypes5
|
|
478
|
+
n = name if str is bytes else bytes(name, _utf_8_) # PYCHOK isPython2 = str is bytes
|
|
479
|
+
u = uint(0)
|
|
480
|
+
z = size_t(sizeof(u))
|
|
481
|
+
r = libc.sysctlbyname(char_p(n), byref(u), byref(z), None, size_t(0))
|
|
482
|
+
else: # could find or load 'libc'
|
|
483
|
+
r = -2
|
|
484
|
+
return int(r if r else u.value) # -1 ENOENT error, -2 no libc
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _tailof(name):
|
|
488
|
+
'''(INTERNAL) Get the base name of qualified C{name} or the C{name}.
|
|
489
|
+
'''
|
|
490
|
+
i = name.rfind(_DOT_) + 1
|
|
491
|
+
return name[i:] if i > 0 else name
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
|
|
495
|
+
'''(INTERNAL) Prefix C{name} with an I{underscore}.
|
|
496
|
+
'''
|
|
497
|
+
return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _usage(file_py, *args): # in .etm
|
|
501
|
+
'''(INTERNAL) Build "usage: python -m ..." cmd line for module B{C{file_py}}.
|
|
502
|
+
'''
|
|
503
|
+
m = _os_path.dirname(file_py).replace(_os.getcwd(), _ELLIPSIS_) \
|
|
504
|
+
.replace(_os.sep, _DOT_).strip()
|
|
505
|
+
b, x = _os_path.splitext(_os_path.basename(file_py))
|
|
506
|
+
if x == '.py' and not _dunder_ismain(b):
|
|
507
|
+
m = _DOT_(m or _pygeodesy_, b)
|
|
508
|
+
p = NN(_python_, _sys.version_info[0])
|
|
509
|
+
u = _COLON_(_dunder_nameof(_usage)[1:], NN)
|
|
510
|
+
return _SPACE_(u, p, '-m', _enquote(m), *args)
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def _version2(version, n=2):
|
|
514
|
+
'''(INTERNAL) Split C{B{version} str} into a C{1-, 2- or 3-tuple} of C{int}s.
|
|
515
|
+
'''
|
|
516
|
+
t = _version_ints(version.split(_DOT_, 2))
|
|
517
|
+
if len(t) < n:
|
|
518
|
+
t += (0,) * n
|
|
519
|
+
return t[:n]
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def _version_info(package): # in .Base.karney, .basics
|
|
523
|
+
'''(INTERNAL) Get the C{package.__version_info__} as a 2- or
|
|
524
|
+
3-tuple C{(major, minor, revision)} if C{int}s.
|
|
525
|
+
'''
|
|
526
|
+
try:
|
|
527
|
+
return _version_ints(package.__version_info__)
|
|
528
|
+
except AttributeError:
|
|
529
|
+
return _version2(package.__version__.strip(), n=3)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def _version_ints(vs):
|
|
533
|
+
# helper for _version2 and _version_info above
|
|
534
|
+
|
|
535
|
+
def _ints(vs):
|
|
536
|
+
for v in vs:
|
|
537
|
+
try:
|
|
538
|
+
yield int(v.strip())
|
|
539
|
+
except (TypeError, ValueError):
|
|
540
|
+
pass
|
|
541
|
+
|
|
542
|
+
return tuple(_ints(vs))
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
__all__ = tuple(map(_dunder_nameof, (machine, print_, printf)))
|
|
546
|
+
__version__ = '24.05.21'
|
|
547
|
+
|
|
548
|
+
if _dunder_ismain(__name__): # PYCHOK no cover
|
|
549
|
+
|
|
550
|
+
from pygeodesy import _isfrozen, isLazy, version as vs
|
|
551
|
+
|
|
552
|
+
print_(_pygeodesy_, vs, *(_Pythonarchine() + _osversion2()
|
|
553
|
+
+ ['isfrozen', _isfrozen,
|
|
554
|
+
'isLazy', isLazy]))
|
|
555
|
+
|
|
556
|
+
# **) MIT License
|
|
557
|
+
#
|
|
558
|
+
# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
559
|
+
#
|
|
560
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
561
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
562
|
+
# to deal in the Software without restriction, including without limitation
|
|
563
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
564
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
565
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
566
|
+
#
|
|
567
|
+
# The above copyright notice and this permission notice shall be included
|
|
568
|
+
# in all copies or substantial portions of the Software.
|
|
569
|
+
#
|
|
570
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
571
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
572
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
573
|
+
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
574
|
+
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
575
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
576
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|