listpick 0.1.15.20__tar.gz → 0.1.16.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.

Potentially problematic release.


This version of listpick might be problematic. Click here for more details.

Files changed (64) hide show
  1. {listpick-0.1.15.20 → listpick-0.1.16.0}/CHANGELOG.md +6 -0
  2. {listpick-0.1.15.20/src/listpick.egg-info → listpick-0.1.16.0}/PKG-INFO +1 -1
  3. {listpick-0.1.15.20 → listpick-0.1.16.0}/TODO.md +1 -0
  4. listpick-0.1.16.0/examples/data_generation/video_duplicates.toml +39 -0
  5. {listpick-0.1.15.20 → listpick-0.1.16.0}/setup.py +1 -1
  6. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/listpick_app.py +19 -8
  7. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/pane/get_data.py +20 -0
  8. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/pane/pane_functions.py +45 -5
  9. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/pane/pane_utils.py +1 -1
  10. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/generate_data.py +20 -1
  11. {listpick-0.1.15.20 → listpick-0.1.16.0/src/listpick.egg-info}/PKG-INFO +1 -1
  12. listpick-0.1.15.20/examples/data_generation/video_duplicates.toml +0 -36
  13. {listpick-0.1.15.20 → listpick-0.1.16.0}/.gitignore +0 -0
  14. {listpick-0.1.15.20 → listpick-0.1.16.0}/LICENSE.txt +0 -0
  15. {listpick-0.1.15.20 → listpick-0.1.16.0}/README.md +0 -0
  16. {listpick-0.1.15.20 → listpick-0.1.16.0}/assets/aria2tui_screenshot.png +0 -0
  17. {listpick-0.1.15.20 → listpick-0.1.16.0}/assets/file_compare.png +0 -0
  18. {listpick-0.1.15.20 → listpick-0.1.16.0}/assets/lpfman.png +0 -0
  19. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/data_generation/list_files.toml +0 -0
  20. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/data_generation/list_files_empty.toml +0 -0
  21. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/data_generation/video_mediainfo.toml +0 -0
  22. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/input_files/polynomials.tsv +0 -0
  23. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/input_guides/gnuplot_graph.md +0 -0
  24. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/picker/auxiallary_files/2024-25_Premier_League.pkl +0 -0
  25. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/picker/footer_string_example.py +0 -0
  26. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/picker/picker_example.py +0 -0
  27. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/picker/template.py +0 -0
  28. {listpick-0.1.15.20 → listpick-0.1.16.0}/examples/picker/wikipedia_table.py +0 -0
  29. {listpick-0.1.15.20 → listpick-0.1.16.0}/listpick.py +0 -0
  30. {listpick-0.1.15.20 → listpick-0.1.16.0}/requirements.txt +0 -0
  31. {listpick-0.1.15.20 → listpick-0.1.16.0}/setup.cfg +0 -0
  32. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/__init__.py +0 -0
  33. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/__main__.py +0 -0
  34. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/pane/__init__.py +0 -0
  35. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/__init__.py +0 -0
  36. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/build_help.py +0 -0
  37. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/footer.py +0 -0
  38. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/help_screen.py +0 -0
  39. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/input_field.py +0 -0
  40. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/keys.py +0 -0
  41. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/ui/picker_colours.py +0 -0
  42. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/__init__.py +0 -0
  43. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/clipboard_operations.py +0 -0
  44. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/config.py +0 -0
  45. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/dump.py +0 -0
  46. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/filtering.py +0 -0
  47. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/graphing.py +0 -0
  48. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/keycodes.py +0 -0
  49. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/options_selectors.py +0 -0
  50. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/paste_operations.py +0 -0
  51. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/picker_log.py +0 -0
  52. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/search_and_filter_utils.py +0 -0
  53. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/searching.py +0 -0
  54. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/sorting.py +0 -0
  55. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/table_to_list_of_lists.py +0 -0
  56. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/user_input.py +0 -0
  57. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick/utils/utils.py +0 -0
  58. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick.egg-info/SOURCES.txt +0 -0
  59. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick.egg-info/dependency_links.txt +0 -0
  60. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick.egg-info/entry_points.txt +0 -0
  61. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick.egg-info/requires.txt +0 -0
  62. {listpick-0.1.15.20 → listpick-0.1.16.0}/src/listpick.egg-info/top_level.txt +0 -0
  63. {listpick-0.1.15.20 → listpick-0.1.16.0}/tests/kitty_control.sh +0 -0
  64. {listpick-0.1.15.20 → listpick-0.1.16.0}/tests/sorting_dates.csv +0 -0
