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.
Files changed (84) hide show
  1. {timefeatures-1.0.18/TimeFeatures.egg-info → timefeatures-2.1.0}/PKG-INFO +7 -2
  2. {timefeatures-1.0.18 → timefeatures-2.1.0}/README.md +4 -1
  3. {timefeatures-1.0.18 → timefeatures-2.1.0/TimeFeatures.egg-info}/PKG-INFO +7 -2
  4. {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/SOURCES.txt +11 -0
  5. {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/requires.txt +2 -0
  6. timefeatures-2.1.0/docs/changes.rst +167 -0
  7. timefeatures-2.1.0/docs/conf.py +62 -0
  8. timefeatures-2.1.0/docs/index.rst +97 -0
  9. timefeatures-2.1.0/docs/installation.rst +103 -0
  10. timefeatures-2.1.0/docs/widgets/load-from-db.rst +172 -0
  11. timefeatures-2.1.0/docs/widgets/save-to-db.rst +220 -0
  12. timefeatures-2.1.0/docs/widgets/time-feature-constructor.rst +209 -0
  13. timefeatures-2.1.0/docs/widgets/variable-dependency-graph.rst +174 -0
  14. {timefeatures-1.0.18 → timefeatures-2.1.0}/setup.py +3 -1
  15. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/.buildinfo +1 -1
  16. timefeatures-2.1.0/timefeatures/help_html/_sources/changes.rst.txt +167 -0
  17. timefeatures-2.1.0/timefeatures/help_html/_sources/index.rst.txt +97 -0
  18. timefeatures-2.1.0/timefeatures/help_html/_sources/installation.rst.txt +103 -0
  19. timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/load-from-db.rst.txt +172 -0
  20. timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/save-to-db.rst.txt +220 -0
  21. timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt +209 -0
  22. timefeatures-2.1.0/timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt +174 -0
  23. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/alabaster.css +6 -1
  24. timefeatures-2.1.0/timefeatures/help_html/changes.html +287 -0
  25. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/genindex.html +42 -27
  26. timefeatures-2.1.0/timefeatures/help_html/index.html +226 -0
  27. timefeatures-2.1.0/timefeatures/help_html/installation.html +231 -0
  28. timefeatures-2.1.0/timefeatures/help_html/objects.inv +0 -0
  29. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/search.html +59 -44
  30. timefeatures-2.1.0/timefeatures/help_html/searchindex.js +1 -0
  31. timefeatures-2.1.0/timefeatures/help_html/widgets/load-from-db.html +298 -0
  32. timefeatures-2.1.0/timefeatures/help_html/widgets/save-to-db.html +356 -0
  33. timefeatures-2.1.0/timefeatures/help_html/widgets/time-feature-constructor.html +346 -0
  34. timefeatures-2.1.0/timefeatures/help_html/widgets/variable-dependency-graph.html +324 -0
  35. timefeatures-2.1.0/timefeatures/widgets/icons/loaddatadb.svg +1 -0
  36. timefeatures-2.1.0/timefeatures/widgets/owloadfromdb.py +752 -0
  37. timefeatures-2.1.0/timefeatures/widgets/owsavetodb.py +886 -0
  38. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/owtimefeaturesconstructor.py +149 -32
  39. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/owvardependencygraph.py +114 -25
  40. timefeatures-1.0.18/docs/conf.py +0 -26
  41. timefeatures-1.0.18/docs/index.rst +0 -37
  42. timefeatures-1.0.18/docs/widgets/save-to-db.rst +0 -70
  43. timefeatures-1.0.18/docs/widgets/time-feature-constructor.rst +0 -100
  44. timefeatures-1.0.18/docs/widgets/variable-dependency-graph.rst +0 -66
  45. timefeatures-1.0.18/timefeatures/help_html/_sources/index.rst.txt +0 -37
  46. timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/save-to-db.rst.txt +0 -70
  47. timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/time-feature-constructor.rst.txt +0 -100
  48. timefeatures-1.0.18/timefeatures/help_html/_sources/widgets/variable-dependency-graph.rst.txt +0 -66
  49. timefeatures-1.0.18/timefeatures/help_html/index.html +0 -135
  50. timefeatures-1.0.18/timefeatures/help_html/objects.inv +0 -6
  51. timefeatures-1.0.18/timefeatures/help_html/searchindex.js +0 -1
  52. timefeatures-1.0.18/timefeatures/help_html/widgets/save-to-db.html +0 -185
  53. timefeatures-1.0.18/timefeatures/help_html/widgets/time-feature-constructor.html +0 -219
  54. timefeatures-1.0.18/timefeatures/help_html/widgets/variable-dependency-graph.html +0 -181
  55. timefeatures-1.0.18/timefeatures/widgets/owsavetodb.py +0 -401
  56. {timefeatures-1.0.18 → timefeatures-2.1.0}/LICENSE +0 -0
  57. {timefeatures-1.0.18 → timefeatures-2.1.0}/MANIFEST.in +0 -0
  58. {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/dependency_links.txt +0 -0
  59. {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/entry_points.txt +0 -0
  60. {timefeatures-1.0.18 → timefeatures-2.1.0}/TimeFeatures.egg-info/top_level.txt +0 -0
  61. {timefeatures-1.0.18 → timefeatures-2.1.0}/docs/Makefile +0 -0
  62. {timefeatures-1.0.18 → timefeatures-2.1.0}/docs/requirements.txt +0 -0
  63. {timefeatures-1.0.18 → timefeatures-2.1.0}/imgs/installation.png +0 -0
  64. {timefeatures-1.0.18 → timefeatures-2.1.0}/imgs/workflow.png +0 -0
  65. {timefeatures-1.0.18 → timefeatures-2.1.0}/setup.cfg +0 -0
  66. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/__init__.py +0 -0
  67. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help.py +0 -0
  68. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/basic.css +0 -0
  69. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/custom.css +0 -0
  70. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/doctools.js +0 -0
  71. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/documentation_options.js +0 -0
  72. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/file.png +0 -0
  73. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/github-banner.svg +0 -0
  74. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/language_data.js +0 -0
  75. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/minus.png +0 -0
  76. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/plus.png +0 -0
  77. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/pygments.css +0 -0
  78. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/searchtools.js +0 -0
  79. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/help_html/_static/sphinx_highlight.js +0 -0
  80. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/__init__.py +0 -0
  81. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/graphgenerator.svg +0 -0
  82. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/savedatadb.svg +0 -0
  83. {timefeatures-1.0.18 → timefeatures-2.1.0}/timefeatures/widgets/icons/timefeature-xs.svg +0 -0
  84. {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.18
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.18
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
@@ -3,7 +3,9 @@ AnyQt>=0.2.0
3
3
  PyQt5>=5.15.6
4
4
  PyQtWebEngine>=5.15.6
5
5
  scipy>=1.7.3
6
+ SQLAlchemy>=1.4.0
6
7
  psycopg2-binary>=2.9.9
8
+ PyMySQL>=1.0.0
7
9
  Orange3-Network>=1.8.0
8
10
 
9
11
  [docs]
@@ -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.