TimeFeatures 1.0.18__tar.gz → 2.1.0__tar.gz
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.
- {timefeatures-1.0.18/TimeFeatures.egg-info → timefeatures-2.1.0}/PKG-INFO +7 -2
- {timefeatures-1.0.18 → timefeatures-2.1.0}/README.md +4 -1
- {timefeatures-1.0.18 → timefeatures-2.1.0/TimeFeatures.egg-info}/PKG-INFO +7 -2
- {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/SOURCES.txt +11 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/requires.txt +2 -0
- timefeatures-2.1.0/docs/changes.rst +167 -0
- timefeatures-2.1.0/docs/conf.py +62 -0
- timefeatures-2.1.0/docs/index.rst +97 -0
- timefeatures-2.1.0/docs/installation.rst +103 -0
- timefeatures-2.1.0/docs/widgets/load-from-db.rst +172 -0
- timefeatures-2.1.0/docs/widgets/save-to-db.rst +220 -0
- timefeatures-2.1.0/docs/widgets/time-feature-constructor.rst +209 -0
- timefeatures-2.1.0/docs/widgets/variable-dependency-graph.rst +174 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/setup.py +3 -1
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/.buildinfo +1 -1
- timefeatures-2.1.0/timefeatures/help_html/_sources/changes.rst.txt +167 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/index.rst.txt +97 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/installation.rst.txt +103 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/load-from-db.rst.txt +172 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/save-to-db.rst.txt +220 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt +209 -0
- timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt +174 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/alabaster.css +6 -1
- timefeatures-2.1.0/timefeatures/help_html/changes.html +287 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/genindex.html +42 -27
- timefeatures-2.1.0/timefeatures/help_html/index.html +226 -0
- timefeatures-2.1.0/timefeatures/help_html/installation.html +231 -0
- timefeatures-2.1.0/timefeatures/help_html/objects.inv +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/search.html +59 -44
- timefeatures-2.1.0/timefeatures/help_html/searchindex.js +1 -0
- timefeatures-2.1.0/timefeatures/help_html/widgets/load-from-db.html +298 -0
- timefeatures-2.1.0/timefeatures/help_html/widgets/save-to-db.html +356 -0
- timefeatures-2.1.0/timefeatures/help_html/widgets/time-feature-constructor.html +346 -0
- timefeatures-2.1.0/timefeatures/help_html/widgets/variable-dependency-graph.html +324 -0
- timefeatures-2.1.0/timefeatures/widgets/icons/loaddatadb.svg +1 -0
- timefeatures-2.1.0/timefeatures/widgets/owloadfromdb.py +752 -0
- timefeatures-2.1.0/timefeatures/widgets/owsavetodb.py +886 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/owtimefeaturesconstructor.py +149 -32
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/owvardependencygraph.py +114 -25
- timefeatures-1.0.18/docs/conf.py +0 -26
- timefeatures-1.0.18/docs/index.rst +0 -37
- timefeatures-1.0.18/docs/widgets/save-to-db.rst +0 -70
- timefeatures-1.0.18/docs/widgets/time-feature-constructor.rst +0 -100
- timefeatures-1.0.18/docs/widgets/variable-dependency-graph.rst +0 -66
- timefeatures-1.0.18/timefeatures/help_html/_sources/index.rst.txt +0 -37
- timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/save-to-db.rst.txt +0 -70
- timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt +0 -100
- timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt +0 -66
- timefeatures-1.0.18/timefeatures/help_html/index.html +0 -135
- timefeatures-1.0.18/timefeatures/help_html/objects.inv +0 -6
- timefeatures-1.0.18/timefeatures/help_html/searchindex.js +0 -1
- timefeatures-1.0.18/timefeatures/help_html/widgets/save-to-db.html +0 -185
- timefeatures-1.0.18/timefeatures/help_html/widgets/time-feature-constructor.html +0 -219
- timefeatures-1.0.18/timefeatures/help_html/widgets/variable-dependency-graph.html +0 -181
- timefeatures-1.0.18/timefeatures/widgets/owsavetodb.py +0 -401
- {timefeatures-1.0.18 → timefeatures-2.1.0}/LICENSE +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/MANIFEST.in +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/dependency_links.txt +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/entry_points.txt +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/top_level.txt +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/docs/Makefile +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/docs/requirements.txt +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/imgs/installation.png +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/imgs/workflow.png +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/setup.cfg +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/__init__.py +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help.py +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/basic.css +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/custom.css +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/doctools.js +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/documentation_options.js +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/file.png +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/github-banner.svg +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/language_data.js +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/minus.png +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/plus.png +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/pygments.css +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/searchtools.js +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/sphinx_highlight.js +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/__init__.py +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/graphgenerator.svg +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/savedatadb.svg +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/timefeature-xs.svg +0 -0
- {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/timefeature.svg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TimeFeatures
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Timefeatures add-on for Orange 3 data mining software.
|
|
5
5
|
Home-page: https://github.com/alervgr/Orange-TimeFeatures
|
|
6
6
|
Author: Alejandro Rivas García
|
|
@@ -23,7 +23,9 @@ Requires-Dist: AnyQt>=0.2.0
|
|
|
23
23
|
Requires-Dist: PyQt5>=5.15.6
|
|
24
24
|
Requires-Dist: PyQtWebEngine>=5.15.6
|
|
25
25
|
Requires-Dist: scipy>=1.7.3
|
|
26
|
+
Requires-Dist: SQLAlchemy>=1.4.0
|
|
26
27
|
Requires-Dist: psycopg2-binary>=2.9.9
|
|
28
|
+
Requires-Dist: PyMySQL>=1.0.0
|
|
27
29
|
Requires-Dist: Orange3-Network>=1.8.0
|
|
28
30
|
Provides-Extra: docs
|
|
29
31
|
Requires-Dist: Sphinx>=7.0; extra == "docs"
|
|
@@ -84,12 +86,15 @@ If using Anaconda Python distribution, simply run
|
|
|
84
86
|
pip install TimeFeatures
|
|
85
87
|
|
|
86
88
|
**Required Dependencies**:
|
|
89
|
+
|
|
87
90
|
* numpy>=1.22.4
|
|
88
91
|
* AnyQt>=0.2.0
|
|
89
|
-
* Orange3>=3.34.0
|
|
90
92
|
* PyQt5>=5.15.6
|
|
91
93
|
* PyQtWebEngine>=5.15.6
|
|
92
94
|
* scipy>=1.7.3
|
|
95
|
+
* SQLAlchemy>=1.4.0
|
|
96
|
+
* psycopg2-binary>=2.9.9
|
|
97
|
+
* PyMySQL>=1.0.0
|
|
93
98
|
* Orange3-Network>=1.8.0
|
|
94
99
|
|
|
95
100
|
Usage
|
|
@@ -42,12 +42,15 @@ If using Anaconda Python distribution, simply run
|
|
|
42
42
|
pip install TimeFeatures
|
|
43
43
|
|
|
44
44
|
**Required Dependencies**:
|
|
45
|
+
|
|
45
46
|
* numpy>=1.22.4
|
|
46
47
|
* AnyQt>=0.2.0
|
|
47
|
-
* Orange3>=3.34.0
|
|
48
48
|
* PyQt5>=5.15.6
|
|
49
49
|
* PyQtWebEngine>=5.15.6
|
|
50
50
|
* scipy>=1.7.3
|
|
51
|
+
* SQLAlchemy>=1.4.0
|
|
52
|
+
* psycopg2-binary>=2.9.9
|
|
53
|
+
* PyMySQL>=1.0.0
|
|
51
54
|
* Orange3-Network>=1.8.0
|
|
52
55
|
|
|
53
56
|
Usage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TimeFeatures
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Timefeatures add-on for Orange 3 data mining software.
|
|
5
5
|
Home-page: https://github.com/alervgr/Orange-TimeFeatures
|
|
6
6
|
Author: Alejandro Rivas García
|
|
@@ -23,7 +23,9 @@ Requires-Dist: AnyQt>=0.2.0
|
|
|
23
23
|
Requires-Dist: PyQt5>=5.15.6
|
|
24
24
|
Requires-Dist: PyQtWebEngine>=5.15.6
|
|
25
25
|
Requires-Dist: scipy>=1.7.3
|
|
26
|
+
Requires-Dist: SQLAlchemy>=1.4.0
|
|
26
27
|
Requires-Dist: psycopg2-binary>=2.9.9
|
|
28
|
+
Requires-Dist: PyMySQL>=1.0.0
|
|
27
29
|
Requires-Dist: Orange3-Network>=1.8.0
|
|
28
30
|
Provides-Extra: docs
|
|
29
31
|
Requires-Dist: Sphinx>=7.0; extra == "docs"
|
|
@@ -84,12 +86,15 @@ If using Anaconda Python distribution, simply run
|
|
|
84
86
|
pip install TimeFeatures
|
|
85
87
|
|
|
86
88
|
**Required Dependencies**:
|
|
89
|
+
|
|
87
90
|
* numpy>=1.22.4
|
|
88
91
|
* AnyQt>=0.2.0
|
|
89
|
-
* Orange3>=3.34.0
|
|
90
92
|
* PyQt5>=5.15.6
|
|
91
93
|
* PyQtWebEngine>=5.15.6
|
|
92
94
|
* scipy>=1.7.3
|
|
95
|
+
* SQLAlchemy>=1.4.0
|
|
96
|
+
* psycopg2-binary>=2.9.9
|
|
97
|
+
* PyMySQL>=1.0.0
|
|
93
98
|
* Orange3-Network>=1.8.0
|
|
94
99
|
|
|
95
100
|
Usage
|
|
@@ -10,9 +10,12 @@ TimeFeatures.egg-info/entry_points.txt
|
|
|
10
10
|
TimeFeatures.egg-info/requires.txt
|
|
11
11
|
TimeFeatures.egg-info/top_level.txt
|
|
12
12
|
docs/Makefile
|
|
13
|
+
docs/changes.rst
|
|
13
14
|
docs/conf.py
|
|
14
15
|
docs/index.rst
|
|
16
|
+
docs/installation.rst
|
|
15
17
|
docs/requirements.txt
|
|
18
|
+
docs/widgets/load-from-db.rst
|
|
16
19
|
docs/widgets/save-to-db.rst
|
|
17
20
|
docs/widgets/time-feature-constructor.rst
|
|
18
21
|
docs/widgets/variable-dependency-graph.rst
|
|
@@ -21,12 +24,17 @@ imgs/workflow.png
|
|
|
21
24
|
timefeatures/__init__.py
|
|
22
25
|
timefeatures/help.py
|
|
23
26
|
timefeatures/help_html/.buildinfo
|
|
27
|
+
timefeatures/help_html/changes.html
|
|
24
28
|
timefeatures/help_html/genindex.html
|
|
25
29
|
timefeatures/help_html/index.html
|
|
30
|
+
timefeatures/help_html/installation.html
|
|
26
31
|
timefeatures/help_html/objects.inv
|
|
27
32
|
timefeatures/help_html/search.html
|
|
28
33
|
timefeatures/help_html/searchindex.js
|
|
34
|
+
timefeatures/help_html/_sources/changes.rst.txt
|
|
29
35
|
timefeatures/help_html/_sources/index.rst.txt
|
|
36
|
+
timefeatures/help_html/_sources/installation.rst.txt
|
|
37
|
+
timefeatures/help_html/_sources/widgets/load-from-db.rst.txt
|
|
30
38
|
timefeatures/help_html/_sources/widgets/save-to-db.rst.txt
|
|
31
39
|
timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt
|
|
32
40
|
timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt
|
|
@@ -43,14 +51,17 @@ timefeatures/help_html/_static/plus.png
|
|
|
43
51
|
timefeatures/help_html/_static/pygments.css
|
|
44
52
|
timefeatures/help_html/_static/searchtools.js
|
|
45
53
|
timefeatures/help_html/_static/sphinx_highlight.js
|
|
54
|
+
timefeatures/help_html/widgets/load-from-db.html
|
|
46
55
|
timefeatures/help_html/widgets/save-to-db.html
|
|
47
56
|
timefeatures/help_html/widgets/time-feature-constructor.html
|
|
48
57
|
timefeatures/help_html/widgets/variable-dependency-graph.html
|
|
49
58
|
timefeatures/widgets/__init__.py
|
|
59
|
+
timefeatures/widgets/owloadfromdb.py
|
|
50
60
|
timefeatures/widgets/owsavetodb.py
|
|
51
61
|
timefeatures/widgets/owtimefeaturesconstructor.py
|
|
52
62
|
timefeatures/widgets/owvardependencygraph.py
|
|
53
63
|
timefeatures/widgets/icons/graphgenerator.svg
|
|
64
|
+
timefeatures/widgets/icons/loaddatadb.svg
|
|
54
65
|
timefeatures/widgets/icons/savedatadb.svg
|
|
55
66
|
timefeatures/widgets/icons/timefeature-xs.svg
|
|
56
67
|
timefeatures/widgets/icons/timefeature.svg
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Changelog
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
Unreleased
|
|
5
|
+
----------
|
|
6
|
+
|
|
7
|
+
**Load from DB (new widget)**
|
|
8
|
+
|
|
9
|
+
- Lists every dataset registered in the ``datasets`` metadata table
|
|
10
|
+
via SQLAlchemy and pulls the selected one back into Orange as an
|
|
11
|
+
``Orange.data.Table`` using ``pandas.read_sql`` +
|
|
12
|
+
``Orange.data.pandas_compat.table_from_frame``.
|
|
13
|
+
- Offers a Class column combo populated from the dataset's columns,
|
|
14
|
+
pre-selected with the user's persisted choice or the ``class_name``
|
|
15
|
+
recorded by Save to DB. The output ``Table`` already exposes the
|
|
16
|
+
chosen column as ``domain.class_var``, so no Select Columns widget
|
|
17
|
+
is needed downstream.
|
|
18
|
+
- Same dialect selector (PostgreSQL / MySQL), connection-status
|
|
19
|
+
label and ``QThread`` worker pattern as Save to DB. Both the
|
|
20
|
+
metadata listing and the actual table read happen off the GUI
|
|
21
|
+
thread.
|
|
22
|
+
- Workflow-persisted settings: ``selected_dataset`` and
|
|
23
|
+
``selected_class`` are ``Setting(..., schema_only=True)``, restored
|
|
24
|
+
as soon as the connection comes back up on reload.
|
|
25
|
+
- The Dataset combo is a ``ComboBoxSearch`` — type to filter when the
|
|
26
|
+
registry gets large.
|
|
27
|
+
- ``↻`` button next to the Dataset combo re-runs the listing without
|
|
28
|
+
dropping the connection (handy when something else just published a
|
|
29
|
+
new dataset). Auto-load is suppressed on Refresh so the user never
|
|
30
|
+
gets a Load they didn't ask for.
|
|
31
|
+
- ``Delete`` button drops the selected dataset's table and removes
|
|
32
|
+
its row in ``datasets``. Runs through a ``_DeleteDatasetWorker`` on
|
|
33
|
+
a background thread, guarded by a confirmation dialog. Idempotent:
|
|
34
|
+
re-deleting a missing table is a no-op thanks to
|
|
35
|
+
``DROP TABLE IF EXISTS``.
|
|
36
|
+
- **Auto-load** on workflow reopen: if the persisted
|
|
37
|
+
``selected_dataset`` is still on the server when the connection
|
|
38
|
+
succeeds and the listing returns, Load fires automatically — the
|
|
39
|
+
data flows out without a single click. The flag is cleared on
|
|
40
|
+
Refresh and on Delete to avoid surprises.
|
|
41
|
+
|
|
42
|
+
**Variable Dependency Graph**
|
|
43
|
+
|
|
44
|
+
- *New:* edges now carry **numeric weights** equal to the largest
|
|
45
|
+
``|argument|`` among the temporal calls (``shift``, ``sum``, ``mean``,
|
|
46
|
+
``count``, ``min``, ``max``, ``sd``) in the source expression that
|
|
47
|
+
reference the dependency. Plain (non-temporal) references default to
|
|
48
|
+
weight ``1``. The weights live in ``network.edges[0].edges.data``
|
|
49
|
+
and are consumable by any downstream Network widget.
|
|
50
|
+
- *New:* the graph is now **directed** (``DirectedEdges``). Previously
|
|
51
|
+
the sparse matrix was passed straight to ``Network`` which auto-wrapped
|
|
52
|
+
it as ``UndirectedEdges`` — a latent bug since A→B is not the same as
|
|
53
|
+
B→A in a dependency graph.
|
|
54
|
+
- *New:* nodes carry an extra ``expression`` meta (literal expression
|
|
55
|
+
text, empty for original variables) so the Network Explorer can show
|
|
56
|
+
the formula as the node label.
|
|
57
|
+
- *New:* ``Warning.no_derived`` fires when every input row is an
|
|
58
|
+
original variable — usually a sign the user wired the data output
|
|
59
|
+
of Time Features Constructor instead of the variable-definitions
|
|
60
|
+
one.
|
|
61
|
+
- Refactor: flattened the ``from_row_col`` / ``grafo`` decorator pattern
|
|
62
|
+
into a single, documented ``build_dependency_network`` function.
|
|
63
|
+
- Performance: O(n³) → O(n²) by precomputing a ``name → index`` map and
|
|
64
|
+
using a ``set`` to dedupe dependencies.
|
|
65
|
+
- Bugfix: an ``IndexError`` was raised when the input domain had a
|
|
66
|
+
single column. The widget now checks ``len(domain) >= 2`` before
|
|
67
|
+
reading the second column.
|
|
68
|
+
- Removed 65 lines of dead commented-out code.
|
|
69
|
+
|
|
70
|
+
**Time Features Constructor**
|
|
71
|
+
|
|
72
|
+
- *New:* **chained descriptors**. A descriptor can now reference
|
|
73
|
+
another derived descriptor in its expression (e.g. ``X2 :=
|
|
74
|
+
shift(X1, -1)`` with ``X1`` itself defined a few rows above). The
|
|
75
|
+
widget topologically sorts the descriptors and cascades the
|
|
76
|
+
transforms — each step runs against the table state produced by
|
|
77
|
+
the previous one, so ``X2`` sees ``X1`` as a regular column.
|
|
78
|
+
Cycles (e.g. ``X1 := X2 + 1`` together with ``X2 := X1 + 1``) raise
|
|
79
|
+
a *Circular dependency between descriptors: X1, X2* error. Errors
|
|
80
|
+
during evaluation are reported per-descriptor so the failing row is
|
|
81
|
+
obvious.
|
|
82
|
+
- *Fixed (critical):* time-window functions used to lose context every
|
|
83
|
+
5 000 rows because Orange chunks tables during ``transform``. The
|
|
84
|
+
widget now caches the full source per ``FeatureFunc`` and returns the
|
|
85
|
+
right slice for each chunk, so ``shift(x, -20)`` is correct across
|
|
86
|
+
chunk boundaries on datasets of any size.
|
|
87
|
+
- *Fixed:* "Variables to generate" was being cleared after every Send
|
|
88
|
+
and on every input change, so workflow save / reload lost the
|
|
89
|
+
definitions. Storage moved from ``ContextSetting`` to
|
|
90
|
+
``Setting(..., schema_only=True)`` (matching upstream Orange v4) and
|
|
91
|
+
the editor is now restored from the persisted descriptors on every
|
|
92
|
+
input. The legacy context handler stays around to migrate old
|
|
93
|
+
workflows.
|
|
94
|
+
- Each **Send** re-transforms the *original* input table instead of the
|
|
95
|
+
cumulative output, removing the implicit "consume on Send" semantics
|
|
96
|
+
and the duplicate-name errors that came with it.
|
|
97
|
+
- ``eval`` hardened: ``__builtins__`` replaced with an empty dict in
|
|
98
|
+
the expression evaluator. Only the curated whitelist
|
|
99
|
+
(safe builtins + ``math`` + selected ``random`` / ``numpy``
|
|
100
|
+
helpers) is exposed.
|
|
101
|
+
- Refactor: ``modificar_expression`` collapsed from 7 near-identical
|
|
102
|
+
loops to a single regex-driven pass.
|
|
103
|
+
- Bugfix: ``FeatureEditor.editorData`` returned the variable name as
|
|
104
|
+
the expression.
|
|
105
|
+
|
|
106
|
+
**Save to DB**
|
|
107
|
+
|
|
108
|
+
- *New:* **write mode** selector with three options — *Create new*
|
|
109
|
+
(default, fail if the target exists), *Overwrite* (drop and
|
|
110
|
+
recreate the table and its ``datasets`` row), *Append* (keep
|
|
111
|
+
existing rows and add the new ones). Re-running a workflow no
|
|
112
|
+
longer breaks. The persisted ``write_mode`` Setting defaults to
|
|
113
|
+
``"create"`` so old workflows keep their previous behaviour. After
|
|
114
|
+
the upload, the widget runs ``SELECT COUNT(*)`` and rewrites the
|
|
115
|
+
``datasets`` row with the actual total, so the registry stays
|
|
116
|
+
accurate across appends.
|
|
117
|
+
- *New:* **MySQL support**. The connection panel now exposes a
|
|
118
|
+
database-type selector (PostgreSQL / MySQL). Per-dialect column
|
|
119
|
+
types and identifier quoting (``"name"`` vs ``\`name\```) live in
|
|
120
|
+
a ``_Dialect`` abstraction.
|
|
121
|
+
- *Performance:* uploads now go through
|
|
122
|
+
``Orange.data.pandas_compat.table_to_frame`` +
|
|
123
|
+
``DataFrame.to_sql(method='multi', chunksize=1000)`` over a
|
|
124
|
+
SQLAlchemy engine. The old row-per-INSERT loop is gone — typical
|
|
125
|
+
speedups are 50-100×, especially over the network. Identifier
|
|
126
|
+
quoting and per-column DDL types are emitted by the SQLAlchemy
|
|
127
|
+
dialect (``DOUBLE_PRECISION`` on PostgreSQL, ``DOUBLE`` on MySQL,
|
|
128
|
+
``DATETIME`` instead of ``TIMESTAMP`` on MySQL to dodge the 2038
|
|
129
|
+
cap, ``VARCHAR(255)`` / ``TEXT`` everywhere else).
|
|
130
|
+
- *UX:* the upload runs in a background ``QThread`` (``_UploadWorker``),
|
|
131
|
+
so the canvas stays interactive on long writes. A status label under
|
|
132
|
+
the connection box reports *Not connected* / *Connected to … : …* /
|
|
133
|
+
*Uploading rows N/M…* / *Upload completed in Xs* / *Upload failed:
|
|
134
|
+
…* with colour cues. **Save**, **Connect** and the form fields are
|
|
135
|
+
disabled while the worker runs and re-enabled on success or
|
|
136
|
+
failure; the widget aborts the thread cleanly on close.
|
|
137
|
+
- *Fixed (critical):* SQL injection in the metadata ``INSERT``. The
|
|
138
|
+
query is now fully parametrised.
|
|
139
|
+
- Added an identifier whitelist
|
|
140
|
+
(``^[A-Za-z_][A-Za-z0-9_]{0,62}$``) and a ``quote_ident`` helper that
|
|
141
|
+
wraps identifiers with PostgreSQL-standard double quotes (with any
|
|
142
|
+
internal ``"`` doubled). Used in every ``CREATE TABLE`` / ``INSERT
|
|
143
|
+
INTO`` that touches user-supplied names.
|
|
144
|
+
- Replaced ``psycopg2`` with ``psycopg2-binary`` in the install
|
|
145
|
+
requirements so installation works on macOS, Linux and Windows
|
|
146
|
+
without a C compiler.
|
|
147
|
+
- ``setup.py`` now declares ``install_requires``; ``pip install`` was
|
|
148
|
+
previously not pulling in any runtime dependency.
|
|
149
|
+
|
|
150
|
+
Testing
|
|
151
|
+
-------
|
|
152
|
+
|
|
153
|
+
The widget suite grew to **92 tests**, covering:
|
|
154
|
+
|
|
155
|
+
- Unit tests for ``modificar_expression``, the time-window helpers,
|
|
156
|
+
``_sanitize_name`` / ``_expression_or_none`` and ``_temporal_weights``.
|
|
157
|
+
- A regression test for the 5 000-row chunk bug
|
|
158
|
+
(``shift(x, -20)`` over a 12 000-row table).
|
|
159
|
+
- ``eval``-safety tests asserting that ``__import__`` / ``open`` raise
|
|
160
|
+
``NameError`` while ``sqrt`` / ``abs`` still resolve.
|
|
161
|
+
- Widget-level tests (via ``Orange.widgets.tests.base.WidgetTest``) for
|
|
162
|
+
descriptor persistence, including an end-to-end
|
|
163
|
+
``settingsHandler.pack_data`` / ``stored_settings=`` round-trip that
|
|
164
|
+
mirrors what Orange does when saving and reopening a ``.ows`` file.
|
|
165
|
+
- Edge-weight tests covering single calls, three-argument families,
|
|
166
|
+
mixed temporal / non-temporal references, max across multiple calls,
|
|
167
|
+
and per-dependency independence.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Sphinx configuration for TimeFeatures."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
7
|
+
sys.path.insert(0, str(ROOT))
|
|
8
|
+
|
|
9
|
+
# -- Project information --------------------------------------------------
|
|
10
|
+
project = "TimeFeatures"
|
|
11
|
+
author = "Alejandro Rivas Garcia"
|
|
12
|
+
copyright = "2026, Alejandro Rivas Garcia"
|
|
13
|
+
release = "1.0.18"
|
|
14
|
+
version = ".".join(release.split(".")[:2])
|
|
15
|
+
|
|
16
|
+
# -- General configuration ------------------------------------------------
|
|
17
|
+
extensions = [
|
|
18
|
+
# Auto-generate :ref: labels from section titles so we can write
|
|
19
|
+
# `:ref:`Edge Weights`` instead of declaring labels by hand.
|
|
20
|
+
"sphinx.ext.autosectionlabel",
|
|
21
|
+
# Link to Orange / NumPy / SciPy reference docs.
|
|
22
|
+
"sphinx.ext.intersphinx",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
# Prefix labels with the document name so two pages can share the same
|
|
26
|
+
# section title (e.g. "Usage Example") without clashing.
|
|
27
|
+
autosectionlabel_prefix_document = True
|
|
28
|
+
|
|
29
|
+
intersphinx_mapping = {
|
|
30
|
+
"python": ("https://docs.python.org/3", None),
|
|
31
|
+
"numpy": ("https://numpy.org/doc/stable/", None),
|
|
32
|
+
"scipy": ("https://docs.scipy.org/doc/scipy/", None),
|
|
33
|
+
"orange": ("https://orange3.readthedocs.io/projects/orange-data-mining-library/en/latest/", None),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
templates_path = ["_templates"]
|
|
37
|
+
exclude_patterns = ["build", "Thumbs.db", ".DS_Store"]
|
|
38
|
+
|
|
39
|
+
language = "en"
|
|
40
|
+
|
|
41
|
+
# -- HTML output ----------------------------------------------------------
|
|
42
|
+
html_theme = "alabaster"
|
|
43
|
+
html_static_path = []
|
|
44
|
+
html_title = "TimeFeatures documentation"
|
|
45
|
+
html_short_title = "TimeFeatures"
|
|
46
|
+
html_theme_options = {
|
|
47
|
+
"description": (
|
|
48
|
+
"Time-series feature engineering for Orange3: build derived "
|
|
49
|
+
"variables, visualise their dependencies, and persist data to "
|
|
50
|
+
"PostgreSQL."
|
|
51
|
+
),
|
|
52
|
+
"github_user": "alervgr",
|
|
53
|
+
"github_repo": "Orange-TimeFeatures",
|
|
54
|
+
"github_banner": True,
|
|
55
|
+
"show_powered_by": False,
|
|
56
|
+
"fixed_sidebar": True,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Default replacements for any RST file (no need to redeclare per page).
|
|
60
|
+
rst_prolog = """
|
|
61
|
+
.. |addon| replace:: TimeFeatures
|
|
62
|
+
"""
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
TimeFeatures
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
|addon| is an `Orange3 <https://orangedatamining.com/>`_ add-on for
|
|
5
|
+
time-series feature engineering. It ships four widgets that work
|
|
6
|
+
together to define, visualise, persist and re-load derived variables
|
|
7
|
+
built on top of an existing dataset.
|
|
8
|
+
|
|
9
|
+
.. list-table::
|
|
10
|
+
:header-rows: 1
|
|
11
|
+
:widths: 30 70
|
|
12
|
+
|
|
13
|
+
* - Widget
|
|
14
|
+
- What it does
|
|
15
|
+
* - :doc:`widgets/time-feature-constructor`
|
|
16
|
+
- Defines new variables from existing ones using Python-style
|
|
17
|
+
expressions and time-window functions (``shift``, ``sum``,
|
|
18
|
+
``mean``, ``min``, ``max``, ``sd``, ``count``).
|
|
19
|
+
* - :doc:`widgets/variable-dependency-graph`
|
|
20
|
+
- Builds a directed, **weighted** dependency graph from the
|
|
21
|
+
resulting variable / expression table. Edge weights summarise
|
|
22
|
+
how far back or forward in time each variable looks.
|
|
23
|
+
* - :doc:`widgets/save-to-db`
|
|
24
|
+
- Persists the resulting dataset to a SQL database (PostgreSQL
|
|
25
|
+
or MySQL), with full SQL-injection defences and an optional
|
|
26
|
+
completion email.
|
|
27
|
+
* - :doc:`widgets/load-from-db`
|
|
28
|
+
- Lists the datasets previously stored by Save to DB and pulls
|
|
29
|
+
the chosen one back into Orange, optionally marking the class
|
|
30
|
+
column directly so no Select Columns widget is needed.
|
|
31
|
+
|
|
32
|
+
.. _workflow:
|
|
33
|
+
|
|
34
|
+
Workflow
|
|
35
|
+
--------
|
|
36
|
+
|
|
37
|
+
A typical pipeline:
|
|
38
|
+
|
|
39
|
+
.. code-block:: text
|
|
40
|
+
|
|
41
|
+
File → Time Features Constructor → ┬→ <downstream models>
|
|
42
|
+
└→ Variable Dependency Graph
|
|
43
|
+
↓
|
|
44
|
+
Network Explorer
|
|
45
|
+
|
|
46
|
+
The **Time Features Constructor** outputs both the transformed data
|
|
47
|
+
(top arrow) and the variable / expression definition table (bottom
|
|
48
|
+
arrow). Feed the latter into the **Variable Dependency Graph** to
|
|
49
|
+
visualise the dependencies, and send the data into **Save to DB** if
|
|
50
|
+
you want to keep it in a database.
|
|
51
|
+
|
|
52
|
+
Getting started
|
|
53
|
+
---------------
|
|
54
|
+
|
|
55
|
+
.. toctree::
|
|
56
|
+
:maxdepth: 2
|
|
57
|
+
|
|
58
|
+
installation
|
|
59
|
+
|
|
60
|
+
.. _widgets:
|
|
61
|
+
|
|
62
|
+
Widgets
|
|
63
|
+
-------
|
|
64
|
+
|
|
65
|
+
.. toctree::
|
|
66
|
+
:maxdepth: 1
|
|
67
|
+
|
|
68
|
+
widgets/time-feature-constructor
|
|
69
|
+
widgets/variable-dependency-graph
|
|
70
|
+
widgets/save-to-db
|
|
71
|
+
widgets/load-from-db
|
|
72
|
+
|
|
73
|
+
Project
|
|
74
|
+
-------
|
|
75
|
+
|
|
76
|
+
.. toctree::
|
|
77
|
+
:maxdepth: 1
|
|
78
|
+
|
|
79
|
+
changes
|
|
80
|
+
|
|
81
|
+
Building this documentation
|
|
82
|
+
---------------------------
|
|
83
|
+
|
|
84
|
+
.. code-block:: bash
|
|
85
|
+
|
|
86
|
+
pip install -e ".[docs]"
|
|
87
|
+
python -m sphinx -b html docs docs/build/html
|
|
88
|
+
|
|
89
|
+
The HTML build is also bundled with the wheel so Orange's in-app help
|
|
90
|
+
panel can resolve every widget's *Help* action without internet
|
|
91
|
+
access.
|
|
92
|
+
|
|
93
|
+
Indices
|
|
94
|
+
-------
|
|
95
|
+
|
|
96
|
+
* :ref:`genindex`
|
|
97
|
+
* :ref:`search`
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Installation
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
|addon| is an Orange3 add-on, so it requires a working Orange3
|
|
5
|
+
installation in the same Python environment.
|
|
6
|
+
|
|
7
|
+
From PyPI
|
|
8
|
+
---------
|
|
9
|
+
|
|
10
|
+
.. code-block:: bash
|
|
11
|
+
|
|
12
|
+
pip install TimeFeatures
|
|
13
|
+
|
|
14
|
+
This pulls in every runtime dependency, including the precompiled
|
|
15
|
+
``psycopg2-binary`` wheel so the **Save to DB** widget works on macOS,
|
|
16
|
+
Linux and Windows without a C toolchain.
|
|
17
|
+
|
|
18
|
+
From source
|
|
19
|
+
-----------
|
|
20
|
+
|
|
21
|
+
.. code-block:: bash
|
|
22
|
+
|
|
23
|
+
git clone https://github.com/alervgr/Orange-TimeFeatures.git
|
|
24
|
+
cd Orange-TimeFeatures
|
|
25
|
+
pip install -e .
|
|
26
|
+
|
|
27
|
+
The ``-e`` flag installs in *editable* mode so changes to the source
|
|
28
|
+
tree are picked up on the next Orange restart without reinstalling.
|
|
29
|
+
|
|
30
|
+
Inside Orange
|
|
31
|
+
-------------
|
|
32
|
+
|
|
33
|
+
|addon| also installs through Orange's GUI:
|
|
34
|
+
|
|
35
|
+
1. Open Orange.
|
|
36
|
+
2. Go to **Options → Add-ons…**.
|
|
37
|
+
3. Tick **TimeFeatures** in the list and confirm.
|
|
38
|
+
4. Restart Orange. The new widgets appear under the **Time-Features**
|
|
39
|
+
toolbox section.
|
|
40
|
+
|
|
41
|
+
.. image:: https://github.com/alervgr/Orange-TimeFeatures/blob/main/imgs/installation.png?raw=true
|
|
42
|
+
:alt: TimeFeatures in Orange's Add-on installer.
|
|
43
|
+
|
|
44
|
+
Anaconda
|
|
45
|
+
--------
|
|
46
|
+
|
|
47
|
+
The same ``pip install TimeFeatures`` command works inside a Conda
|
|
48
|
+
environment as long as Orange3 is installed there.
|
|
49
|
+
|
|
50
|
+
Dependencies
|
|
51
|
+
------------
|
|
52
|
+
|
|
53
|
+
|addon| declares the following runtime dependencies (see
|
|
54
|
+
``setup.py``):
|
|
55
|
+
|
|
56
|
+
.. list-table::
|
|
57
|
+
:header-rows: 1
|
|
58
|
+
|
|
59
|
+
* - Package
|
|
60
|
+
- Minimum version
|
|
61
|
+
- Used by
|
|
62
|
+
* - ``numpy``
|
|
63
|
+
- 1.22.4
|
|
64
|
+
- All widgets.
|
|
65
|
+
* - ``scipy``
|
|
66
|
+
- 1.7.3
|
|
67
|
+
- Sparse adjacency matrices in the dependency graph.
|
|
68
|
+
* - ``PyQt5``
|
|
69
|
+
- 5.15.6
|
|
70
|
+
- Widget UI.
|
|
71
|
+
* - ``AnyQt``
|
|
72
|
+
- 0.2.0
|
|
73
|
+
- Qt abstraction used by Orange.
|
|
74
|
+
* - ``SQLAlchemy``
|
|
75
|
+
- 1.4.0
|
|
76
|
+
- Dialect-agnostic SQL toolkit used by **Save to DB**.
|
|
77
|
+
* - ``psycopg2-binary``
|
|
78
|
+
- 2.9.9
|
|
79
|
+
- PostgreSQL driver for **Save to DB**.
|
|
80
|
+
* - ``PyMySQL``
|
|
81
|
+
- 1.0.0
|
|
82
|
+
- MySQL driver for **Save to DB**.
|
|
83
|
+
* - ``Orange3-Network``
|
|
84
|
+
- 1.8.0
|
|
85
|
+
- ``Network`` type produced by **Variable Dependency Graph**.
|
|
86
|
+
|
|
87
|
+
Orange3 itself is intentionally left out of the requirements list — the
|
|
88
|
+
host application provides it.
|
|
89
|
+
|
|
90
|
+
Running tests
|
|
91
|
+
-------------
|
|
92
|
+
|
|
93
|
+
The test suite uses ``unittest`` and lives under
|
|
94
|
+
``timefeatures/widgets/tests/``. From a checkout:
|
|
95
|
+
|
|
96
|
+
.. code-block:: bash
|
|
97
|
+
|
|
98
|
+
pip install -e .
|
|
99
|
+
python -m unittest discover -v timefeatures/widgets/tests
|
|
100
|
+
|
|
101
|
+
The widget-level tests inherit from ``Orange.widgets.tests.base.WidgetTest``
|
|
102
|
+
and therefore require Qt; a virtual display (``Xvfb``) is enough on a
|
|
103
|
+
headless CI worker.
|