TimeFeatures 2.0.0__tar.gz → 2.1.1__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.
Files changed (85) hide show
  1. {timefeatures-2.0.0/TimeFeatures.egg-info → timefeatures-2.1.1}/PKG-INFO +42 -25
  2. timefeatures-2.1.1/README.md +101 -0
  3. {timefeatures-2.0.0 → timefeatures-2.1.1/TimeFeatures.egg-info}/PKG-INFO +42 -25
  4. {timefeatures-2.0.0 → timefeatures-2.1.1}/TimeFeatures.egg-info/SOURCES.txt +10 -0
  5. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/changes.rst +48 -2
  6. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/conf.py +6 -2
  7. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/index.rst +9 -0
  8. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/widgets/load-from-db.rst +45 -4
  9. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/widgets/save-to-db.rst +46 -6
  10. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/widgets/time-feature-constructor.rst +32 -0
  11. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/widgets/variable-dependency-graph.rst +22 -3
  12. timefeatures-2.1.1/imgs/installation.png +0 -0
  13. timefeatures-2.1.1/imgs/widgets/owloadfromdb.png +0 -0
  14. timefeatures-2.1.1/imgs/widgets/owsavetodb.png +0 -0
  15. timefeatures-2.1.1/imgs/widgets/owtimefeaturesconstructor.png +0 -0
  16. timefeatures-2.1.1/imgs/widgets/owvariabledependencygraph.png +0 -0
  17. timefeatures-2.1.1/imgs/workflow.png +0 -0
  18. {timefeatures-2.0.0 → timefeatures-2.1.1}/setup.py +12 -2
  19. timefeatures-2.1.1/timefeatures/__init__.py +5 -0
  20. timefeatures-2.1.1/timefeatures/__version__.py +3 -0
  21. timefeatures-2.1.1/timefeatures/help_html/.buildinfo +4 -0
  22. timefeatures-2.1.1/timefeatures/help_html/_images/owloadfromdb.png +0 -0
  23. timefeatures-2.1.1/timefeatures/help_html/_images/owsavetodb.png +0 -0
  24. timefeatures-2.1.1/timefeatures/help_html/_images/owtimefeaturesconstructor.png +0 -0
  25. timefeatures-2.1.1/timefeatures/help_html/_images/owvariabledependencygraph.png +0 -0
  26. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/changes.rst.txt +48 -2
  27. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/index.rst.txt +9 -0
  28. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/widgets/load-from-db.rst.txt +45 -4
  29. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/widgets/save-to-db.rst.txt +46 -6
  30. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt +32 -0
  31. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt +22 -3
  32. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/documentation_options.js +1 -1
  33. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/changes.html +50 -4
  34. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/genindex.html +2 -2
  35. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/index.html +8 -2
  36. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/installation.html +2 -2
  37. timefeatures-2.1.1/timefeatures/help_html/objects.inv +0 -0
  38. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/search.html +2 -2
  39. timefeatures-2.1.1/timefeatures/help_html/searchindex.js +1 -0
  40. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/widgets/load-from-db.html +49 -6
  41. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/widgets/save-to-db.html +53 -9
  42. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/widgets/time-feature-constructor.html +33 -2
  43. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/widgets/variable-dependency-graph.html +27 -5
  44. timefeatures-2.1.1/timefeatures/widgets/icons/loaddatadb.svg +1 -0
  45. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/owloadfromdb.py +206 -7
  46. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/owsavetodb.py +182 -146
  47. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/owtimefeaturesconstructor.py +141 -26
  48. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/owvardependencygraph.py +74 -34
  49. timefeatures-2.0.0/README.md +0 -84
  50. timefeatures-2.0.0/imgs/installation.png +0 -0
  51. timefeatures-2.0.0/imgs/workflow.png +0 -0
  52. timefeatures-2.0.0/timefeatures/__init__.py +0 -0
  53. timefeatures-2.0.0/timefeatures/help_html/objects.inv +0 -0
  54. timefeatures-2.0.0/timefeatures/help_html/searchindex.js +0 -1
  55. timefeatures-2.0.0/timefeatures/widgets/icons/loaddatadb.svg +0 -1
  56. {timefeatures-2.0.0 → timefeatures-2.1.1}/LICENSE +0 -0
  57. {timefeatures-2.0.0 → timefeatures-2.1.1}/MANIFEST.in +0 -0
  58. {timefeatures-2.0.0 → timefeatures-2.1.1}/TimeFeatures.egg-info/dependency_links.txt +0 -0
  59. {timefeatures-2.0.0 → timefeatures-2.1.1}/TimeFeatures.egg-info/entry_points.txt +0 -0
  60. {timefeatures-2.0.0 → timefeatures-2.1.1}/TimeFeatures.egg-info/requires.txt +0 -0
  61. {timefeatures-2.0.0 → timefeatures-2.1.1}/TimeFeatures.egg-info/top_level.txt +0 -0
  62. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/Makefile +0 -0
  63. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/installation.rst +0 -0
  64. {timefeatures-2.0.0 → timefeatures-2.1.1}/docs/requirements.txt +0 -0
  65. {timefeatures-2.0.0 → timefeatures-2.1.1}/setup.cfg +0 -0
  66. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help.py +0 -0
  67. /timefeatures-2.0.0/timefeatures/help_html/.buildinfo → /timefeatures-2.1.1/timefeatures/help_html/.buildinfo.bak +0 -0
  68. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_sources/installation.rst.txt +0 -0
  69. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/alabaster.css +0 -0
  70. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/basic.css +0 -0
  71. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/custom.css +0 -0
  72. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/doctools.js +0 -0
  73. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/file.png +0 -0
  74. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/github-banner.svg +0 -0
  75. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/language_data.js +0 -0
  76. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/minus.png +0 -0
  77. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/plus.png +0 -0
  78. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/pygments.css +0 -0
  79. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/searchtools.js +0 -0
  80. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/help_html/_static/sphinx_highlight.js +0 -0
  81. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/__init__.py +0 -0
  82. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/icons/graphgenerator.svg +0 -0
  83. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/icons/savedatadb.svg +0 -0
  84. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/icons/timefeature-xs.svg +0 -0
  85. {timefeatures-2.0.0 → timefeatures-2.1.1}/timefeatures/widgets/icons/timefeature.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TimeFeatures
