tidy3 0.3.0__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.
- tidy3/__init__.py +407 -0
- tidy3/__main__.py +141 -0
- tidy3/__version__.py +1 -0
- tidy3/bench.py +359 -0
- tidy3/bench_suite.py +797 -0
- tidy3/craft.py +169 -0
- tidy3/display.py +149 -0
- tidy3/eda.py +327 -0
- tidy3/export.py +519 -0
- tidy3/expr.py +684 -0
- tidy3/frame.py +1348 -0
- tidy3/io.py +25 -0
- tidy3/join_spec.py +182 -0
- tidy3/jupyter.py +561 -0
- tidy3/masking.py +867 -0
- tidy3/options.py +31 -0
- tidy3/pandas_engine.py +1420 -0
- tidy3/partial_run.py +411 -0
- tidy3/plot3_bridge.py +19 -0
- tidy3/py.typed +0 -0
- tidy3/tidyr.py +1567 -0
- tidy3/tidyselect.py +818 -0
- tidy3/verbs.py +4152 -0
- tidy3-0.3.0.dist-info/METADATA +1239 -0
- tidy3-0.3.0.dist-info/RECORD +28 -0
- tidy3-0.3.0.dist-info/WHEEL +5 -0
- tidy3-0.3.0.dist-info/licenses/LICENSE +21 -0
- tidy3-0.3.0.dist-info/top_level.txt +1 -0
tidy3/__init__.py
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"""tidy3 — dplyr-style lazy data manipulation on Polars."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from tidy3.expr import (
|
|
6
|
+
all,
|
|
7
|
+
any,
|
|
8
|
+
between_values,
|
|
9
|
+
case_when,
|
|
10
|
+
case_match,
|
|
11
|
+
coalesce,
|
|
12
|
+
col,
|
|
13
|
+
consecutive_id,
|
|
14
|
+
cumall,
|
|
15
|
+
cumany,
|
|
16
|
+
cume_dist,
|
|
17
|
+
cummean,
|
|
18
|
+
dense_rank,
|
|
19
|
+
desc,
|
|
20
|
+
first,
|
|
21
|
+
if_else,
|
|
22
|
+
lag,
|
|
23
|
+
last,
|
|
24
|
+
lead,
|
|
25
|
+
max,
|
|
26
|
+
mean,
|
|
27
|
+
median,
|
|
28
|
+
min,
|
|
29
|
+
min_rank,
|
|
30
|
+
na_if,
|
|
31
|
+
n,
|
|
32
|
+
n_distinct,
|
|
33
|
+
near,
|
|
34
|
+
nth,
|
|
35
|
+
ntile,
|
|
36
|
+
percent_rank,
|
|
37
|
+
row_number,
|
|
38
|
+
recode,
|
|
39
|
+
sd,
|
|
40
|
+
std,
|
|
41
|
+
var,
|
|
42
|
+
)
|
|
43
|
+
from tidy3.expr import sum as sum # noqa: A001
|
|
44
|
+
from tidy3.eda import colnames, describe, dim, dtypes, names, ncol, nrow, summary
|
|
45
|
+
from tidy3.frame import TidyFrame, options, tidy
|
|
46
|
+
from tidy3.io import scan_csv, scan_ipc, scan_parquet
|
|
47
|
+
from tidy3.join_spec import (
|
|
48
|
+
JoinCondition,
|
|
49
|
+
JoinSpec,
|
|
50
|
+
between,
|
|
51
|
+
closest,
|
|
52
|
+
eq,
|
|
53
|
+
ge,
|
|
54
|
+
gt,
|
|
55
|
+
join_by,
|
|
56
|
+
le,
|
|
57
|
+
lt,
|
|
58
|
+
overlaps,
|
|
59
|
+
within,
|
|
60
|
+
)
|
|
61
|
+
from tidy3.export import (
|
|
62
|
+
ExportResult,
|
|
63
|
+
collect_known_names,
|
|
64
|
+
nb_export,
|
|
65
|
+
transform_cell,
|
|
66
|
+
transform_source,
|
|
67
|
+
)
|
|
68
|
+
from tidy3.partial_run import (
|
|
69
|
+
looks_like_tidy_pipe,
|
|
70
|
+
maybe_rewrite_cell,
|
|
71
|
+
normalize_pipe_source,
|
|
72
|
+
partial_run,
|
|
73
|
+
)
|
|
74
|
+
from tidy3.tidyselect import (
|
|
75
|
+
Selector,
|
|
76
|
+
across,
|
|
77
|
+
all_of,
|
|
78
|
+
any_of,
|
|
79
|
+
c_across,
|
|
80
|
+
col_range,
|
|
81
|
+
cols_between,
|
|
82
|
+
contains,
|
|
83
|
+
cur_column,
|
|
84
|
+
cur_group,
|
|
85
|
+
cur_group_id,
|
|
86
|
+
cur_group_rows,
|
|
87
|
+
ends_with,
|
|
88
|
+
everything,
|
|
89
|
+
group_cols,
|
|
90
|
+
group_vars,
|
|
91
|
+
n_groups,
|
|
92
|
+
if_all,
|
|
93
|
+
if_any,
|
|
94
|
+
is_bool,
|
|
95
|
+
is_boolean,
|
|
96
|
+
is_categorical,
|
|
97
|
+
is_character,
|
|
98
|
+
is_datetime,
|
|
99
|
+
is_float,
|
|
100
|
+
is_integer,
|
|
101
|
+
is_numeric,
|
|
102
|
+
is_string,
|
|
103
|
+
is_temporal,
|
|
104
|
+
last_col,
|
|
105
|
+
matches,
|
|
106
|
+
num_range,
|
|
107
|
+
pick,
|
|
108
|
+
starts_with,
|
|
109
|
+
where,
|
|
110
|
+
)
|
|
111
|
+
from tidy3.tidyr import (
|
|
112
|
+
complete,
|
|
113
|
+
drop_na,
|
|
114
|
+
expand,
|
|
115
|
+
fill,
|
|
116
|
+
hoist,
|
|
117
|
+
nest,
|
|
118
|
+
nesting,
|
|
119
|
+
pivot_longer,
|
|
120
|
+
pivot_wider,
|
|
121
|
+
replace_na,
|
|
122
|
+
separate,
|
|
123
|
+
separate_longer_delim,
|
|
124
|
+
separate_wider_delim,
|
|
125
|
+
unite,
|
|
126
|
+
unnest,
|
|
127
|
+
unnest_longer,
|
|
128
|
+
unnest_wider,
|
|
129
|
+
pack,
|
|
130
|
+
unpack,
|
|
131
|
+
)
|
|
132
|
+
from tidy3.verbs import (
|
|
133
|
+
add_count,
|
|
134
|
+
add_tally,
|
|
135
|
+
anti_join,
|
|
136
|
+
arrange,
|
|
137
|
+
bind_cols,
|
|
138
|
+
bind_rows,
|
|
139
|
+
collect,
|
|
140
|
+
count,
|
|
141
|
+
cross_join,
|
|
142
|
+
distinct,
|
|
143
|
+
drop,
|
|
144
|
+
filter,
|
|
145
|
+
filter_out,
|
|
146
|
+
full_join,
|
|
147
|
+
glimpse,
|
|
148
|
+
group_by,
|
|
149
|
+
group_map,
|
|
150
|
+
group_modify,
|
|
151
|
+
group_nest,
|
|
152
|
+
group_split,
|
|
153
|
+
head,
|
|
154
|
+
inner_join,
|
|
155
|
+
intersect,
|
|
156
|
+
left_join,
|
|
157
|
+
mutate,
|
|
158
|
+
nest_join,
|
|
159
|
+
peek,
|
|
160
|
+
pull,
|
|
161
|
+
relocate,
|
|
162
|
+
reframe,
|
|
163
|
+
rename,
|
|
164
|
+
rename_with,
|
|
165
|
+
clean_names,
|
|
166
|
+
make_clean_names,
|
|
167
|
+
set_names,
|
|
168
|
+
right_join,
|
|
169
|
+
rowwise,
|
|
170
|
+
rows_append,
|
|
171
|
+
rows_delete,
|
|
172
|
+
rows_insert,
|
|
173
|
+
rows_patch,
|
|
174
|
+
rows_update,
|
|
175
|
+
rows_upsert,
|
|
176
|
+
sample_frac,
|
|
177
|
+
sample_n,
|
|
178
|
+
select,
|
|
179
|
+
semi_join,
|
|
180
|
+
setdiff,
|
|
181
|
+
setequal,
|
|
182
|
+
slice,
|
|
183
|
+
slice_head,
|
|
184
|
+
slice_max,
|
|
185
|
+
slice_min,
|
|
186
|
+
slice_sample,
|
|
187
|
+
slice_tail,
|
|
188
|
+
summarise,
|
|
189
|
+
summarize,
|
|
190
|
+
symdiff,
|
|
191
|
+
tally,
|
|
192
|
+
transmute,
|
|
193
|
+
to_numpy,
|
|
194
|
+
ungroup,
|
|
195
|
+
union,
|
|
196
|
+
union_all,
|
|
197
|
+
with_groups,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
from tidy3.__version__ import __version__
|
|
201
|
+
|
|
202
|
+
__all__ = [
|
|
203
|
+
"TidyFrame",
|
|
204
|
+
"JoinCondition",
|
|
205
|
+
"JoinSpec",
|
|
206
|
+
"Selector",
|
|
207
|
+
"across",
|
|
208
|
+
"cur_column",
|
|
209
|
+
"cur_group",
|
|
210
|
+
"cur_group_id",
|
|
211
|
+
"cur_group_rows",
|
|
212
|
+
"all",
|
|
213
|
+
"add_count",
|
|
214
|
+
"add_tally",
|
|
215
|
+
"anti_join",
|
|
216
|
+
"any",
|
|
217
|
+
"all_of",
|
|
218
|
+
"any_of",
|
|
219
|
+
"c_across",
|
|
220
|
+
"arrange",
|
|
221
|
+
"bind_cols",
|
|
222
|
+
"bind_rows",
|
|
223
|
+
"between",
|
|
224
|
+
"between_values",
|
|
225
|
+
"case_when",
|
|
226
|
+
"case_match",
|
|
227
|
+
"col",
|
|
228
|
+
"coalesce",
|
|
229
|
+
"collect",
|
|
230
|
+
"colnames",
|
|
231
|
+
"complete",
|
|
232
|
+
"col_range",
|
|
233
|
+
"cols_between",
|
|
234
|
+
"clean_names",
|
|
235
|
+
"closest",
|
|
236
|
+
"describe",
|
|
237
|
+
"dim",
|
|
238
|
+
"dtypes",
|
|
239
|
+
"contains",
|
|
240
|
+
"consecutive_id",
|
|
241
|
+
"count",
|
|
242
|
+
"cross_join",
|
|
243
|
+
"cumall",
|
|
244
|
+
"cumany",
|
|
245
|
+
"cume_dist",
|
|
246
|
+
"cummean",
|
|
247
|
+
"dense_rank",
|
|
248
|
+
"desc",
|
|
249
|
+
"distinct",
|
|
250
|
+
"drop",
|
|
251
|
+
"drop_na",
|
|
252
|
+
"ends_with",
|
|
253
|
+
"eq",
|
|
254
|
+
"everything",
|
|
255
|
+
"expand",
|
|
256
|
+
"ExportResult",
|
|
257
|
+
"collect_known_names",
|
|
258
|
+
"nb_export",
|
|
259
|
+
"transform_cell",
|
|
260
|
+
"transform_source",
|
|
261
|
+
"filter",
|
|
262
|
+
"filter_out",
|
|
263
|
+
"fill",
|
|
264
|
+
"hoist",
|
|
265
|
+
"first",
|
|
266
|
+
"full_join",
|
|
267
|
+
"ge",
|
|
268
|
+
"glimpse",
|
|
269
|
+
"group_by",
|
|
270
|
+
"group_map",
|
|
271
|
+
"group_modify",
|
|
272
|
+
"group_nest",
|
|
273
|
+
"group_split",
|
|
274
|
+
"group_cols",
|
|
275
|
+
"group_vars",
|
|
276
|
+
"n_groups",
|
|
277
|
+
"gt",
|
|
278
|
+
"head",
|
|
279
|
+
"inner_join",
|
|
280
|
+
"intersect",
|
|
281
|
+
"if_all",
|
|
282
|
+
"if_any",
|
|
283
|
+
"if_else",
|
|
284
|
+
"is_bool",
|
|
285
|
+
"is_boolean",
|
|
286
|
+
"is_categorical",
|
|
287
|
+
"is_character",
|
|
288
|
+
"is_datetime",
|
|
289
|
+
"is_float",
|
|
290
|
+
"is_integer",
|
|
291
|
+
"is_numeric",
|
|
292
|
+
"is_string",
|
|
293
|
+
"is_temporal",
|
|
294
|
+
"join_by",
|
|
295
|
+
"lag",
|
|
296
|
+
"last",
|
|
297
|
+
"last_col",
|
|
298
|
+
"le",
|
|
299
|
+
"lead",
|
|
300
|
+
"left_join",
|
|
301
|
+
"looks_like_tidy_pipe",
|
|
302
|
+
"lt",
|
|
303
|
+
"max",
|
|
304
|
+
"mean",
|
|
305
|
+
"median",
|
|
306
|
+
"make_clean_names",
|
|
307
|
+
"matches",
|
|
308
|
+
"min",
|
|
309
|
+
"min_rank",
|
|
310
|
+
"maybe_rewrite_cell",
|
|
311
|
+
"mutate",
|
|
312
|
+
"nest",
|
|
313
|
+
"nest_join",
|
|
314
|
+
"nesting",
|
|
315
|
+
"n",
|
|
316
|
+
"n_distinct",
|
|
317
|
+
"na_if",
|
|
318
|
+
"names",
|
|
319
|
+
"near",
|
|
320
|
+
"ncol",
|
|
321
|
+
"normalize_pipe_source",
|
|
322
|
+
"nrow",
|
|
323
|
+
"num_range",
|
|
324
|
+
"ntile",
|
|
325
|
+
"nth",
|
|
326
|
+
"options",
|
|
327
|
+
"overlaps",
|
|
328
|
+
"partial_run",
|
|
329
|
+
"peek",
|
|
330
|
+
"pick",
|
|
331
|
+
"percent_rank",
|
|
332
|
+
"pivot_longer",
|
|
333
|
+
"pivot_wider",
|
|
334
|
+
"pull",
|
|
335
|
+
"relocate",
|
|
336
|
+
"reframe",
|
|
337
|
+
"rename",
|
|
338
|
+
"rename_with",
|
|
339
|
+
"set_names",
|
|
340
|
+
"replace_na",
|
|
341
|
+
"right_join",
|
|
342
|
+
"rowwise",
|
|
343
|
+
"rows_append",
|
|
344
|
+
"rows_delete",
|
|
345
|
+
"rows_insert",
|
|
346
|
+
"rows_patch",
|
|
347
|
+
"rows_update",
|
|
348
|
+
"rows_upsert",
|
|
349
|
+
"row_number",
|
|
350
|
+
"recode",
|
|
351
|
+
"sample_frac",
|
|
352
|
+
"sample_n",
|
|
353
|
+
"scan_csv",
|
|
354
|
+
"scan_ipc",
|
|
355
|
+
"scan_parquet",
|
|
356
|
+
"select",
|
|
357
|
+
"separate",
|
|
358
|
+
"separate_longer_delim",
|
|
359
|
+
"separate_wider_delim",
|
|
360
|
+
"semi_join",
|
|
361
|
+
"setdiff",
|
|
362
|
+
"setequal",
|
|
363
|
+
"slice",
|
|
364
|
+
"slice_head",
|
|
365
|
+
"slice_max",
|
|
366
|
+
"slice_min",
|
|
367
|
+
"slice_sample",
|
|
368
|
+
"slice_tail",
|
|
369
|
+
"std",
|
|
370
|
+
"sd",
|
|
371
|
+
"starts_with",
|
|
372
|
+
"sum",
|
|
373
|
+
"summarise",
|
|
374
|
+
"summarize",
|
|
375
|
+
"summary",
|
|
376
|
+
"tally",
|
|
377
|
+
"tidy",
|
|
378
|
+
"to_numpy",
|
|
379
|
+
"transmute",
|
|
380
|
+
"unite",
|
|
381
|
+
"ungroup",
|
|
382
|
+
"unnest",
|
|
383
|
+
"unnest_longer",
|
|
384
|
+
"unnest_wider",
|
|
385
|
+
"pack",
|
|
386
|
+
"unpack",
|
|
387
|
+
"union",
|
|
388
|
+
"union_all",
|
|
389
|
+
"with_groups",
|
|
390
|
+
"var",
|
|
391
|
+
"symdiff",
|
|
392
|
+
"where",
|
|
393
|
+
"within",
|
|
394
|
+
"__version__",
|
|
395
|
+
]
|
|
396
|
+
|
|
397
|
+
# Inside IPython / SolveIt / Jupyter: enable multi-line ``>>`` rewriting even
|
|
398
|
+
# when the user only did ``from tidy3 import …`` (without %load_ext / addon).
|
|
399
|
+
try:
|
|
400
|
+
from IPython import get_ipython as _get_ipython
|
|
401
|
+
|
|
402
|
+
if _get_ipython is not None and _get_ipython() is not None:
|
|
403
|
+
from tidy3.jupyter import ensure_ipython_integration as _ensure_ip
|
|
404
|
+
|
|
405
|
+
_ensure_ip(quiet=True)
|
|
406
|
+
except Exception:
|
|
407
|
+
pass
|
tidy3/__main__.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""CLI: ``python -m tidy3 export notebook.ipynb -o script.py``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _cmd_export(args: argparse.Namespace) -> int:
|
|
11
|
+
from tidy3.export import nb_export
|
|
12
|
+
|
|
13
|
+
result = nb_export(
|
|
14
|
+
args.notebook,
|
|
15
|
+
args.output,
|
|
16
|
+
only_export=args.only_export,
|
|
17
|
+
with_plot3=not args.no_plot3,
|
|
18
|
+
known_extra=args.known or None,
|
|
19
|
+
)
|
|
20
|
+
print(result)
|
|
21
|
+
if result.warnings:
|
|
22
|
+
for w in result.warnings:
|
|
23
|
+
print(f" warning: {w}", file=sys.stderr)
|
|
24
|
+
return 0
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _cmd_run(args: argparse.Namespace) -> int:
|
|
28
|
+
"""Run a ``.py`` file after applying the same R-style transforms as export."""
|
|
29
|
+
from tidy3.export import collect_known_names, transform_source
|
|
30
|
+
|
|
31
|
+
path = Path(args.script).expanduser().resolve()
|
|
32
|
+
if not path.is_file():
|
|
33
|
+
print(f"error: file not found: {path}", file=sys.stderr)
|
|
34
|
+
return 1
|
|
35
|
+
src = path.read_text(encoding="utf-8")
|
|
36
|
+
known = collect_known_names([src])
|
|
37
|
+
if args.known:
|
|
38
|
+
known.update(args.known)
|
|
39
|
+
try:
|
|
40
|
+
code = transform_source(src, known=known, with_plot3=not args.no_plot3)
|
|
41
|
+
except SyntaxError as e:
|
|
42
|
+
print(f"error: transform failed: {e}", file=sys.stderr)
|
|
43
|
+
return 1
|
|
44
|
+
ns: dict = {"__name__": "__main__", "__file__": str(path)}
|
|
45
|
+
# Inject public APIs so short scripts work like notebooks
|
|
46
|
+
if not args.no_inject:
|
|
47
|
+
import tidy3 as t3
|
|
48
|
+
from tidy3.masking import make_named_assign
|
|
49
|
+
|
|
50
|
+
for name in t3.__all__:
|
|
51
|
+
if name.startswith("_"):
|
|
52
|
+
continue
|
|
53
|
+
try:
|
|
54
|
+
ns[name] = getattr(t3, name)
|
|
55
|
+
except AttributeError:
|
|
56
|
+
pass
|
|
57
|
+
ns["tidy3"] = t3
|
|
58
|
+
ns["__tidy3_assign__"] = make_named_assign
|
|
59
|
+
try:
|
|
60
|
+
import plot3 as p3
|
|
61
|
+
|
|
62
|
+
for name in getattr(p3, "__all__", ()):
|
|
63
|
+
if str(name).startswith("_"):
|
|
64
|
+
continue
|
|
65
|
+
try:
|
|
66
|
+
ns[name] = getattr(p3, name)
|
|
67
|
+
except AttributeError:
|
|
68
|
+
pass
|
|
69
|
+
ns["plot3"] = p3
|
|
70
|
+
except ImportError:
|
|
71
|
+
pass
|
|
72
|
+
exec(compile(code, str(path), "exec"), ns, ns)
|
|
73
|
+
return 0
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def main(argv: list[str] | None = None) -> int:
|
|
77
|
+
parser = argparse.ArgumentParser(
|
|
78
|
+
prog="python -m tidy3",
|
|
79
|
+
description="tidy3 utilities: export notebooks, run R-style scripts",
|
|
80
|
+
)
|
|
81
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
82
|
+
|
|
83
|
+
p_export = sub.add_parser(
|
|
84
|
+
"export",
|
|
85
|
+
help="export a Jupyter notebook to plain Python (nbdev-style)",
|
|
86
|
+
)
|
|
87
|
+
p_export.add_argument("notebook", type=str, help="path to .ipynb")
|
|
88
|
+
p_export.add_argument(
|
|
89
|
+
"-o",
|
|
90
|
+
"--output",
|
|
91
|
+
type=str,
|
|
92
|
+
default=None,
|
|
93
|
+
help="output .py path (default: notebook stem + .py)",
|
|
94
|
+
)
|
|
95
|
+
p_export.add_argument(
|
|
96
|
+
"--only-export",
|
|
97
|
+
action="store_true",
|
|
98
|
+
help="only include cells marked with #| export",
|
|
99
|
+
)
|
|
100
|
+
p_export.add_argument(
|
|
101
|
+
"--no-plot3",
|
|
102
|
+
action="store_true",
|
|
103
|
+
help="do not apply plot3 aes/facet masking",
|
|
104
|
+
)
|
|
105
|
+
p_export.add_argument(
|
|
106
|
+
"--known",
|
|
107
|
+
action="append",
|
|
108
|
+
default=[],
|
|
109
|
+
help="extra non-column name (repeatable), e.g. --known cars",
|
|
110
|
+
)
|
|
111
|
+
p_export.set_defaults(func=_cmd_export)
|
|
112
|
+
|
|
113
|
+
p_run = sub.add_parser(
|
|
114
|
+
"run",
|
|
115
|
+
help="run a .py file after R-style bare-name/backtick transforms",
|
|
116
|
+
)
|
|
117
|
+
p_run.add_argument("script", type=str, help="path to .py")
|
|
118
|
+
p_run.add_argument(
|
|
119
|
+
"--no-plot3",
|
|
120
|
+
action="store_true",
|
|
121
|
+
help="do not apply plot3 aes/facet masking",
|
|
122
|
+
)
|
|
123
|
+
p_run.add_argument(
|
|
124
|
+
"--no-inject",
|
|
125
|
+
action="store_true",
|
|
126
|
+
help="do not inject tidy3/plot3 into the script namespace",
|
|
127
|
+
)
|
|
128
|
+
p_run.add_argument(
|
|
129
|
+
"--known",
|
|
130
|
+
action="append",
|
|
131
|
+
default=[],
|
|
132
|
+
help="extra non-column name (repeatable)",
|
|
133
|
+
)
|
|
134
|
+
p_run.set_defaults(func=_cmd_run)
|
|
135
|
+
|
|
136
|
+
args = parser.parse_args(argv)
|
|
137
|
+
return int(args.func(args))
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
raise SystemExit(main())
|
tidy3/__version__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.0"
|