pygeodesy 24.10.10__py2.py3-none-any.whl → 24.11.11__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.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
- PyGeodesy-24.11.11.dist-info/RECORD +118 -0
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +14 -14
- pygeodesy/__main__.py +5 -5
- pygeodesy/albers.py +12 -17
- pygeodesy/azimuthal.py +51 -61
- pygeodesy/basics.py +60 -62
- pygeodesy/booleans.py +87 -79
- pygeodesy/cartesianBase.py +6 -6
- pygeodesy/constants.py +23 -19
- pygeodesy/css.py +7 -8
- pygeodesy/datums.py +3 -3
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +9 -9
- pygeodesy/deprecated/functions.py +6 -6
- pygeodesy/dms.py +250 -270
- pygeodesy/ecef.py +11 -14
- pygeodesy/ellipsoidalBase.py +106 -121
- pygeodesy/ellipsoidalBaseDI.py +114 -118
- pygeodesy/ellipsoidalExact.py +35 -37
- pygeodesy/ellipsoidalNvector.py +4 -4
- pygeodesy/ellipsoidalVincenty.py +2 -2
- pygeodesy/ellipsoids.py +10 -51
- pygeodesy/elliptic.py +14 -14
- pygeodesy/errors.py +28 -28
- pygeodesy/etm.py +92 -68
- pygeodesy/fmath.py +42 -40
- pygeodesy/formy.py +7 -6
- pygeodesy/fsums.py +72 -51
- pygeodesy/geodesici.py +43 -40
- pygeodesy/geodesicw.py +17 -16
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodesicx/gxarea.py +3 -2
- pygeodesy/geodsolve.py +79 -39
- pygeodesy/geohash.py +2 -2
- pygeodesy/geoids.py +32 -31
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +201 -147
- pygeodesy/interns.py +23 -20
- pygeodesy/karney.py +62 -13
- pygeodesy/ktm.py +11 -13
- pygeodesy/latlonBase.py +18 -20
- pygeodesy/lazily.py +210 -218
- pygeodesy/lcc.py +4 -4
- pygeodesy/ltp.py +10 -10
- pygeodesy/ltpTuples.py +74 -75
- pygeodesy/mgrs.py +20 -21
- pygeodesy/named.py +15 -10
- pygeodesy/nvectorBase.py +1 -1
- pygeodesy/osgr.py +9 -12
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +35 -14
- pygeodesy/resections.py +9 -10
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +5 -5
- pygeodesy/rhumb/solve.py +9 -10
- pygeodesy/simplify.py +5 -5
- pygeodesy/solveBase.py +7 -25
- pygeodesy/sphericalBase.py +20 -23
- pygeodesy/sphericalNvector.py +103 -145
- pygeodesy/sphericalTrigonometry.py +68 -73
- pygeodesy/streprs.py +5 -5
- pygeodesy/trf.py +6 -4
- pygeodesy/triaxials.py +46 -9
- pygeodesy/units.py +5 -4
- pygeodesy/ups.py +6 -6
- pygeodesy/utily.py +2 -2
- pygeodesy/utm.py +7 -7
- pygeodesy/vector2d.py +13 -13
- pygeodesy/vector3d.py +19 -21
- pygeodesy/vector3dBase.py +21 -19
- pygeodesy/webmercator.py +4 -4
- pygeodesy/wgrs.py +4 -4
- PyGeodesy-24.10.10.dist-info/RECORD +0 -118
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/azimuthal.py
CHANGED
|
@@ -49,7 +49,7 @@ from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB, \
|
|
|
49
49
|
_xinstanceof
|
|
50
50
|
from pygeodesy.datums import _spherical_datum, _WGS84
|
|
51
51
|
from pygeodesy.errors import _ValueError, _xdatum, _xkwds
|
|
52
|
-
from pygeodesy.fmath import euclid, hypot as _hypot, Fsum
|
|
52
|
+
from pygeodesy.fmath import euclid, fdot_, hypot as _hypot, Fsum
|
|
53
53
|
# from pygeodesy.fsums import Fsum # from .fmath
|
|
54
54
|
# from pygeodesy.formy import antipode # _MODS
|
|
55
55
|
from pygeodesy.interns import _azimuth_, _datum_, _lat_, _lon_, _scale_, \
|
|
@@ -70,7 +70,7 @@ from pygeodesy.utily import asin1, atan1, atan2b, atan2d, sincos2, \
|
|
|
70
70
|
from math import acos, atan2, degrees, fabs, sin, sqrt
|
|
71
71
|
|
|
72
72
|
__all__ = _ALL_LAZY.azimuthal
|
|
73
|
-
__version__ = '24.07
|
|
73
|
+
__version__ = '24.11.07'
|
|
74
74
|
|
|
75
75
|
_EPS_K = _EPStol * _0_1 # Karney's eps_ or _EPSmin * _0_1?
|
|
76
76
|
_over_horizon_ = 'over horizon'
|
|
@@ -154,10 +154,10 @@ class _AzimuthalBase(_NamedBase):
|
|
|
154
154
|
s0, c0 = self._sc0
|
|
155
155
|
|
|
156
156
|
cb *= ca
|
|
157
|
-
k, t = _k_t_2(s0
|
|
157
|
+
k, t = _k_t_2(fdot_(s0, sa, c0, cb))
|
|
158
158
|
if t:
|
|
159
159
|
r = k * self.radius
|
|
160
|
-
y = r * (c0
|
|
160
|
+
y = r * fdot_(c0, sa, -s0, cb)
|
|
161
161
|
e, n, z, _ = _enzh4(r * sb * ca, y, None)
|
|
162
162
|
else: # 0 or 180
|
|
163
163
|
e = n = z = _0_0
|
|
@@ -233,11 +233,11 @@ class _AzimuthalBase(_NamedBase):
|
|
|
233
233
|
Lon_(lon0=lon0, Error=AzimuthalError))
|
|
234
234
|
self._sc0 = sincos2d(self.lat0)
|
|
235
235
|
|
|
236
|
-
def reverse(self, x, y,
|
|
236
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
237
237
|
'''I{Must be overloaded}.'''
|
|
238
|
-
self._notOverloaded(x, y,
|
|
238
|
+
self._notOverloaded(x, y, **name_LatLon_and_kwds) # PYCHOK no cover
|
|
239
239
|
|
|
240
|
-
def _reverse(self, x, y, _c, lea, LatLon, **name_LatLon_kwds):
|
|
240
|
+
def _reverse(self, x, y, _c, lea, LatLon=None, **name_LatLon_kwds):
|
|
241
241
|
'''(INTERNAL) Azimuthal (spherical) reverse C{x, y} to C{lat, lon}.
|
|
242
242
|
'''
|
|
243
243
|
e, n, z, r = _enzh4(x, y)
|
|
@@ -379,15 +379,14 @@ class Equidistant(_AzimuthalBase):
|
|
|
379
379
|
|
|
380
380
|
return self._forward(lat, lon, name, _k_t)
|
|
381
381
|
|
|
382
|
-
def reverse(self, x, y,
|
|
382
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
383
383
|
'''Convert an azimuthal equidistant location to geodetic lat- and longitude.
|
|
384
384
|
|
|
385
385
|
@arg x: Easting of the location (C{meter}).
|
|
386
386
|
@arg y: Northing of the location (C{meter}).
|
|
387
|
-
@kwarg
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
ignored if C{B{LatLon} is None}.
|
|
387
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}=NN} and class C{B{LatLon}=None}
|
|
388
|
+
to use and optionally, additional B{C{LatLon}} keyword arguments,
|
|
389
|
+
ignored if C{B{LatLon} is None}.
|
|
391
390
|
|
|
392
391
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
393
392
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
@@ -401,7 +400,7 @@ class Equidistant(_AzimuthalBase):
|
|
|
401
400
|
def _c(c):
|
|
402
401
|
return c if c > EPS else None
|
|
403
402
|
|
|
404
|
-
return self._reverse(x, y, _c, False,
|
|
403
|
+
return self._reverse(x, y, _c, False, **name_LatLon_and_kwds)
|
|
405
404
|
|
|
406
405
|
|
|
407
406
|
def equidistant(lat0, lon0, datum=_WGS84, exact=False, geodsolve=False, **name):
|
|
@@ -505,9 +504,8 @@ class _EquidistantBase(_AzimuthalGeodesic):
|
|
|
505
504
|
@arg x: Easting of the location (C{meter}).
|
|
506
505
|
@arg y: Northing of the location (C{meter}).
|
|
507
506
|
@kwarg LatLon: Class to use (C{LatLon}) or C{None}.
|
|
508
|
-
@kwarg name_LatLon_kwds: Optional C{B{name}=NN}
|
|
509
|
-
|
|
510
|
-
ignored if C{B{LatLon} is None}.
|
|
507
|
+
@kwarg name_LatLon_kwds: Optional C{B{name}=NN} and optionally, additional
|
|
508
|
+
B{C{LatLon}} keyword arguments, ignored if C{B{LatLon} is None}.
|
|
511
509
|
|
|
512
510
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
513
511
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
@@ -670,15 +668,14 @@ class Gnomonic(_AzimuthalBase):
|
|
|
670
668
|
|
|
671
669
|
return self._forward(lat, lon, name, _k_t)
|
|
672
670
|
|
|
673
|
-
def reverse(self, x, y,
|
|
671
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
674
672
|
'''Convert an azimuthal equidistant location to geodetic lat- and longitude.
|
|
675
673
|
|
|
676
674
|
@arg x: Easting of the location (C{meter}).
|
|
677
675
|
@arg y: Northing of the location (C{meter}).
|
|
678
|
-
@kwarg
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
ignored if C{B{LatLon} is None}.
|
|
676
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}=NN} and class C{B{LatLon}=None}
|
|
677
|
+
for the location and optionally, additional B{C{LatLon}} keyword
|
|
678
|
+
arguments, ignored if C{B{LatLon} is None}.
|
|
682
679
|
|
|
683
680
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
684
681
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
@@ -692,7 +689,7 @@ class Gnomonic(_AzimuthalBase):
|
|
|
692
689
|
def _c(c):
|
|
693
690
|
return atan1(c) if c > EPS else None
|
|
694
691
|
|
|
695
|
-
return self._reverse(x, y, _c, False,
|
|
692
|
+
return self._reverse(x, y, _c, False, **name_LatLon_and_kwds)
|
|
696
693
|
|
|
697
694
|
|
|
698
695
|
def gnomonic(lat0, lon0, datum=_WGS84, exact=False, geodsolve=False, **name):
|
|
@@ -787,20 +784,18 @@ class _GnomonicBase(_AzimuthalGeodesic):
|
|
|
787
784
|
@arg x: Easting of the location (C{meter}).
|
|
788
785
|
@arg y: Northing of the location (C{meter}).
|
|
789
786
|
@kwarg LatLon: Class to use (C{LatLon}) or C{None}.
|
|
790
|
-
@kwarg name_LatLon_kwds: Optional C{B{name}=NN} for the location and
|
|
791
|
-
|
|
792
|
-
ignored if C{B{LatLon} is None}.
|
|
787
|
+
@kwarg name_LatLon_kwds: Optional C{B{name}=NN} for the location and optionally,
|
|
788
|
+
additional B{C{LatLon}} keyword arguments, ignored if C{B{LatLon} is None}.
|
|
793
789
|
|
|
794
790
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
795
791
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
796
792
|
|
|
797
793
|
@raise AzimuthalError: No convergence.
|
|
798
794
|
|
|
799
|
-
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon}
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
to this.
|
|
795
|
+
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon} in the range
|
|
796
|
+
C{[-180..180] degrees}. The C{azimuth} is clockwise from true North. The
|
|
797
|
+
scale is C{1 / reciprocal**2} in C{radial} direction and C{1 / reciprocal}
|
|
798
|
+
in the direction perpendicular to this.
|
|
804
799
|
'''
|
|
805
800
|
e, n, z, q = _enzh4(x, y)
|
|
806
801
|
|
|
@@ -974,30 +969,28 @@ class LambertEqualArea(_AzimuthalBase):
|
|
|
974
969
|
|
|
975
970
|
return self._forward(lat, lon, name, _k_t)
|
|
976
971
|
|
|
977
|
-
def reverse(self, x, y,
|
|
972
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
978
973
|
'''Convert an azimuthal Lambert-equal-area location to geodetic lat- and longitude.
|
|
979
974
|
|
|
980
975
|
@arg x: Easting of the location (C{meter}).
|
|
981
976
|
@arg y: Northing of the location (C{meter}).
|
|
982
|
-
@kwarg
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
arguments, ignored if C{B{LatLon} is None}.
|
|
977
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}=NN} and class C{B{LatLon}=None}
|
|
978
|
+
to use and optionally, additional B{C{LatLon}} keyword arguments,
|
|
979
|
+
ignored if C{B{LatLon} is None}.
|
|
986
980
|
|
|
987
981
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
988
982
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
989
983
|
|
|
990
|
-
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
perpendicular to this.
|
|
984
|
+
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon} in the
|
|
985
|
+
range C{[-180..180] degrees}. The C{scale} of the projection is C{1}
|
|
986
|
+
in I{radial} direction, C{azimuth} clockwise from true North and is C{1
|
|
987
|
+
/ reciprocal} in the direction perpendicular to this.
|
|
995
988
|
'''
|
|
996
989
|
def _c(c):
|
|
997
990
|
c *= _0_5
|
|
998
991
|
return (asin1(c) * _2_0) if c > EPS else None
|
|
999
992
|
|
|
1000
|
-
return self._reverse(x, y, _c, True,
|
|
993
|
+
return self._reverse(x, y, _c, True, **name_LatLon_and_kwds)
|
|
1001
994
|
|
|
1002
995
|
|
|
1003
996
|
class Orthographic(_AzimuthalBase):
|
|
@@ -1028,29 +1021,27 @@ class Orthographic(_AzimuthalBase):
|
|
|
1028
1021
|
|
|
1029
1022
|
return self._forward(lat, lon, name, _k_t)
|
|
1030
1023
|
|
|
1031
|
-
def reverse(self, x, y,
|
|
1024
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
1032
1025
|
'''Convert an azimuthal orthographic location to geodetic lat- and longitude.
|
|
1033
1026
|
|
|
1034
1027
|
@arg x: Easting of the location (C{meter}).
|
|
1035
1028
|
@arg y: Northing of the location (C{meter}).
|
|
1036
|
-
@kwarg
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
ignored if C{B{LatLon} is None}.
|
|
1029
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}=NN} and class C{B{LatLon}=None}
|
|
1030
|
+
to use and optionally, additional B{C{LatLon}} keyword arguments,
|
|
1031
|
+
ignored if C{B{LatLon} is None}.
|
|
1040
1032
|
|
|
1041
1033
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
1042
1034
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
1043
1035
|
|
|
1044
|
-
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
perpendicular to this.
|
|
1036
|
+
@note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon} in the
|
|
1037
|
+
range C{[-180..180] degrees}. The C{scale} of the projection is C{1}
|
|
1038
|
+
in I{radial} direction, C{azimuth} clockwise from true North and is C{1
|
|
1039
|
+
/ reciprocal} in the direction perpendicular to this.
|
|
1049
1040
|
'''
|
|
1050
1041
|
def _c(c):
|
|
1051
1042
|
return asin1(c) if c > EPS else None
|
|
1052
1043
|
|
|
1053
|
-
return self._reverse(x, y, _c, False,
|
|
1044
|
+
return self._reverse(x, y, _c, False, **name_LatLon_and_kwds)
|
|
1054
1045
|
|
|
1055
1046
|
|
|
1056
1047
|
class Stereographic(_AzimuthalBase):
|
|
@@ -1101,28 +1092,27 @@ class Stereographic(_AzimuthalBase):
|
|
|
1101
1092
|
self._k0 = Scalar_(factor, name=n, low=EPS, high=2) # XXX high=1, 2, other?
|
|
1102
1093
|
self._k02 = self._k0 * _2_0
|
|
1103
1094
|
|
|
1104
|
-
def reverse(self, x, y,
|
|
1095
|
+
def reverse(self, x, y, **name_LatLon_and_kwds):
|
|
1105
1096
|
'''Convert an azimuthal stereographic location to geodetic lat- and longitude.
|
|
1106
1097
|
|
|
1107
1098
|
@arg x: Easting of the location (C{meter}).
|
|
1108
1099
|
@arg y: Northing of the location (C{meter}).
|
|
1109
|
-
@kwarg
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
ignored if C{B{LatLon} is None}.
|
|
1100
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}=NN} and class C{B{LatLon}=None}
|
|
1101
|
+
to use and optionally, additional B{C{LatLon}} keyword arguments,
|
|
1102
|
+
ignored if C{B{LatLon} is None}.
|
|
1113
1103
|
|
|
1114
1104
|
@return: The geodetic (C{LatLon}) or if C{B{LatLon} is None} an
|
|
1115
1105
|
L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}.
|
|
1116
1106
|
|
|
1117
1107
|
@note: The C{lat} will be in range C{[-90..90] degrees}, C{lon} in range
|
|
1118
|
-
C{[-180..180] degrees} and C{azimuth} clockwise from true North.
|
|
1119
|
-
|
|
1120
|
-
|
|
1108
|
+
C{[-180..180] degrees} and C{azimuth} clockwise from true North. The
|
|
1109
|
+
C{scale} of the projection is C{1} in I{radial} direction and is C{1
|
|
1110
|
+
/ reciprocal} in the direction perpendicular to this.
|
|
1121
1111
|
'''
|
|
1122
1112
|
def _c(c):
|
|
1123
1113
|
return (atan2(c, self._k02) * _2_0) if c > EPS else None
|
|
1124
1114
|
|
|
1125
|
-
return self._reverse(x, y, _c, False,
|
|
1115
|
+
return self._reverse(x, y, _c, False, **name_LatLon_and_kwds)
|
|
1126
1116
|
|
|
1127
1117
|
|
|
1128
1118
|
__all__ += _ALL_DOCS(_AzimuthalBase, _AzimuthalGeodesic, _EquidistantBase, _GnomonicBase)
|
pygeodesy/basics.py
CHANGED
|
@@ -20,30 +20,28 @@ from pygeodesy.errors import _AttributeError, _ImportError, _NotImplementedError
|
|
|
20
20
|
_TypeError, _TypesError, _ValueError, _xAssertionError, \
|
|
21
21
|
_xkwds_get1
|
|
22
22
|
# from pygeodesy.fsums import _isFsum_2Tuple # _MODS
|
|
23
|
-
from pygeodesy.internals import _0_0, _enquote, _passarg,
|
|
23
|
+
from pygeodesy.internals import _0_0, _enquote, _getenv, _passarg, _PYGEODESY, \
|
|
24
|
+
_version_info
|
|
24
25
|
from pygeodesy.interns import MISSING, NN, _1_, _by_, _COMMA_, _DOT_, _DEPRECATED_, \
|
|
25
26
|
_ELLIPSIS4_, _EQUAL_, _in_, _invalid_, _N_A_, _not_, \
|
|
26
27
|
_not_scalar_, _odd_, _SPACE_, _UNDER_, _version_
|
|
27
28
|
# from pygeodesy.latlonBase import LatLonBase # _MODS
|
|
28
|
-
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS,
|
|
29
|
-
LazyImportError, _sys_version_info2
|
|
29
|
+
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, LazyImportError
|
|
30
30
|
# from pygeodesy.named import classname, modulename, _name__ # _MODS
|
|
31
31
|
# from pygeodesy.nvectorBase import NvectorBase # _MODS
|
|
32
32
|
# from pygeodesy.props import _update_all # _MODS
|
|
33
33
|
# from pygeodesy.streprs import Fmt # _MODS
|
|
34
|
-
# from pygeodesy.unitsBase import _NamedUnit, Str # _MODS
|
|
35
34
|
|
|
36
35
|
from copy import copy as _copy, deepcopy as _deepcopy
|
|
37
36
|
from math import copysign as _copysign
|
|
38
|
-
import inspect as _inspect
|
|
37
|
+
# import inspect as _inspect # _MODS
|
|
39
38
|
|
|
40
39
|
__all__ = _ALL_LAZY.basics
|
|
41
|
-
__version__ = '24.
|
|
40
|
+
__version__ = '24.11.02'
|
|
42
41
|
|
|
43
|
-
_below_
|
|
44
|
-
_list_tuple_types
|
|
45
|
-
|
|
46
|
-
_required_ = 'required'
|
|
42
|
+
_below_ = 'below'
|
|
43
|
+
_list_tuple_types = (list, tuple)
|
|
44
|
+
_required_ = 'required'
|
|
47
45
|
|
|
48
46
|
try: # Luciano Ramalho, "Fluent Python", O'Reilly, 2016 p. 395, 2022 p. 577+
|
|
49
47
|
from numbers import Integral as _Ints, Real as _Scalars # .units
|
|
@@ -113,28 +111,29 @@ except NameError: # Python 3+
|
|
|
113
111
|
return ub
|
|
114
112
|
|
|
115
113
|
|
|
116
|
-
def _args_kwds_count2(func, exelf=True):
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
114
|
+
# def _args_kwds_count2(func, exelf=True): # in .formy
|
|
115
|
+
# '''(INTERNAL) Get a C{func}'s args and kwds count as 2-tuple
|
|
116
|
+
# C{(nargs, nkwds)}, including arg C{self} for methods.
|
|
117
|
+
#
|
|
118
|
+
# @kwarg exelf: If C{True}, exclude C{self} in the C{args}
|
|
119
|
+
# of a method (C{bool}).
|
|
120
|
+
# '''
|
|
121
|
+
# i = _MODS.inspect
|
|
122
|
+
# try:
|
|
123
|
+
# a = k = 0
|
|
124
|
+
# for _, p in i.signature(func).parameters.items():
|
|
125
|
+
# if p.kind is p.POSITIONAL_OR_KEYWORD:
|
|
126
|
+
# if p.default is p.empty:
|
|
127
|
+
# a += 1
|
|
128
|
+
# else:
|
|
129
|
+
# k += 1
|
|
130
|
+
# except AttributeError: # Python 2-
|
|
131
|
+
# s = i.getargspec(func)
|
|
132
|
+
# k = len(s.defaults or ())
|
|
133
|
+
# a = len(s.args) - k
|
|
134
|
+
# if exelf and a > 0 and i.ismethod(func):
|
|
135
|
+
# a -= 1
|
|
136
|
+
# return a, k
|
|
138
137
|
|
|
139
138
|
|
|
140
139
|
def _args_kwds_names(func, splast=False):
|
|
@@ -147,10 +146,11 @@ def _args_kwds_names(func, splast=False):
|
|
|
147
146
|
@note: Python 2 may I{not} include the C{*args} nor the
|
|
148
147
|
C{**kwds} names.
|
|
149
148
|
'''
|
|
149
|
+
i = _MODS.inspect
|
|
150
150
|
try:
|
|
151
|
-
args_kwds =
|
|
152
|
-
except AttributeError: #
|
|
153
|
-
args_kwds =
|
|
151
|
+
args_kwds = i.signature(func).parameters.keys()
|
|
152
|
+
except AttributeError: # Python 2-
|
|
153
|
+
args_kwds = i.getargspec(func).args
|
|
154
154
|
if splast and args_kwds: # PYCHOK no cover
|
|
155
155
|
args_kwds = list(args_kwds)
|
|
156
156
|
t = args_kwds[-1:]
|
|
@@ -222,7 +222,7 @@ def halfs2(str2):
|
|
|
222
222
|
return str2[:h], str2[h:]
|
|
223
223
|
|
|
224
224
|
|
|
225
|
-
def int1s(x):
|
|
225
|
+
def int1s(x): # PYCHOK no cover
|
|
226
226
|
'''Count the number of 1-bits in an C{int}, I{unsigned}.
|
|
227
227
|
|
|
228
228
|
@note: C{int1s(-B{x}) == int1s(abs(B{x}))}.
|
|
@@ -266,14 +266,10 @@ def isCartesian(obj, ellipsoidal=None):
|
|
|
266
266
|
return isinstanceof(obj, _MODS.cartesianBase.CartesianBase)
|
|
267
267
|
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
'''
|
|
274
|
-
return _inspect.isclass(obj)
|
|
275
|
-
else:
|
|
276
|
-
isclass = _inspect.isclass
|
|
269
|
+
def isclass(obj): # XXX avoid epydoc Python 2.7 error
|
|
270
|
+
'''Is B{C{obj}}ect a C{Class} or C{type}?
|
|
271
|
+
'''
|
|
272
|
+
return _MODS.inspect.isclass(obj)
|
|
277
273
|
|
|
278
274
|
|
|
279
275
|
def iscomplex(obj, both=False):
|
|
@@ -511,7 +507,7 @@ def issubclassof(Sub, *Supers):
|
|
|
511
507
|
if isclass(Sub):
|
|
512
508
|
t = tuple(S for S in Supers if isclass(S))
|
|
513
509
|
if t:
|
|
514
|
-
return bool(issubclass(Sub, t))
|
|
510
|
+
return bool(issubclass(Sub, t)) # built-in
|
|
515
511
|
return None
|
|
516
512
|
|
|
517
513
|
|
|
@@ -711,9 +707,9 @@ def splice(iterable, n=2, **fill):
|
|
|
711
707
|
yield t # 1 slice, all
|
|
712
708
|
|
|
713
709
|
|
|
714
|
-
def _splituple(strs, *sep_splits): # in .mgrs,
|
|
710
|
+
def _splituple(strs, *sep_splits): # in .mgrs, ...
|
|
715
711
|
'''(INTERNAL) Split a C{comma}- or C{whitespace}-separated
|
|
716
|
-
string into a C{tuple} of stripped
|
|
712
|
+
string into a C{tuple} of stripped C{str}ings.
|
|
717
713
|
'''
|
|
718
714
|
t = (strs.split(*sep_splits) if sep_splits else
|
|
719
715
|
strs.replace(_COMMA_, _SPACE_).split()) if strs else ()
|
|
@@ -740,11 +736,11 @@ def _xcopy(obj, deep=False):
|
|
|
740
736
|
return _deepcopy(obj) if deep else _copy(obj)
|
|
741
737
|
|
|
742
738
|
|
|
743
|
-
def _xcoverage(where, *required):
|
|
739
|
+
def _xcoverage(where, *required): # in .__main__ # PYCHOK no cover
|
|
744
740
|
'''(INTERNAL) Import C{coverage} and check required version.
|
|
745
741
|
'''
|
|
746
742
|
try:
|
|
747
|
-
|
|
743
|
+
_xpackages(_xcoverage)
|
|
748
744
|
import coverage
|
|
749
745
|
except ImportError as x:
|
|
750
746
|
raise _xImportError(x, where)
|
|
@@ -780,7 +776,7 @@ def _xgeographiclib(where, *required):
|
|
|
780
776
|
'''(INTERNAL) Import C{geographiclib} and check required version.
|
|
781
777
|
'''
|
|
782
778
|
try:
|
|
783
|
-
|
|
779
|
+
_xpackages(_xgeographiclib)
|
|
784
780
|
import geographiclib
|
|
785
781
|
except ImportError as x:
|
|
786
782
|
raise _xImportError(x, where, Error=LazyImportError)
|
|
@@ -828,7 +824,7 @@ def _xiterablen(obj):
|
|
|
828
824
|
def _xiterror(obj, _xwhich):
|
|
829
825
|
'''(INTERNAL) Helper for C{_xinterable} and C{_xiterablen}.
|
|
830
826
|
'''
|
|
831
|
-
t = _not_(_xwhich.__name__[2:]) #
|
|
827
|
+
t = _not_(_xwhich.__name__[2:]) # _DUNDER_nameof
|
|
832
828
|
raise _TypeError(repr(obj), txt=t)
|
|
833
829
|
|
|
834
830
|
|
|
@@ -836,7 +832,7 @@ def _xnumpy(where, *required):
|
|
|
836
832
|
'''(INTERNAL) Import C{numpy} and check required version.
|
|
837
833
|
'''
|
|
838
834
|
try:
|
|
839
|
-
|
|
835
|
+
_xpackages(_xnumpy)
|
|
840
836
|
import numpy
|
|
841
837
|
except ImportError as x:
|
|
842
838
|
raise _xImportError(x, where)
|
|
@@ -851,14 +847,16 @@ def _xor(x, *xs):
|
|
|
851
847
|
return x
|
|
852
848
|
|
|
853
849
|
|
|
854
|
-
def
|
|
850
|
+
def _xpackages(_xpkgf):
|
|
855
851
|
'''(INTERNAL) Check dependency to be excluded.
|
|
856
852
|
'''
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
853
|
+
if _XPACKAGES: # PYCHOK no cover
|
|
854
|
+
n = _xpkgf.__name__[2:] # _DUNDER_nameof, less '_x'
|
|
855
|
+
if n.lower() in _XPACKAGES:
|
|
856
|
+
E = _PYGEODESY(_xpackages)
|
|
857
|
+
x = _SPACE_(n, _in_, E)
|
|
858
|
+
e = _enquote(_getenv(E, NN))
|
|
859
|
+
raise ImportError(_EQUAL_(x, e))
|
|
862
860
|
|
|
863
861
|
|
|
864
862
|
def _xscalar(**names_values):
|
|
@@ -873,7 +871,7 @@ def _xscipy(where, *required):
|
|
|
873
871
|
'''(INTERNAL) Import C{scipy} and check required version.
|
|
874
872
|
'''
|
|
875
873
|
try:
|
|
876
|
-
|
|
874
|
+
_xpackages(_xscipy)
|
|
877
875
|
import scipy
|
|
878
876
|
except ImportError as x:
|
|
879
877
|
raise _xImportError(x, where)
|
|
@@ -905,7 +903,7 @@ def _xversion(package, where, *required, **name):
|
|
|
905
903
|
if required:
|
|
906
904
|
t = _version_info(package)
|
|
907
905
|
if t[:len(required)] < required:
|
|
908
|
-
t = _SPACE_(package.__name__, #
|
|
906
|
+
t = _SPACE_(package.__name__, # _DUNDER_nameof
|
|
909
907
|
_version_, _DOT_(*t),
|
|
910
908
|
_below_, _DOT_(*required),
|
|
911
909
|
_req_d_by(where, **name))
|
|
@@ -925,14 +923,14 @@ def _xzip(*args, **strict): # PYCHOK no cover
|
|
|
925
923
|
return zip(*args)
|
|
926
924
|
|
|
927
925
|
|
|
928
|
-
if
|
|
926
|
+
if _MODS.sys_version_info2 < (3, 10): # see .errors
|
|
929
927
|
_zip = zip # PYCHOK exported
|
|
930
928
|
else: # Python 3.10+
|
|
931
929
|
|
|
932
930
|
def _zip(*args):
|
|
933
931
|
return zip(*args, strict=True)
|
|
934
932
|
|
|
935
|
-
_XPACKAGES = _splituple(_getenv(
|
|
933
|
+
_XPACKAGES = _splituple(_getenv(_PYGEODESY(_xpackages), NN).lower()) # test/bases._X_OK
|
|
936
934
|
|
|
937
935
|
# **) MIT License
|
|
938
936
|
#
|