3
- Version: 2.0.0
3
+ Version: 2.1.1
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
@@ -42,15 +42,37 @@ Dynamic: provides-extra
42
42
  Dynamic: requires-dist
43
43
  Dynamic: summary
44
44
 
45
- Orange3 TimeFeatures
46
- ===============
45
+ # Orange3 TimeFeatures
47
46
 
48
- Timefeatures add-on for [Orange] 3 data mining software for generating synthetic data using datasets with time series, generating graphs of relationships between the generated variables and includes another widget to save the data and configuration tables in a database.
47
+ [![PyPI version](https://img.shields.io/pypi/v/TimeFeatures)](https://pypi.org/project/TimeFeatures/)
48
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
49
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
50
+ [![Orange3](https://img.shields.io/badge/Orange3-add--on-orange)](https://orangedatamining.com/)
51
+
52
+ TimeFeatures is an add-on for [Orange] 3 data mining software for generating synthetic data using datasets with time series, generating graphs of relationships between the generated variables, and includes widgets to save and load data and configuration tables from a database.
49
53
 
50
54
  [Orange]: https://orangedatamining.com/
51
55
 
52
- Installation
53
- ------------
56
+ ## Features
57
+
58
+ - 🕐 **7 time-window functions** — `shift`, `sum`, `mean`, `min`, `max`, `count`, `sd` with full chunk-boundary correctness
59
+ - 🔗 **Chained descriptors** — derived variables can reference each other; topological sort resolves the evaluation order automatically
60
+ - 🛡️ **Secure evaluation** — expressions run in a restricted `eval` sandbox (`__builtins__` replaced, curated whitelist only)
61
+ - 🗄️ **PostgreSQL & MySQL** — persist and reload datasets via SQLAlchemy with dialect-agnostic SQL generation
62
+ - 📊 **Directed weighted dependency graphs** — edge weights reflect temporal window size; visualise in Network Explorer
63
+ - ⚡ **Bulk upload performance** — pandas `DataFrame.to_sql` with chunked multi-row INSERTs
64
+ - 💾 **Workflow persistence** — variable definitions survive save/reload without clicking Send first
65
+
66
+ ## Widgets
67
+
68
+ | Widget | Description |
69
+ |---|---|
70
+ | **Time Features Constructor** | Defines new variables from existing ones using Python-style expressions and time-window functions. Supports chained descriptors with automatic topological sorting. |
71
+ | **Variable Dependency Graph** | Builds a directed, weighted dependency graph from the variable definitions. Edge weights summarise how far back or forward in time each variable looks. |
72
+ | **Save to DB** | Persists the resulting dataset to a SQL database (PostgreSQL or MySQL), with full SQL-injection defences, three write modes (create / overwrite / append) and an optional completion email. |
73
+ | **Load from DB** | Lists datasets previously stored by Save to DB and pulls the chosen one back into Orange, optionally marking the class column directly so no Select Columns widget is needed. |
74
+
75
+ ## Installation
54
76
 
55
77
  ### Orange add-on installer
56
78
 
@@ -64,21 +86,10 @@ To install the add-on with pip use
64
86
 
65
87
  pip install TimeFeatures
66
88
 
67
- To install the add-on from source, run
68
-
69
- python setup.py install
70
-
71
- To register this add-on with Orange, but keep the code in the development directory (do not copy it to
72
- Python's site-packages directory), run
73
-
74
- python setup.py develop
75
-
76
- You can also run
89
+ To install the add-on from source in editable mode, run
77
90
 
78
91
  pip install -e .
79
92
 
80
- which is sometimes preferable as you can *pip uninstall* packages later.
81
-
82
93
  ### Anaconda
83
94
 
84
95
  If using Anaconda Python distribution, simply run
@@ -86,16 +97,18 @@ If using Anaconda Python distribution, simply run
86
97
  pip install TimeFeatures
87
98
 
88
99
  **Required Dependencies**:
100
+
89
101
  * numpy>=1.22.4
90
102
  * AnyQt>=0.2.0
91
- * Orange3>=3.34.0
92
103
  * PyQt5>=5.15.6
93
104
  * PyQtWebEngine>=5.15.6
94
105
  * scipy>=1.7.3
106
+ * SQLAlchemy>=1.4.0
107
+ * psycopg2-binary>=2.9.9
108
+ * PyMySQL>=1.0.0
95
109
  * Orange3-Network>=1.8.0
96
110
 
97
- Usage
98
- -----
111
+ ## Usage
99
112
 
100
113
  After the installation, the widgets from this add-on are registered with Orange. To run Orange from the terminal,
101
114
  use
@@ -108,21 +121,25 @@ or
108
121
 
109
122
  New widgets are in the toolbox bar under Time-Features section.
110
123
 
111
- Documentation
112
- -------------
124
+ ## Documentation
113
125
 
114
126
  The add-on includes Sphinx documentation for each widget. Orange resolves the
115
127
  local HTML pages through its internal Help panel, not through an internet URL.
116
128
  To rebuild the documentation locally, run
117
129
 
118
130
  pip install -e ".[docs]"
131
+ python -m sphinx -b html docs docs/build/html
132
+
133
+ The bundled in-app help is pre-built under `timefeatures/help_html/`. To
134
+ regenerate it (e.g. after editing the `.rst` files), run
135
+
119
136
  python -m sphinx -b html docs timefeatures/help_html
120
137
 
121
138
  Use the widget help action in Orange to open the corresponding page inside the
122
139
  Orange Help window.
123
140
 
124
- Workflow Example
125
- -----
141
+ ## Workflow Example
142
+
126
143
  This is an example of how you can use this add-on.
127
144
 
128
145
  ![Workflow](https://github.com/alervgr/Orange-TimeFeatures/blob/main/imgs/workflow.png?raw=true)
@@ -0,0 +1,101 @@
1
+ # Orange3 TimeFeatures
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/TimeFeatures)](https://pypi.org/project/TimeFeatures/)
4
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
5
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
6
+ [![Orange3](https://img.shields.io/badge/Orange3-add--on-orange)](https://orangedatamining.com/)
7
+
8
+ TimeFeatures is an add-on for [Orange] 3 data mining software for generating synthetic data using datasets with time series, generating graphs of relationships between the generated variables, and includes widgets to save and load data and configuration tables from a database.
9
+
10
+ [Orange]: https://orangedatamining.com/
11
+
12
+ ## Features
13
+
14
+ - 🕐 **7 time-window functions** — `shift`, `sum`, `mean`, `min`, `max`, `count`, `sd` with full chunk-boundary correctness
15
+ - 🔗 **Chained descriptors** — derived variables can reference each other; topological sort resolves the evaluation order automatically
16
+ - 🛡️ **Secure evaluation** — expressions run in a restricted `eval` sandbox (`__builtins__` replaced, curated whitelist only)
17
+ - 🗄️ **PostgreSQL & MySQL** — persist and reload datasets via SQLAlchemy with dialect-agnostic SQL generation
18
+ - 📊 **Directed weighted dependency graphs** — edge weights reflect temporal window size; visualise in Network Explorer
19
+ - ⚡ **Bulk upload performance** — pandas `DataFrame.to_sql` with chunked multi-row INSERTs
20
+ - 💾 **Workflow persistence** — variable definitions survive save/reload without clicking Send first
21
+
22
+ ## Widgets
23
+
24
+ | Widget | Description |
25
+ |---|---|
26
+ | **Time Features Constructor** | Defines new variables from existing ones using Python-style expressions and time-window functions. Supports chained descriptors with automatic topological sorting. |
27
+ | **Variable Dependency Graph** | Builds a directed, weighted dependency graph from the variable definitions. Edge weights summarise how far back or forward in time each variable looks. |
28
+ | **Save to DB** | Persists the resulting dataset to a SQL database (PostgreSQL or MySQL), with full SQL-injection defences, three write modes (create / overwrite / append) and an optional completion email. |
29
+ | **Load from DB** | Lists datasets previously stored by Save to DB and pulls the chosen one back into Orange, optionally marking the class column directly so no Select Columns widget is needed. |
30
+
31
+ ## Installation
32
+
33
+ ### Orange add-on installer
34
+
35
+ Install from Orange add-on installer through Options -> Add-ons.
36
+
37
+ ![Installation](https://github.com/alervgr/Orange-TimeFeatures/blob/main/imgs/installation.png?raw=true)
38
+
39
+ ### Using pip
40
+
41
+ To install the add-on with pip use
42
+
43
+ pip install TimeFeatures
44
+
45
+ To install the add-on from source in editable mode, run
46
+
47
+ pip install -e .
48
+
49
+ ### Anaconda
50
+
51
+ If using Anaconda Python distribution, simply run
52
+
53
+ pip install TimeFeatures
54
+
55
+ **Required Dependencies**:
56
+
57
+ * numpy>=1.22.4
58
+ * AnyQt>=0.2.0
59
+ * PyQt5>=5.15.6
60
+ * PyQtWebEngine>=5.15.6
61
+ * scipy>=1.7.3
62
+ * SQLAlchemy>=1.4.0
63
+ * psycopg2-binary>=2.9.9
64
+ * PyMySQL>=1.0.0
65
+ * Orange3-Network>=1.8.0
66
+
67
+ ## Usage
68
+
69
+ After the installation, the widgets from this add-on are registered with Orange. To run Orange from the terminal,
70
+ use
71
+
72
+ orange-canvas
73
+
74
+ or
75
+
76
+ python3 -m Orange.canvas
77
+
78
+ New widgets are in the toolbox bar under Time-Features section.
79
+
80
+ ## Documentation
81
+
82
+ The add-on includes Sphinx documentation for each widget. Orange resolves the
83
+ local HTML pages through its internal Help panel, not through an internet URL.
84
+ To rebuild the documentation locally, run
85
+
86
+ pip install -e ".[docs]"
87
+ python -m sphinx -b html docs docs/build/html
88
+
89
+ The bundled in-app help is pre-built under `timefeatures/help_html/`. To
90
+ regenerate it (e.g. after editing the `.rst` files), run
91
+
92
+ python -m sphinx -b html docs timefeatures/help_html
93
+
94
+ Use the widget help action in Orange to open the corresponding page inside the
95
+ Orange Help window.
96
+
97
+ ## Workflow Example
98
+
99
+ This is an example of how you can use this add-on.
100
+
101
+ ![Workflow](https://github.com/alervgr/Orange-TimeFeatures/blob/main/imgs/workflow.png?raw=true)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TimeFeatures
3
- Version: 2.0.0
3
+ Version: 2.1.1
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
@@ -42,15 +42,37 @@ Dynamic: provides-extra
42
42
  Dynamic: requires-dist
43
43
  Dynamic: summary
44
44
 
45
- Orange3 TimeFeatures
46
- ===============
45
+ # Orange3 TimeFeatures
47
46
 
48
- Timefeatures add-on for [Orange] 3 data mining software for generating synthetic data using datasets with time series, generating graphs of relationships between the generated variables and includes another widget to save the data and configuration tables in a database.
47
+ [![PyPI version](https://img.shields.io/pypi/v/TimeFeatures)](https://pypi.org/project/TimeFeatures/)
48
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
49
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
50
+ [![Orange3](https://img.shields.io/badge/Orange3-add--on-orange)](https://orangedatamining.com/)
51
+
52
+ TimeFeatures is an add-on for [Orange] 3 data mining software for generating synthetic data using datasets with time series, generating graphs of relationships between the generated variables, and includes widgets to save and load data and configuration tables from a database.
49
53
 
50
54
  [Orange]: https://orangedatamining.com/
51
55
 
52
- Installation
53
- ------------
56
+ ## Features
57
+
58
+ - 🕐 **7 time-window functions** — `shift`, `sum`, `mean`, `min`, `max`, `count`, `sd` with full chunk-boundary correctness
59
+ - 🔗 **Chained descriptors** — derived variables can reference each other; topological sort resolves the evaluation order automatically
60
+ - 🛡️ **Secure evaluation** — expressions run in a restricted `eval` sandbox (`__builtins__` replaced, curated whitelist only)
61
+ - 🗄️ **PostgreSQL & MySQL** — persist and reload datasets via SQLAlchemy with dialect-agnostic SQL generation
62
+ - 📊 **Directed weighted dependency graphs** — edge weights reflect temporal window size; visualise in Network Explorer
63
+ - ⚡ **Bulk upload performance** — pandas `DataFrame.to_sql` with chunked multi-row INSERTs
64
+ - 💾 **Workflow persistence** — variable definitions survive save/reload without clicking Send first
65
+
66
+ ## Widgets
67
+
68
+ | Widget | Description |
69
+ |---|---|
70
+ | **Time Features Constructor** | Defines new variables from existing ones using Python-style expressions and time-window functions. Supports chained descriptors with automatic topological sorting. |
71
+ | **Variable Dependency Graph** | Builds a directed, weighted dependency graph from the variable definitions. Edge weights summarise how far back or forward in time each variable looks. |
72
+ | **Save to DB** | Persists the resulting dataset to a SQL database (PostgreSQL or MySQL), with full SQL-injection defences, three write modes (create / overwrite / append) and an optional completion email. |
73
+ | **Load from DB** | Lists datasets previously stored by Save to DB and pulls the chosen one back into Orange, optionally marking the class column directly so no Select Columns widget is needed. |
74
+
75
+ ## Installation
54
76
 
55
77
  ### Orange add-on installer
56
78
 
@@ -64,21 +86,10 @@ To install the add-on with pip use
64
86
 
65
87
  pip install TimeFeatures
66
88
 
67
- To install the add-on from source, run
68
-
69
- python setup.py install
70
-
71
- To register this add-on with Orange, but keep the code in the development directory (do not copy it to
72
- Python's site-packages directory), run
73
-
74
- python setup.py develop
75
-
76
- You can also run
89
+ To install the add-on from source in editable mode, run
77
90
 
78
91
  pip install -e .
79
92
 
80
- which is sometimes preferable as you can *pip uninstall* packages later.
81
-
82
93
  ### Anaconda
83
94
 
84
95
  If using Anaconda Python distribution, simply run
@@ -86,16 +97,18 @@ If using Anaconda Python distribution, simply run
86
97
  pip install TimeFeatures
87
98
 
88
99
  **Required Dependencies**:
100
+
89
101
  * numpy>=1.22.4
90
102
  * AnyQt>=0.2.0
91
- * Orange3>=3.34.0
92
103
  * PyQt5>=5.15.6
93
104
  * PyQtWebEngine>=5.15.6
94
105
  * scipy>=1.7.3
106
+ * SQLAlchemy>=1.4.0
107
+ * psycopg2-binary>=2.9.9
108
+ * PyMySQL>=1.0.0
95
109
  * Orange3-Network>=1.8.0
96
110
 
97
- Usage
98
- -----
111
+ ## Usage
99
112
 
100
113
  After the installation, the widgets from this add-on are registered with Orange. To run Orange from the terminal,
101
114
  use
@@ -108,21 +121,25 @@ or
108
121
 
109
122
  New widgets are in the toolbox bar under Time-Features section.
110
123
 
111
- Documentation
112
- -------------
124
+ ## Documentation
113
125
 
114
126
  The add-on includes Sphinx documentation for each widget. Orange resolves the
115
127
  local HTML pages through its internal Help panel, not through an internet URL.
116
128
  To rebuild the documentation locally, run
117
129
 
118
130
  pip install -e ".[docs]"
131
+ python -m sphinx -b html docs docs/build/html
132
+
133
+ The bundled in-app help is pre-built under `timefeatures/help_html/`. To
134
+ regenerate it (e.g. after editing the `.rst` files), run
135
+
119
136
  python -m sphinx -b html docs timefeatures/help_html
120
137
 
121
138
  Use the widget help action in Orange to open the corresponding page inside the
122
139
  Orange Help window.
123
140
 
124
- Workflow Example
125
- -----
141
+ ## Workflow Example
142
+
126
143
  This is an example of how you can use this add-on.
127
144
 
128
145
  ![Workflow](https://github.com/alervgr/Orange-TimeFeatures/blob/main/imgs/workflow.png?raw=true)
@@ -21,9 +21,15 @@ docs/widgets/time-feature-constructor.rst
21
21
  docs/widgets/variable-dependency-graph.rst
22
22
  imgs/installation.png
23
23
  imgs/workflow.png
24
+ imgs/widgets/owloadfromdb.png
25
+ imgs/widgets/owsavetodb.png
26
+ imgs/widgets/owtimefeaturesconstructor.png
27
+ imgs/widgets/owvariabledependencygraph.png
24
28
  timefeatures/__init__.py
29
+ timefeatures/__version__.py
25
30
  timefeatures/help.py
26
31
  timefeatures/help_html/.buildinfo
32
+ timefeatures/help_html/.buildinfo.bak
27
33
  timefeatures/help_html/changes.html
28
34
  timefeatures/help_html/genindex.html
29
35
  timefeatures/help_html/index.html
@@ -31,6 +37,10 @@ timefeatures/help_html/installation.html
31
37
  timefeatures/help_html/objects.inv
32
38
  timefeatures/help_html/search.html
33
39
  timefeatures/help_html/searchindex.js
40
+ timefeatures/help_html/_images/owloadfromdb.png
41
+ timefeatures/help_html/_images/owsavetodb.png
42
+ timefeatures/help_html/_images/owtimefeaturesconstructor.png
43
+ timefeatures/help_html/_images/owvariabledependencygraph.png
34
44
  timefeatures/help_html/_sources/changes.rst.txt
35
45
  timefeatures/help_html/_sources/index.rst.txt
36
46
  timefeatures/help_html/_sources/installation.rst.txt
@@ -1,8 +1,8 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- Unreleased
5
- ----------
4
+ 2.1.1 — 2026-06-09
5
+ -------------------
6
6
 
7
7
  **Load from DB (new widget)**
8
8
 
@@ -22,6 +22,22 @@ Unreleased
22
22
  - Workflow-persisted settings: ``selected_dataset`` and
23
23
  ``selected_class`` are ``Setting(..., schema_only=True)``, restored
24
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.
25
41
 
26
42
  **Variable Dependency Graph**
27
43
 
@@ -31,6 +47,17 @@ Unreleased
31
47
  reference the dependency. Plain (non-temporal) references default to
32
48
  weight ``1``. The weights live in ``network.edges[0].edges.data``
33
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.
34
61
  - Refactor: flattened the ``from_row_col`` / ``grafo`` decorator pattern
35
62
  into a single, documented ``build_dependency_network`` function.
36
63
  - Performance: O(n³) → O(n²) by precomputing a ``name → index`` map and
@@ -42,6 +69,16 @@ Unreleased
42
69
 
43
70
  **Time Features Constructor**
44
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.
45
82
  - *Fixed (critical):* time-window functions used to lose context every
46
83
  5 000 rows because Orange chunks tables during ``transform``. The
47
84
  widget now caches the full source per ``FeatureFunc`` and returns the
@@ -68,6 +105,15 @@ Unreleased
68
105
 
69
106
  **Save to DB**
70
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.
71
117
  - *New:* **MySQL support**. The connection panel now exposes a
72
118
  database-type selector (PostgreSQL / MySQL). Per-dialect column
73
119
  types and identifier quoting (``"name"`` vs ``\`name\```) live in
@@ -10,7 +10,11 @@ sys.path.insert(0, str(ROOT))
10
10
  project = "TimeFeatures"
11
11
  author = "Alejandro Rivas Garcia"
12
12
  copyright = "2026, Alejandro Rivas Garcia"
13
- release = "1.0.18"
13
+
14
+ # Read version from the single source of truth.
15
+ _version_globals = {}
16
+ exec((ROOT / "timefeatures" / "__version__.py").read_text(encoding="utf-8"), _version_globals)
17
+ release = _version_globals["__version__"]
14
18
  version = ".".join(release.split(".")[:2])
15
19
 
16
20
  # -- General configuration ------------------------------------------------
@@ -47,7 +51,7 @@ html_theme_options = {
47
51
  "description": (
48
52
  "Time-series feature engineering for Orange3: build derived "
49
53
  "variables, visualise their dependencies, and persist data to "
50
- "PostgreSQL."
54
+ "PostgreSQL or MySQL."
51
55
  ),
52
56
  "github_user": "alervgr",
53
57
  "github_repo": "Orange-TimeFeatures",
@@ -81,11 +81,20 @@ Project
81
81
  Building this documentation
82
82
  ---------------------------
83
83
 
84
+ **Development build** (for previewing locally):
85
+
84
86
  .. code-block:: bash
85
87
 
86
88
  pip install -e ".[docs]"
87
89
  python -m sphinx -b html docs docs/build/html
88
90
 
91
+ **In-app help** (bundled with the wheel so Orange's Help panel works
92
+ offline):
93
+
94
+ .. code-block:: bash
95
+
96
+ python -m sphinx -b html docs timefeatures/help_html
97
+
89
98
  The HTML build is also bundled with the wheel so Orange's in-app help
90
99
  panel can resolve every widget's *Help* action without internet
91
100
  access.
@@ -7,6 +7,11 @@ connects to a SQL database, lists the datasets previously persisted by
7
7
  ``Table`` — optionally marking the class column on the fly so no
8
8
  **Select Columns** widget is needed downstream.
9
9
 
10
+ .. figure:: ../../imgs/widgets/owloadfromdb.png
11
+ :alt: Load from DB widget interface.
12
+
13
+ The Load from DB widget.
14
+
10
15
  Inputs
11
16
  ------
12
17
 
@@ -48,9 +53,21 @@ Controls
48
53
  host/db (N datasets)", "Loaded <name> (N rows)"), error
49
54
  ("Connection failed: …", "Load failed: …").
50
55
  * - Dataset
51
- - Combo populated from ``SELECT * FROM datasets ORDER BY
52
- datetime DESC``. The most recent upload comes first; the last
53
- choice is restored when reopening a workflow.
56
+ - Searchable combo populated from ``SELECT * FROM datasets ORDER
57
+ BY datetime DESC``. The most recent upload comes first; the
58
+ last choice is restored when reopening a workflow. Type to
59
+ filter the visible items — handy when the registry grows large.
60
+ * - ↻ (Refresh)
61
+ - Small button to the right of the Dataset combo. Re-runs the
62
+ list query without dropping the connection. Useful if another
63
+ Orange canvas (or a parallel tool) just published a new
64
+ dataset while this widget was open.
65
+ * - Delete
66
+ - Drops the currently selected dataset's table from the database
67
+ and removes its row in ``datasets``. Gated by a confirmation
68
+ dialog — there is no Orange-side undo. The operation runs on a
69
+ background thread, so the canvas stays responsive even if the
70
+ table is large.
54
71
  * - Dataset info
55
72
  - Read-only block under the combo: save timestamp, row/column
56
73
  counts and the original class column recorded by **Save to DB**.
@@ -60,7 +77,9 @@ Controls
60
77
  choice, (2) the ``class_name`` stored in the ``datasets``
61
78
  metadata, (3) ``(no class)`` if none of the above apply.
62
79
  * - Load
63
- - Triggers the actual download.
80
+ - Triggers the actual download. Skipped automatically on the
81
+ first connection after a workflow reopen if the persisted
82
+ dataset name is still available (see *Auto-load* below).
64
83
 
65
84
  How it Works
66
85
  ------------
@@ -88,6 +107,28 @@ While any worker runs, the form controls (database type, connection
88
107
  fields, **Connect**, **Load**, dataset and class combos) are
89
108
  temporarily disabled and the status label keeps the user informed.
90
109
 
110
+ Auto-load
111
+ ---------
112
+
113
+ When you reopen a workflow that already had a Load from DB widget with
114
+ a saved ``selected_dataset``, the widget fires Load automatically the
115
+ first time the dataset listing comes back successfully. The data flows
116
+ out of the **Data** output without a single click, mirroring how Orange
117
+ treats sources like **File** and **Datasets**.
118
+
119
+ Subtleties:
120
+
121
+ - Auto-load is a *one-shot* per widget lifetime. Manually clicking
122
+ **Refresh** clears the pending flag, so a Refresh never surprises
123
+ the user by loading something behind their back.
124
+ - If the persisted dataset no longer exists on the server (deleted
125
+ from outside, or the registry was wiped), the flag is cleared and
126
+ the widget just shows the available list — no error.
127
+ - If a different backend or set of credentials is restored, the user
128
+ still has to click **Connect** explicitly, just like in earlier
129
+ versions; auto-load happens *after* the first successful connection
130
+ + listing.
131
+
91
132
  Workflow Persistence
92
133
  --------------------
93
134
 
@@ -7,6 +7,11 @@ database. Two dialects are supported out of the box:
7
7
  - **PostgreSQL** — through ``psycopg2``.
8
8
  - **MySQL** — through ``pymysql``.
9
9
 
10
+ .. figure:: ../../imgs/widgets/owsavetodb.png
11
+ :alt: Save to DB widget interface.
12
+
13
+ The Save to DB widget.
14
+
10
15
  Both drivers are reached via **SQLAlchemy**, which keeps the SQL
11
16
  generation, identifier quoting and type rendering dialect-agnostic. The
12
17
  actual upload uses a `pandas <https://pandas.pydata.org/>`_ DataFrame
@@ -59,6 +64,21 @@ TimeFeatures-specific controls:
59
64
  - Destination table name. Validated against PostgreSQL identifier
60
65
  rules (see *Validation* below); MySQL accepts a superset, so
61
66
  the same rule is safe on both.
67
+ * - Mode
68
+ - Combo between the Table name and the Email fields:
69
+
70
+ - **Create new (fail if table exists)** — default, refuses to
71
+ touch an existing table or metadata row. Use this for first
72
+ uploads or when you want a clear error on accidental name
73
+ collisions.
74
+ - **Overwrite (drop and recreate)** — drops the existing data
75
+ table and the matching ``datasets`` row before uploading,
76
+ then recreates them. Re-running the workflow stops breaking.
77
+ - **Append (keep existing rows)** — adds rows to the existing
78
+ table (creating it if it doesn't exist). After the upload,
79
+ the widget runs ``SELECT COUNT(*)`` and rewrites the
80
+ ``datasets`` row with the *actual* total row count, so the
81
+ registry stays accurate across repeated appends.
62
82
  * - Email
63
83
  - Optional notification address. A summary email is sent once the
64
84
  upload finishes, including the table name, row / column counts,
@@ -79,12 +99,32 @@ When **Save** is clicked, the widget:
79
99
 
80
100
  - converts the dataset to a pandas DataFrame with
81
101
  ``Orange.data.pandas_compat.table_to_frame(include_metas=True)``
82
- and reorders the columns (class first, then metas in domain order,
83
- then attributes) to match the existing schema convention;
84
- - creates the ``datasets`` metadata table if it doesn't exist;
85
- - inserts one row into ``datasets`` describing this upload;
86
- - writes the dataset itself in ``PANDAS_SQL_CHUNKSIZE`` chunks
87
- (default ``1 000``) via ``df.to_sql(..., method='multi')``.
102
+ and reorders the columns (class first, then metas in domain
103
+ order, then attributes) to match the existing schema convention;
104
+ - ensures the ``datasets`` metadata table exists;
105
+ - applies the mode-specific preparation:
106
+
107
+ - **create** fail fast if a ``datasets`` row with this name
108
+ already exists.
109
+ - **overwrite** — ``DROP TABLE IF EXISTS`` on the target plus
110
+ ``DELETE`` of the matching ``datasets`` row.
111
+ - **append** — leave everything in place; the upload itself will
112
+ create the table on the first chunk if it doesn't exist.
113
+
114
+ - writes the dataset in ``PANDAS_SQL_CHUNKSIZE`` chunks (default
115
+ ``1 000``) via ``df.to_sql(..., method='multi')`` with the
116
+ ``if_exists`` value tailored to the mode (see
117
+ ``_pandas_if_exists`` for the exact table);
118
+ - runs ``SELECT COUNT(*)`` on the target table and re-inserts the
119
+ ``datasets`` row with that real row count, so the registry stays
120
+ consistent even after multiple appends.
121
+
122
+ Everything happens inside a single SQLAlchemy transaction
123
+ (``engine.begin()``), so a mid-upload error rolls every step back on
124
+ PostgreSQL. MySQL auto-commits DDL (``DROP TABLE``, ``CREATE TABLE``),
125
+ so an Overwrite that crashes during the upload may leave you without
126
+ the original table — there's no way around that without engine-level
127
+ support.
88
128
 
89
129
  While the worker runs, the widget's progress bar and status label are
90
130
  updated through Qt signals; the **Save**, **Connect** and form controls