@@ -1,5 +1,11 @@
1
1
  # CHANGELOG.md
2
2
  Note that the changes between 0.1.11.0 and 1.1.12.0 are listed under 0.1.11
3
+
4
+ ## [0.1.16.0] 2025-09-05
5
+ - Data generation is now multithreaded.
6
+ - ~5x quicker when getting data for video files
7
+
8
+
3
9
  ## [0.1.15.20] 2025-08-31
4
10
  - Fixed screen refresh function for default options selector.
5
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.15.20
3
+ Version: 0.1.16.0
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
@@ -388,6 +388,7 @@
388
388
  > - [x] Update footer height when there is a search query.
389
389
  > - [x] Header columns are not aligned with long header values.
390
390
  > - [x] Done: 2025-08-27
391
+ > - [ ] Pressing page forward/page back in an empty picker changes the index in the footer from 0 to 1...
391
392
 
392
393
 
393
394
 
@@ -0,0 +1,39 @@
1
+ #
2
+ # video_duplicates.toml
3
+ # Generate list of mp4 files along with their: sha1, duration, width, height, and size.
4
+ #
5
+ # Author: GrimAndGreedy
6
+ # License: MIT
7
+
8
+
9
+ [environment]
10
+ cwd="~/Downloads/new"
11
+ # cwd="~/Videos/"
12
+
13
+ [data]
14
+ # files_command = "eza -1 --no-quotes | grep -E mp4$"
15
+
16
+ commands = [
17
+ """eza -1 --no-quotes | grep -E mp4$""",
18
+ # """sha1sum {} | awk '{{print $1}}'""",
19
+ # """ffprobe -show_entries format=duration -v quiet -of csv="p=0" -i {}""",
20
+ # """ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 {}""",
21
+ # """ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 {}""",
22
+ """mediainfo --Inform="Video;%Duration%" {}""",
23
+ """mediainfo --Inform="Video;%Width%" {}""",
24
+ """mediainfo --Inform="Video;%Height%" {}""",
25
+ """du -hs {} | awk '{{ print $1 }}'""",
26
+ ]
27
+
28
+ header = [
29
+ "file",
30
+ # "sha1",
31
+ "duration",
32
+ "width",
33
+ "height",
34
+ "size",
35
+ ]
36
+
37
+ # run = [
38
+ # "mpv",
39
+ # ]
@@ -16,7 +16,7 @@ with open("README.md", "r", encoding = "utf-8") as fh:
16
16
 
17
17
  setuptools.setup(
18
18
  name = "listpick",
19
- version = "0.1.15.20",
19
+ version = "0.1.16.0",
20
20
  author = "Grim",
21
21
  author_email = "grimandgreedy@protonmail.com",
22
22
  description = "Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.",
@@ -42,7 +42,7 @@ from listpick.ui.build_help import build_help_rows
42
42
  from listpick.ui.footer import StandardFooter, CompactFooter, NoFooter
43
43
  from listpick.utils.picker_log import setup_logger
44
44
  from listpick.utils.user_input import get_char, open_tty
45
- from listpick.pane.pane_functions import right_split_file_attributes, right_split_graph, right_split_display_list
45
+ from listpick.pane.pane_functions import right_split_file_attributes, right_split_file_attributes_dynamic, right_split_graph, right_split_display_list
46
46
  from listpick.pane.get_data import *
47
47
 
48
48
 
@@ -127,17 +127,18 @@ class Picker:
127
127
  columns_sort_method: list[int] = [0],
128
128
  key_chain: str = "",
129
129
  last_key: Optional[str] = None,
130
+ disabled_keys: list=[],
130
131
 
131
132
  paginate: bool =False,
132
133
  cancel_is_back: bool = False,
133
134
  mode_index: int = 0,
134
135
  modes: list[dict] = [],
135
- display_modes: bool =False,
136
- require_option: list=[],
137
- require_option_default: list=[],
136
+ display_modes: bool = False,
137
+ require_option: list[bool] = [],
138
+ require_option_default: bool = False,
138
139
  option_functions: list[Callable[..., Tuple[bool, str]]] = [],
139
140
  default_option_function: Callable[..., Tuple[bool, str]] = default_option_input,
140
- disabled_keys: list=[],
141
+
141
142
 
142
143
  show_header: bool = True,
143
144
  show_row_header: bool = False,
@@ -195,6 +196,7 @@ class Picker:
195
196
  split_right: bool = False,
196
197
  right_panes: list = [],
197
198
  right_pane_index: int = 0,
199
+
198
200
  ):
199
201
  self.stdscr = stdscr
