Ejemplo n.º 1
0
def callername(up=1, dflt=NN, source=False):
    '''Get the name of the calling callable.

       @kwarg up: Number of call stack frames up (C{int}).
       @kwarg dflt: Default return value (C{any}).
       @kwarg source: Include source file name and line
                      number (C{bool}).

       @return: Name of the non-internal callable (C{str})
                or B{C{dflt}} if none found.
    '''
    try:
        from sys import _getframe
        for u in range(up, up + 32):
            f = _getframe(u)
            n = f.f_code.co_name
            if n and (n.startswith(_DUNDER_)
                      or not n.startswith(_UNDERSCORE_)):
                if source:
                    from os.path import basename
                    n = NN.join(
                        (n, _AT_, basename(f.f_code.co_filename), _COLON_,
                         str(f.f_lineno)))
                return n
    except (AttributeError, ImportError):
        pass
    return dflt
Ejemplo n.º 2
0
def encode(lat, lon, precision=3, height=None, radius=None):  # MCCABE 14
    '''Encode a lat-/longitude as a C{georef} of the given precision.

       @arg lat: Latitude (C{degrees}).
       @arg lon: Longitude (C{degrees}).
       @kwarg precision: Optional, the desired C{georef} resolution and length
                         (C{int} 0..11).
       @kwarg height: Optional, height in C{meter}, see U{Designation of area
                      <https://WikiPedia.org/wiki/World_Geographic_Reference_System>}.
       @kwarg radius: Optional, radius in C{meter}, see U{Designation of area
                      <https://WikiPedia.org/wiki/World_Geographic_Reference_System>}.

       @return: The C{georef} (C{str}).

       @raise RangeError: Invalid B{C{lat}} or B{C{lon}}.

       @raise WGRSError: Invalid B{C{precision}}, B{C{height}} or B{C{radius}}.

       @note: The B{C{precision}} value differs from U{Georef<https://
              GeographicLib.SourceForge.io/html/classGeographicLib_1_1Georef.html>}.
              The C{georef} length is M{2 * (precision + 1)} and the
              C{georef} resolution is I{15°} for B{C{precision}} 0, I{1°}
              for 1, I{1′} for 2, I{0.1′} for 3, I{0.01′} for 4, ...
              M{10**(2 - precision)}.
    '''
    def _option(name, m, m2_, K):
        f = Scalar_(m, name=name, Error=WGRSError)
        return '%s%d' % (name[0].upper(), int(m2_(f * K) + 0.5))

    def _pstr(p, x):
        return '%0*d' % (p, x)

    p = _2Precision(precision)

    lat, lon, _ = _2fllh(lat, lon)
    if lat == 90:
        lat *= EPS1_2

    xt, xd, x = _2divmod3(lon, _LonOrig_M_)
    yt, yd, y = _2divmod3(lat, _LatOrig_M_)

    g = _LonTile[xt], _LatTile[yt]
    if p > 0:
        g += _DegChar[xd], _DegChar[yd]
        p -= 1
        if p > 0:
            d = pow(_Base, _MaxPrec - p)
            x = _pstr(p, x // d)
            y = _pstr(p, y // d)
            g += x, y

    if radius is not None:  # R before H
        g += _option(_radius_, radius, m2NM, 1.0),
    if height is not None:  # H is last
        g += _option(_height_, height, m2ft, 1e-3),

    return NN.join(g)  # XXX Georef(''.join(g))
Ejemplo n.º 3
0
    def _DDDMMSS_(strDDDMMSS, suffix, sep, clip):
        S = suffix.upper()
        if isstr(strDDDMMSS):
            t = strDDDMMSS.strip()
            if sep:
                t = t.replace(sep, NN).strip()

            s = t[:1]  # sign or digit
            P = t[-1:]  # compass point, digit or dot

            t = t.lstrip(_PLUSMINUS_).rstrip(S).strip()
            f = t.split(_DOT_)
            d = len(f[0])
            f = NN.join(f)
            if 1 < d < 8 and f.isdigit() and (
                (P in S and s.isdigit()) or
                (P.isdigit() and s in '-0123456789+'  # PYCHOK indent
                 and S in ((_NS_, _EW_) + _WINDS))):
                # check [D]DDMMSS form and compass point
                X = _EW_ if (d & 1) else _NS_
                if not (P in X or (S in X and (P.isdigit() or P == _DOT_))):
                    t = 'DDDMMSS'[d & 1 ^ 1:d | 1], X[:1], X[1:]
                    raise ParseError('form %s applies %s-%s' % t)
                f = 0  # fraction
            else:  # try other forms
                return _DMS2deg(strDDDMMSS, S, sep, clip)

        else:  # float or int to [D]DDMMSS[.fff]
            f = float(strDDDMMSS)
            s = _MINUS_ if f < 0 else NN
            P = _0_  # anything except _SW_
            f, i = modf(abs(f))
            t = Fmt.f(i, prec=0)  # str(i) == 'i.0'
            d = len(t)
            # bump number of digits to match
            # the given, valid compass point
            if S in (_NS_ if (d & 1) else _EW_):
                t = _0_ + t
                d += 1
            #   P = S
            # elif d > 1:
            #   P = (_EW_ if (d & 1) else _NS_)[0]

        if d < 4:  # [D]DD[.ddd]
            if f:
                t = float(t) + f
            t = t, 0, 0
        else:
            f += float(t[d - 2:])
            if d < 6:  # [D]DDMM[.mmm]
                t = t[:d - 2], f, 0
            else:  # [D]DDMMSS[.sss]
                t = t[:d - 4], t[d - 4:d - 2], f
        d = _dms2deg(s, P, *map2(float, t))

        return clipDegrees(d, float(clip)) if clip else d
Ejemplo n.º 4
0
def encode(lat, lon, precision=1):  # MCCABE 14
    '''Encode a lat-/longitude as a C{garef} of the given precision.

       @arg lat: Latitude (C{degrees}).
       @arg lon: Longitude (C{degrees}).
       @kwarg precision: Optional, the desired C{garef} resolution
                         and length (C{int} 0..2).

       @return: The C{garef} (C{str}).

       @raise RangeError: Invalid B{C{lat}} or B{C{lon}}.

       @raise GARSError: Invalid B{C{precision}}.

       @note: The C{garef} length is M{precision + 5} and the C{garef}
              resolution is B{30′} for B{C{precision}} 0, B{15′} for 1
              and B{5′} for 2, respectively.
    '''
    def _digit(x, y, m):
        return _Digits[m * (m - y - 1) + x + 1],

    def _str(chars, x, n):
        s, b = [], len(chars)
        for i in range(n):
            x, i = divmod(x, b)
            s.append(chars[i])
        return tuple(reversed(s))

    p = _2Precision(precision)

    lat, lon = _2fll(lat, lon)
    if lat == 90:
        lat *= EPS1_2

    ix, x = _2divmod2(lon, _LonOrig_M_)
    iy, y = _2divmod2(lat, _LatOrig_M_)

    g = _str(_Digits, ix + 1, _LonLen) + _str(_Letters, iy, _LatLen)
    if p > 0:
        ix, x = divmod(x, _M3)
        iy, y = divmod(y, _M3)
        g += _digit(ix, iy, _M2)
        if p > 1:
            g += _digit(x, y, _M3)

    return NN.join(g)
Ejemplo n.º 5
0
def _error_init(Error,
                inst,
                name_value,
                fmt_name_value='%s (%r)',
                txt=_invalid_,
                **name_values):  # by .lazily
    '''(INTERNAL) Format an error text and initialize an C{Error} instance.

       @arg Error: The error super-class (C{Exception}).
       @arg inst: Sub-class instance to be initialized (C{_Exception}).
       @arg name_value: Either just a value or several name, value, ...
                        positional arguments (C{str}, any C{type}), in
                        particular for name conflicts with keyword
                        arguments of C{error_init} or which can't be
                        used as C{name=value} keyword arguments.
       @kwarg name_value_fmt: Format for (name, value) (C{str}).
       @kwarg txt: Optional explanation of the error (C{str}).
       @kwarg name_values: One or more B{C{name=value}} pairs overriding
                           any B{C{name_value}} positional arguments.
    '''
    if name_values:
        t = _or(*(fmt_name_value % t
                  for t in name_values.items()))  # XXX sorted
    elif len(name_value) > 1:
        t = _or(*(fmt_name_value % t
                  for t in zip(name_value[0::2], name_value[1::2])))
    elif name_value:
        t = str(name_value[0])
    else:
        t = '%s %s' % (_Missing, _Missing)

    if txt is None:
        x = NN
    else:
        x = str(txt) or _invalid_
        c = _COMMA_ if _COLON_ in t else _COLON_
        t = NN.join((t, c, _SPACE_, x))
    Error.__init__(inst, t)
    #   inst.__x_txt__ = x  # hold explanation
    _cause_(inst)  # no Python 3+ exception chaining
    _ename_(inst)
Ejemplo n.º 6
0
def callername(up=1, dflt=NN, source=False):
    '''Get the name of the calling callable.

       @kwarg up: Number of call stack frames up (C{int}).
       @kwarg dflt: Default return value (C{any}).
       @kwarg source: Include source file name and line
                      number (C{bool}).

       @return: Name of the non-internal callable (C{str})
                or B{C{dflt}} if none found.
    '''
    try:  # see .lazily._caller3
        for u in range(up, up + 32):
            n, f, s = _caller3(u)
            if n and (n.startswith(_DUNDER_)
                      or not n.startswith(_UNDERSCORE_)):
                if source:
                    n = NN.join((n, _AT_, f, _COLON_, str(s)))
                return n
    except (AttributeError, ValueError):  # PYCHOK no cover
        pass
    return dflt
Ejemplo n.º 7
0
def _toDMS(deg, form, prec, sep, ddd, suff):  # MCCABE 15 by .units.py
    '''(INTERNAL) Convert degrees to C{str}, with/-out sign and/or suffix.
    '''
    try:
        deg = float(deg)
    except (TypeError, ValueError) as x:
        raise _ValueError(deg=deg, txt=str(x))

    form = form.lower()
    sign = form[:1]
    if sign in _MINUS_PLUS_:
        form = form[1:]
    else:
        sign = S_NUL

    if prec is None:
        z = p = _F_prec.get(form, 6)
    else:
        z = int(prec)
        p = abs(z)
    w = p + (1 if p else 0)
    d = abs(deg)

    if form in _F_symb:
        s_deg = s_min = s_sec = S_NUL  # no symbols
    else:
        s_deg, s_min, s_sec = S_DEG, S_MIN, S_SEC

    F = _F_case.get(form, F_DMS)
    if F is F_DMS:  # 'deg+min+sec'
        d, s = divmod(round(d * 3600, p), 3600)
        m, s = divmod(s, 60)
        t = NN.join((_0wpF(ddd, 0, d), s_deg, sep, _0wpF(2, 0, m), s_min, sep,
                     _0wpF(w + 2, p, s)))
        s = s_sec

    elif F is F_DM:  # 'deg+min'
        d, m = divmod(round(d * 60, p), 60)
        t = NN.join((_0wpF(ddd, 0, d), s_deg, sep, _0wpF(w + 2, p, m)))
        s = s_min

    elif F is F_D:  # 'deg'
        t = _0wpF(ddd + w, p, d)
        s = s_deg

    elif F is F_RAD:
        t = '%.*F' % (p, radians(d))
        s = S_RAD

    else:  # F in (F__E, F__F, F__G)
        t = ('%.*' + F) % (p, d)
        s = S_NUL

    if z > 1:
        t = fstrzs(t, ap1z=F is F__G)

    if sign:
        if deg < 0:
            t = _MINUS_ + t
        elif deg > 0 and sign == _PLUS_:
            t = _PLUS_ + t
    elif suff:  # and deg:  # zero suffix?
        s += sep + suff
    return t + s