File: compatibility.py

package info (click to toggle)
plotly 5.4.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 90,200 kB
  • sloc: python: 368,793; javascript: 213,159; sh: 49; makefile: 4
file content (211 lines) | stat: -rw-r--r-- 6,812 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
from io import StringIO
from os import path as opath

from codegen.utils import write_source_py

# Build dict with info about deprecated datatypes
DEPRECATED_DATATYPES = {
    # List types
    "Data": {"base_type": list, "new": ["Scatter", "Bar", "Area", "Histogram", "etc."]},
    "Annotations": {
        "base_type": list,
        "new": ["layout.Annotation", "layout.scene.Annotation"],
    },
    "Frames": {"base_type": list, "new": ["Frame"]},
    # Dict types
    "AngularAxis": {"base_type": dict, "new": ["layout", "layout.polar"]},
    "Annotation": {"base_type": dict, "new": ["layout", "layout.scene"]},
    "ColorBar": {"base_type": dict, "new": ["scatter.marker", "surface", "etc."]},
    "Contours": {"base_type": dict, "new": ["contour", "surface", "etc."]},
    "ErrorX": {"base_type": dict, "new": ["scatter", "histogram", "etc."]},
    "ErrorY": {"base_type": dict, "new": ["scatter", "histogram", "etc."]},
    "ErrorZ": {"base_type": dict, "new": ["scatter3d"]},
    "Font": {"base_type": dict, "new": ["layout", "layout.hoverlabel", "etc."]},
    "Legend": {"base_type": dict, "new": ["layout"]},
    "Line": {"base_type": dict, "new": ["scatter", "layout.shape", "etc."]},
    "Margin": {"base_type": dict, "new": ["layout"]},
    "Marker": {"base_type": dict, "new": ["scatter", "histogram.selected", "etc."]},
    "RadialAxis": {"base_type": dict, "new": ["layout", "layout.polar"]},
    "Scene": {"base_type": dict, "new": ["layout"]},
    "Stream": {"base_type": dict, "new": ["scatter", "area"]},
    "XAxis": {"base_type": dict, "new": ["layout", "layout.scene"]},
    "YAxis": {"base_type": dict, "new": ["layout", "layout.scene"]},
    "ZAxis": {"base_type": dict, "new": ["layout.scene"]},
    "XBins": {"base_type": dict, "new": ["histogram", "histogram2d"]},
    "YBins": {"base_type": dict, "new": ["histogram", "histogram2d"]},
    "Trace": {
        "base_type": dict,
        "new": ["Scatter", "Bar", "Area", "Histogram", "etc."],
    },
    "Histogram2dcontour": {"base_type": dict, "new": ["Histogram2dContour"]},
}


def build_deprecated_datatypes_py():
    """
    Build datatype (graph_objs) class source code string for deprecated
    datatypes

    Returns
    -------
    str
    """

    # Initialize source code buffer
    # -----------------------------
    buffer = StringIO()

    # Write warnings import
    # ---------------------
    buffer.write("import warnings\n")

    # Write warnings filter
    # ---------------------
    # Use filter to enable DeprecationWarnings on our deprecated classes
    buffer.write(
        r"""
warnings.filterwarnings('default',
                        r'plotly\.graph_objs\.\w+ is deprecated',
                        DeprecationWarning)


"""
    )

    # Write deprecated class definitions
    # ----------------------------------
    for class_name, opts in DEPRECATED_DATATYPES.items():
        base_class_name = opts["base_type"].__name__
        depr_msg = build_deprecation_message(class_name, **opts)

        buffer.write(
            f"""\
class {class_name}({base_class_name}):
    \"\"\"
    {depr_msg}
    \"\"\"
    def __init__(self, *args, **kwargs):
        \"\"\"
        {depr_msg}
        \"\"\"
        warnings.warn(\"\"\"{depr_msg}\"\"\", DeprecationWarning)
        super({class_name}, self).__init__(*args, **kwargs)\n\n\n"""
        )

    # Return source string
    # --------------------
    return buffer.getvalue()


def build_deprecation_message(class_name, base_type, new):
    """
    Build deprecation warning message for a deprecated class

    Parameters
    ----------
    class_name : str
        Name of a deprecated class
    base_type: type
        base class (either list or dict)
    new: list of str
        List of replacements that users should use instead.
        Replacements may be:
            - A package string relative to plotly.graph_objs. In this case the
              replacement class is assumed to be named `class_name`.
              e.g. `new` == ['layout`] and `class_name` == 'XAxis` corresponds
              to the 'plotly.graph_objs.layout.XAxis' class
            - String containing the package and class. The string is
              identified as containing a class name if the final name in the
              package string begins with an uppercase letter.
              e.g. `new` == ['Scatter'] corresponds to the
              ['plotly.graph_objs.Scatter'] class.
            - The literal string 'etc.'. This string is not interpreted as a
              package or class and is displayed to the user as-is to
              indicate that the list of replacement classes is not complete.

    Returns
    -------
    str
    """
    replacements = []
    for repl in new:

        if repl == "etc.":
            replacements.append(repl)
        else:
            repl_parts = repl.split(".")

            # Add class_name if class not provided
            repl_is_class = repl_parts[-1][0].isupper()
            if not repl_is_class:
                repl_parts.append(class_name)

            # Add plotly.graph_objs prefix
            full_class_str = ".".join(["plotly", "graph_objs"] + repl_parts)
            replacements.append(full_class_str)

    replacemens_str = "\n  - ".join(replacements)

    if base_type == list:
        return f"""\
plotly.graph_objs.{class_name} is deprecated.
Please replace it with a list or tuple of instances of the following types
  - {replacemens_str}
"""
    else:
        return f"""\
plotly.graph_objs.{class_name} is deprecated.
Please replace it with one of the following more specific types
  - {replacemens_str}
"""


def write_deprecated_datatypes(outdir):
    """
    Build source code for deprecated datatype class definitions and write
    them to a file

    Parameters
    ----------
    outdir :
        Root outdir in which the graph_objs package should reside

    Returns
    -------
    None
    """
    # Generate source code
    # --------------------
    datatype_source = build_deprecated_datatypes_py()
    filepath = opath.join(outdir, "graph_objs", "_deprecations.py")

    # Write file
    # ----------
    write_source_py(datatype_source, filepath)


def write_graph_objs_graph_objs(outdir):
    """
    Write the plotly/graph_objs/graph_objs.py file

    This module just imports everything from the plotly.graph_objs package.
    We write it for backward compatibility with legacy imports like:

    from plotly.graph_objs import graph_objs

    Parameters
    ----------
    outdir : str
        Root outdir in which the graph_objs package should reside

    Returns
    -------
    None
    """
    filepath = opath.join(outdir, "graph_objs", "graph_objs.py")
    with open(filepath, "wt") as f:
        f.write(
            """\
from plotly.graph_objs import *
"""
        )