200
202
  self.items = items
@@ -3975,7 +3977,7 @@ def main() -> None:
3975
3977
  # function_data["debug_level"] = 1
3976
3978
 
3977
3979
  function_data["split_right"] = False
3978
- function_data["right_pane_index"] = 3
3980
+ function_data["right_pane_index"] = 2
3979
3981
 
3980
3982
  function_data["right_panes"] = [
3981
3983
  # Graph or random numbers generated each second
@@ -3996,15 +3998,24 @@ def main() -> None:
3996
3998
  "data": ["Files", [str(x) for x in range(100)]],
3997
3999
  "refresh_time": 1.0,
3998
4000
  },
3999
- # File attribures
4001
+ # File attributes
4000
4002
  {
4001
4003
  "proportion": 2/3,
4002
4004
  "auto_refresh": False,
4003
4005
  "get_data": lambda data, state: [],
4004
4006
  "display": right_split_file_attributes,
4005
- "data": ["Files", [str(x) for x in range(100)]],
4007
+ "data": [],
4006
4008
  "refresh_time": 1.0,
4007
4009
  },
4010
+ # File attributes dynamic
4011
+ {
4012
+ "proportion": 2/3,
4013
+ "auto_refresh": True,
4014
+ "get_data": update_file_attributes,
4015
+ "display": right_split_file_attributes_dynamic,
4016
+ "data": [],
4017
+ "refresh_time": 2.0,
4018
+ },
4008
4019
  # List of random numbers generated each second
4009
4020
  {
4010
4021
  "proportion": 1/2,
@@ -8,6 +8,8 @@ Author: GrimAndGreedy
8
8
  License: MIT
9
9
  """
10
10
 
11
+ from listpick.pane.pane_utils import get_file_attributes
12
+
11
13
  def data_refresh_randint_by_row(data, state):
12
14
  """
13
15
  Add a random number to the data if row id is the same.
@@ -93,3 +95,21 @@ def get_dl(data, state):
93
95
  data[0].append(data[0][-1]+1)
94
96
  data[1].append(dl)
95
97
  return data
98
+
99
+
100
+ def update_file_attributes(data, state):
101
+ """
102
+ Get file attributes
103
+
104
+ data[0]: ["size: {}", filetype: {}, last modified: {}]
105
+ ]
106
+ data[1]: id
107
+ """
108
+ if state["indexed_items"]:
109
+ # id = state["indexed_items"][state["cursor_pos"]][1][state["id_column"]]
110
+ id = state["indexed_items"][state["cursor_pos"]][1][0]
111
+ else:
112
+ return [[], -1]
113
+ return [get_file_attributes(id), id]
114
+
115
+
@@ -11,15 +11,14 @@ License: MIT
11
11
  import curses
12
12
  import os
13
13
  from listpick.pane.pane_utils import get_file_attributes, get_graph_string, escape_ansi
14
+ from listpick.pane.get_data import update_file_attributes
14
15
 
15
- def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, past_data: list = [], data: list = [], test: bool = False):
16
+ def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
16
17
  """
17
18
  Display file attributes in right pane.
18
19
  """
19
20
  if test: return True
20
21
 
21
- os.chdir(os.path.expanduser("~/Downloads/new"))
22
-
23
22
  # Title
24
23
  title = "File attributes"
25
24
  if len(title) < w: title = f"{title:^{w}}"
