File: _config.py

package info (click to toggle)
python-geopandas 1.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,752 kB
  • sloc: python: 26,021; makefile: 147; sh: 25
file content (133 lines) | stat: -rw-r--r-- 3,866 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
Lightweight options machinery.

Based on https://github.com/topper-123/optioneer, but simplified (don't deal
with nested options, deprecated options, ..), just the attribute-style dict
like holding the options and giving a nice repr.
"""

import textwrap
import warnings
from collections import namedtuple

Option = namedtuple("Option", "key default_value doc validator callback")


class Options:
    """Provide attribute-style access to configuration dict."""

    def __init__(self, options):
        super().__setattr__("_options", options)
        # populate with default values
        config = {}
        for key, option in options.items():
            config[key] = option.default_value

        super().__setattr__("_config", config)

    def __setattr__(self, key, value):
        # you can't set new keys
        if key in self._config:
            option = self._options[key]
            if option.validator:
                option.validator(value)
            self._config[key] = value
            if option.callback:
                option.callback(key, value)
        else:
            msg = "You can only set the value of existing options"
            raise AttributeError(msg)

    def __getattr__(self, key):
        try:
            return self._config[key]
        except KeyError:
            raise AttributeError("No such option")

    def __dir__(self):
        return list(self._config.keys())

    def __repr__(self):
        cls = self.__class__.__name__
        description = ""
        for key, option in self._options.items():
            descr = (
                f"{key}: {self._config[key]!r} [default: {option.default_value!r}]\n"
            )
            description += descr

            if option.doc:
                doc_text = "\n".join(textwrap.wrap(option.doc, width=70))
            else:
                doc_text = "No description available."
            doc_text = textwrap.indent(doc_text, prefix="    ")
            description += doc_text + "\n"
        space = "\n  "
        description = description.replace("\n", space)
        return f"{cls}({space}{description})"


def _validate_display_precision(value):
    if value is not None:
        if not isinstance(value, int) or not (0 <= value <= 16):
            raise ValueError("Invalid value, needs to be an integer [0-16]")


display_precision = Option(
    key="display_precision",
    default_value=None,
    doc=(
        "The precision (maximum number of decimals) of the coordinates in "
        "the WKT representation in the Series/DataFrame display. "
        "By default (None), it tries to infer and use 3 decimals for projected "
        "coordinates and 5 decimals for geographic coordinates."
    ),
    validator=_validate_display_precision,
    callback=None,
)


def _warn_use_pygeos_deprecated(_value):
    warnings.warn(
        "pygeos support was removed in 1.0. "
        "geopandas.use_pygeos is a no-op and will be removed in geopandas 1.1.",
        stacklevel=3,
    )


def _validate_io_engine(value):
    if value is not None:
        if value not in ("pyogrio", "fiona"):
            raise ValueError(f"Expected 'pyogrio' or 'fiona', got '{value}'")


io_engine = Option(
    key="io_engine",
    default_value=None,
    doc=(
        "The default engine for ``read_file`` and ``to_file``. "
        "Options are 'pyogrio' and 'fiona'."
    ),
    validator=_validate_io_engine,
    callback=None,
)

# TODO: deprecate this
use_pygeos = Option(
    key="use_pygeos",
    default_value=False,
    doc=(
        "Deprecated option previously used to enable PyGEOS. "
        "It will be removed in GeoPandas 1.1."
    ),
    validator=_warn_use_pygeos_deprecated,
    callback=None,
)

options = Options(
    {
        "display_precision": display_precision,
        "use_pygeos": use_pygeos,
        "io_engine": io_engine,
    }
)