@@ -45,7 +44,48 @@ def right_split_file_attributes(stdscr, x, y, w, h, state, row, cell, past_data:
45
44
 
46
45
  return []
47
46
 
48
- def right_split_graph(stdscr, x, y, w, h, state, row, cell, past_data: list = [], data: list = [], test: bool = False):
47
+
48
+ def right_split_file_attributes_dynamic(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
49
+ """
50
+ Display file attributes in right pane.
51
+ """
52
+ if test: return True
53
+
54
+ # Title
55
+ title = "File attributes"
56
+ if len(title) < w: title = f"{title:^{w}}"
57
+ stdscr.addstr(y, x,title[:w], curses.color_pair(state["colours_start"]+4) | curses.A_BOLD)
58
+
59
+ # Separator
60
+ for j in range(h):
61
+ stdscr.addstr(j+y, x, ' ', curses.color_pair(state["colours_start"]+16))
62
+
63
+ # Display pane count
64
+ pane_count = len(state["right_panes"])
65
+ pane_index = state["right_pane_index"]
66
+ if pane_count > 1:
67
+ s = f" {pane_index+1}/{pane_count} "
68
+ stdscr.addstr(y+h-1, x+w-len(s)-1, s, curses.color_pair(state["colours_start"]+20))
69
+
70
+ if len(state["indexed_items"]) == 0:
71
+ return []
72
+
73
+ # Filename/cursor cell value
74
+ stdscr.addstr(y+2, x+2, cell[:w-3])
75
+
76
+ # If the cursor-hovered file is different then reload the data
77
+ if data[1] != cell:
78
+ data[:] = update_file_attributes(data, state)
79
+
80
+ # attributes = get_file_attributes(cell)
81
+ if len(data) == 0: return []
82
+ attributes = data[0]
83
+ for i, attr in enumerate(attributes):
84
+ stdscr.addstr(y+3+i, x+4, attr[:w-5])
85
+
86
+ return []
87
+
88
+ def right_split_graph(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
49
89
  """
50
90
  Display a graph of the data in right pane.
51
91
 
@@ -95,7 +135,7 @@ def right_split_graph(stdscr, x, y, w, h, state, row, cell, past_data: list = []
95
135
 
96
136
 
97
137
 
98
- def right_split_display_list(stdscr, x, y, w, h, state, row, cell, past_data: list = [], data: list = [], test: bool = False):
138
+ def right_split_display_list(stdscr, x, y, w, h, state, row, cell, data: list = [], test: bool = False):
99
139
  """
100
140
  data[0]:str = title
101
141
  data[1]:list[str] = list of strings to display
@@ -83,6 +83,6 @@ def get_file_attributes(filename):
83
83
  return attributes
84
84
 
85
85
  except Exception as e:
86
- print(f"An error occurred: {e}")
86
+ # print(f"An error occurred: {e}")
87
87
  return []
88
88
 
@@ -15,8 +15,27 @@ import toml
15
15
  import logging
16
16
 
17
17
  logger = logging.getLogger('picker_log')
18
+ import concurrent.futures
18
19
 
19
20
  def generate_columns(funcs: list, files: list) -> list[list[str]]:
21
+ """
22
+ Takes a list of functions and a list of files.
23
+ Tasks are run in parallel using concurrent.futures.
24
+ """
25
+ logger.info("function: generate_columns (generate_data.py)")
26
+
27
+ results = []
28
+ # Create a future object for each combination of func and file
29
+ with concurrent.futures.ThreadPoolExecutor() as executor:
30
+ futures = [[executor.submit(func, file) for func in funcs] for file in files]
31
+
32
+ for file_futures in futures:
33
+ result = [future.result() for future in file_futures]
34
+ results.append(result)
35
+ return results
36
+
37
+
38
+ def generate_columns_single_thread(funcs: list, files: list) -> list[list[str]]:
20
39
  """
21
40
  Takes a list of functions and a list of files. Each function is run for each file and a list of lists is returned.
22
41
  """
@@ -30,7 +49,7 @@ def generate_columns(funcs: list, files: list) -> list[list[str]]:
30
49
  except:
31
50
  item.append("")
32
51
  items.append(item)
33
-
52
+
34
53
  return items
35
54
 
36
55
  def command_to_func(command: str) -> Callable:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: listpick
3
- Version: 0.1.15.20
3
+ Version: 0.1.16.0
4
4
  Summary: Listpick is a powerful TUI data tool for creating TUI apps or viewing/comparing tabulated data.
5
5
  Home-page: https://github.com/grimandgreedy/listpick
6
6
  Author: Grim
@@ -1,36 +0,0 @@
1
- #
2
- # video_duplicates.toml
3
- # Generate list of mp4 files along with their: sha1, duration, width, height, and size.
4
- #
5
- # Author: GrimAndGreedy
6
- # License: MIT
7
-
8
-
9
- [environment]
10
- cwd="~/Downloads/new/creators/ashla/"
11
- # cwd="~/Videos/"
12
-
13
- [data]
14
- files_command = "eza -1 --no-quotes | grep -E mp4$"
15
-
16
- commands = [
17
- """eza -1 --no-quotes | grep -E mp4$""",
18
- # """sha1sum {} | awk '{{print $1}}'""",
19
- """ffprobe -show_entries format=duration -v quiet -of csv="p=0" -i {}""",
20
- """ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 {}""",
21
- """ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 {}""",
22
- """du -hs {} | awk '{{ print $1 }}'"""
23
- ]
24
-
25
- header = [
26
- "file",
27
- # "sha1",
28
- "duration",
29
- "width",
30
- "height",
31
- "size",
32
- ]
33
-
34
- # run = [
35
- # "mpv",
36
- # ]
File without changes
File without changes
File without changes
File without changes
File without changes