twd-m4sc0 2.0.0__tar.gz → 2.0.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: twd_m4sc0
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: A tool to temporarily save and go to a working directory
5
5
  Home-page: https://github.com/m4sc0/twd
6
6
  Author: m4sc0
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="twd_m4sc0",
5
- version="2.0.0",
5
+ version="2.0.1",
6
6
  packages=find_packages(),
7
7
  entry_points={
8
8
  "console_scripts": [
@@ -2,9 +2,12 @@ import os
2
2
  import json
3
3
  import hashlib
4
4
  import time
5
- from .logger import log, error
5
+ import logging
6
6
  from collections import OrderedDict
7
7
 
8
+ log = logging.getLogger("log")
9
+ error_log = logging.getLogger("error")
10
+
8
11
 
9
12
  def create_alias_id():
10
13
  data = str(time.time()) + str(os.urandom(16))
@@ -21,8 +24,9 @@ def ensure_data_file_exists(config):
21
24
  try:
22
25
  with open(data_file, "w") as f:
23
26
  json.dump({}, f)
27
+ log.info(f"Created data file at {data_file}")
24
28
  except OSError as e:
25
- error(f"Error creating data file: {e}", config)
29
+ error_log.error(f"Error creating data file: {e}")
26
30
 
27
31
 
28
32
  def load_data(config):
@@ -32,12 +36,13 @@ def load_data(config):
32
36
  try:
33
37
  with open(data_file, "r") as f:
34
38
  data = json.load(f)
39
+ log.info(f"Loaded data from {data_file}")
35
40
  return data
36
41
  except json.JSONDecodeError as e:
37
- error(f"Error reading data file: {e}", config)
42
+ error_log.error(f"Error reading data file: {e}")
38
43
  return {}
39
44
  except OSError as e:
40
- error(f"Error reading data file: {e}", config)
45
+ error_log.error(f"Error reading data file: {e}")
41
46
  return {}
42
47
 
43
48
 
@@ -49,8 +54,9 @@ def save_data(config, data):
49
54
  )
50
55
  with open(data_file, "w") as f:
51
56
  json.dump(sorted_data, f, indent=4)
57
+ log.info(f"Saved data to {data_file}")
52
58
  except OSError as e:
53
- error(f"Error writing to data file: {e}", config)
59
+ error_log.error(f"Error writing to data file: {e}")
54
60
 
55
61
 
56
62
  def create_entry(config, data, path, alias=None):
@@ -61,6 +67,7 @@ def create_entry(config, data, path, alias=None):
61
67
  "created_at": time.time(),
62
68
  }
63
69
  save_data(config, data)
70
+ log.info(f"Created new entry with alias_id '{alias_id}' and path '{path}'")
64
71
  return alias_id
65
72
 
66
73
 
@@ -68,8 +75,9 @@ def delete_entry(config, data, entry_id):
68
75
  if entry_id in data:
69
76
  del data[entry_id]
70
77
  save_data(config, data)
78
+ log.info(f"Deleted entry with alias_id '{entry_id}'")
71
79
  else:
72
- error(f"Entry ID {entry_id} not found", config)
80
+ error_log.error(f"Entry ID '{entry_id}' not found")
73
81
  raise KeyError(f"Entry ID {entry_id} not found")
74
82
 
75
83
 
@@ -77,8 +85,9 @@ def update_entry(config, data, entry_id, entry):
77
85
  if entry_id in data:
78
86
  data[entry_id] = entry
79
87
  save_data(config, data)
88
+ log.info(f"Updated entry with alias_id '{entry_id}'")
80
89
  else:
81
- error(f"Entry ID {entry_id} not found", config)
90
+ error_log.error(f"Entry ID '{entry_id}' not found")
82
91
  raise KeyError(f"Entry ID {entry_id} not found")
83
92
 
84
93
 
@@ -87,8 +96,9 @@ def delete_data_file(config):
87
96
  if os.path.exists(data_file):
88
97
  try:
89
98
  os.remove(data_file)
99
+ log.info(f"Deleted data file at {data_file}")
90
100
  except OSError as e:
91
- error(f"Error deleting data file: {e}", config)
101
+ error_log.error(f"Error deleting data file: {e}")
92
102
  raise
93
103
  else:
94
- error("No data file found to delete", config)
104
+ error_log.error("No data file found to delete")
@@ -0,0 +1,47 @@
1
+ import logging
2
+ import os
3
+ from logging.handlers import RotatingFileHandler
4
+
5
+
6
+ def setup_logger(config):
7
+ """Set up loggers based on the configuration provided."""
8
+ log_file = os.path.expanduser(config.get("log_file"))
9
+ error_file = os.path.expanduser(config.get("error_file"))
10
+ log_level = config.get("log_level", "INFO").upper()
11
+ max_bytes = config.get("log_max_bytes", 5 * 1024 * 1024) # Default 5MB
12
+ backup_count = config.get("log_backup_count", 3) # Default 3 backup files
13
+
14
+ os.makedirs(os.path.dirname(log_file), exist_ok=True)
15
+ os.makedirs(os.path.dirname(error_file), exist_ok=True)
16
+
17
+ # General log configuration
18
+ log_formatter = logging.Formatter(
19
+ config.get("log_format", "%(asctime)s - %(levelname)s - %(message)s")
20
+ )
21
+
22
+ # Avoid duplicate handlers
23
+ logger = logging.getLogger("log")
24
+ if not logger.hasHandlers():
25
+ logger.setLevel(log_level)
26
+ log_handler = RotatingFileHandler(
27
+ log_file, maxBytes=max_bytes, backupCount=backup_count
28
+ )
29
+ log_handler.setFormatter(log_formatter)
30
+ logger.addHandler(log_handler)
31
+
32
+ # Error log configuration
33
+ error_logger = logging.getLogger("error")
34
+ if not error_logger.hasHandlers():
35
+ error_logger.setLevel(logging.ERROR)
36
+ error_handler = RotatingFileHandler(
37
+ error_file, maxBytes=max_bytes, backupCount=backup_count
38
+ )
39
+ error_handler.setFormatter(log_formatter)
40
+ error_logger.addHandler(error_handler)
41
+
42
+ return logger, error_logger
43
+
44
+
45
+ def initialize_logging(config):
46
+ setup_logger(config)
47
+
@@ -2,7 +2,10 @@ import curses
2
2
  import time
3
3
  import os
4
4
  from . import crud
5
- from .logger import error
5
+ import logging
6
+
7
+ log = logging.getLogger("log")
8
+ error_log = logging.getLogger("error")
6
9
 
7
10
  CONFIG = None
8
11
  DIRS = None
@@ -163,7 +166,7 @@ def display_select_screen(stdscr):
163
166
  try:
164
167
  crud.delete_entry(CONFIG, data, selected_entry_id)
165
168
  except KeyError:
166
- error(f"Entry ID {selected_entry_id} not found", CONFIG)
169
+ error_log.error(f"Entry ID {selected_entry_id} not found")
167
170
  del filtered_DIRS[selected_entry_id]
168
171
  if selected_entry >= len(filtered_DIRS):
169
172
  selected_entry = max(len(filtered_DIRS) - 1, 0)
@@ -196,4 +199,3 @@ def display_select(config, dirs):
196
199
  original_DIRS = DIRS
197
200
  search_query = ""
198
201
  return curses.wrapper(display_select_screen)
199
-
@@ -3,11 +3,15 @@ import argparse
3
3
  import json
4
4
  import time
5
5
  import re
6
+ import logging
6
7
  from importlib.metadata import version, PackageNotFoundError
7
- from .logger import log, error
8
+ from .logger import initialize_logging
8
9
  from .screen import display_select
9
10
  from . import crud
10
11
 
12
+ log = logging.getLogger("log")
13
+ error_log = logging.getLogger("error")
14
+
11
15
  TWD_DIR = os.path.join(os.path.expanduser("~"), ".twd")
12
16
  CONFIG_FILE = os.path.join(TWD_DIR, "config")
13
17
 
@@ -16,7 +20,10 @@ DEFAULT_CONFIG = {
16
20
  "output_behaviour": 2,
17
21
  "log_file": os.path.expanduser("~/.twd/log"),
18
22
  "error_file": os.path.expanduser("~/.twd/error"),
19
- "log_format": "[$T]: $M",
23
+ "log_format": "%(asctime)s - %(levelname)s - %(message)s",
24
+ "log_level": "INFO",
25
+ "log_max_bytes": 5 * 1024 * 1024, # 5 MB log rotation
26
+ "log_backup_count": 3,
20
27
  }
21
28
 
22
29
 
@@ -31,32 +38,34 @@ def load_config():
31
38
  try:
32
39
  return json.load(file)
33
40
  except json.JSONDecodeError as e:
34
- error(f"Error loading config: {e}", DEFAULT_CONFIG)
41
+ error_log.error(f"Error loading config: {e}")
35
42
  return DEFAULT_CONFIG
36
43
 
37
44
 
38
45
  CONFIG = load_config()
46
+ initialize_logging(CONFIG)
39
47
 
40
- # Ensure data files exist
41
48
  crud.ensure_data_file_exists(CONFIG)
42
- log_file = os.path.expanduser(CONFIG.get("log_file"))
43
- error_file = os.path.expanduser(CONFIG.get("error_file"))
44
49
 
45
50
 
46
51
  def ensure_log_error_files():
52
+ """Ensure that log and error files exist based on configuration settings."""
53
+ log_file = os.path.expanduser(CONFIG.get("log_file"))
54
+ error_file = os.path.expanduser(CONFIG.get("error_file"))
55
+
47
56
  if not os.path.exists(log_file):
48
57
  try:
49
58
  with open(log_file, "w+") as f:
50
59
  f.write("")
51
60
  except OSError as e:
52
- error(f"Error creating log file: {e}", CONFIG)
61
+ error_log.error(f"Error creating log file: {e}")
53
62
 
54
63
  if not os.path.exists(error_file):
55
64
  try:
56
65
  with open(error_file, "w+") as f:
57
66
  f.write("")
58
67
  except OSError as e:
59
- error(f"Error creating error file: {e}", CONFIG)
68
+ error_log.error(f"Error creating error file: {e}")
60
69
 
61
70
 
62
71
  ensure_log_error_files()
@@ -66,14 +75,14 @@ def get_absolute_path(path):
66
75
  try:
67
76
  return os.path.abspath(path)
68
77
  except Exception as e:
69
- error(f"Error getting absolute path for {path}: {e}", CONFIG)
78
+ error_log.error(f"Error getting absolute path for {path}: {e}")
70
79
  raise
71
80
 
72
81
 
73
82
  def validate_alias(alias):
74
83
  """Ensure the alias contains only valid characters."""
75
84
  if not re.match(r"^[\w-]+$", alias):
76
- error(f"Invalid alias provided: {alias}", CONFIG)
85
+ error_log.error(f"Invalid alias provided: {alias}")
77
86
  raise ValueError(
78
87
  f"Invalid alias: '{alias}'. Aliases can only contain alphanumeric characters, dashes, and underscores."
79
88
  )
@@ -83,7 +92,7 @@ def validate_alias(alias):
83
92
  def output_handler(
84
93
  message=None, path=None, output=True, simple_output=False, message_type=0
85
94
  ):
86
- log(f"Type: {message_type}, Msg: {message or path}", CONFIG)
95
+ log.info(f"Type: {message_type}, Msg: {message or path}")
87
96
 
88
97
  if CONFIG["output_behaviour"] == 1 or simple_output:
89
98
  if path:
@@ -126,12 +135,10 @@ def load_directory():
126
135
 
127
136
  def show_main(alias=None, output=True, simple_output=False):
128
137
  dirs = load_directory()
129
-
130
138
  if dirs is None:
131
139
  output_handler("No TWD found", None, output, simple_output)
132
140
  return 1
133
141
  else:
134
- # Use alias if provided
135
142
  if alias:
136
143
  matched_dirs = []
137
144
 
@@ -149,14 +156,13 @@ def show_main(alias=None, output=True, simple_output=False):
149
156
 
150
157
  if len(matched_dirs) == 1:
151
158
  TWD = matched_dirs[0]["path"]
152
-
153
159
  if os.path.exists(TWD):
154
160
  output_handler(
155
161
  f"cd {TWD}", TWD, output, simple_output, message_type=1
156
162
  )
157
163
  return 0
158
164
  else:
159
- error(f"Directory does not exist: {TWD}", CONFIG)
165
+ error_log.error(f"Directory does not exist: {TWD}")
160
166
  output_handler(
161
167
  f"Directory does not exist: {TWD}", None, output, simple_output
162
168
  )
@@ -177,19 +183,17 @@ def show_main(alias=None, output=True, simple_output=False):
177
183
  output_handler("No TWD with alias found", None, output, simple_output)
178
184
  return 1
179
185
 
180
- # Display selection using curses if alias is not given
181
186
  selected_dir = display_select(CONFIG, dirs)
182
187
  if selected_dir is None:
183
188
  output_handler("No TWD selected", None, output, simple_output)
184
189
  return 0
185
190
  else:
186
191
  TWD = selected_dir["path"]
187
-
188
192
  if os.path.exists(TWD):
189
193
  output_handler(f"cd {TWD}", TWD, output, simple_output, message_type=1)
190
194
  return 0
191
195
  else:
192
- error(f"Directory does not exist: {TWD}", CONFIG)
196
+ error_log.error(f"Directory does not exist: {TWD}")
193
197
  output_handler(
194
198
  f"Directory does not exist: {TWD}", None, output, simple_output
195
199
  )
@@ -198,7 +202,6 @@ def show_main(alias=None, output=True, simple_output=False):
198
202
 
199
203
  def show_directory(output=True, simple_output=False):
200
204
  dirs = load_directory()
201
-
202
205
  if not dirs:
203
206
  output_handler("No TWD set", None, output, simple_output)
204
207
  return
@@ -240,7 +243,7 @@ This feature is to prevent accidental execution.""",
240
243
  try:
241
244
  crud.delete_data_file(CONFIG)
242
245
  except OSError as e:
243
- error(f"Error deleting TWD file: {e}", CONFIG)
246
+ error_log.error(f"Error deleting TWD file: {e}")
244
247
  raise
245
248
  output_handler("TWD File deleted and TWD unset", None, output, simple_output)
246
249
 
@@ -249,7 +252,7 @@ def get_package_version():
249
252
  try:
250
253
  return version("twd_m4sc0")
251
254
  except PackageNotFoundError as e:
252
- error(f"Package version not found: {e}", CONFIG)
255
+ error_log.error(f"Package version not found: {e}")
253
256
  return "Unknown version"
254
257
 
255
258
 
@@ -258,13 +261,10 @@ def main():
258
261
  description="Temporarily save and navigate to working directories."
259
262
  )
260
263
 
261
- # Positional arguments
262
264
  parser.add_argument("directory", nargs="?", help="Directory to save")
263
265
  parser.add_argument(
264
266
  "alias", nargs="?", help="Alias for the saved directory (optional)"
265
267
  )
266
-
267
- # Optional Arguments/Flags
268
268
  parser.add_argument(
269
269
  "-s",
270
270
  "--save",
@@ -285,63 +285,48 @@ def main():
285
285
  "--version",
286
286
  action="version",
287
287
  version=f"TWD Version: v{get_package_version()}",
288
- help="Show the current version of TWD installed",
289
288
  )
290
289
  parser.add_argument("-f", "--force", action="store_true", help="Force an action")
291
290
  parser.add_argument(
292
291
  "--shell", nargs="?", const="twd", help="Output shell function for integration"
293
292
  )
294
293
  parser.add_argument(
295
- "--simple-output",
296
- action="store_true",
297
- help="Only print essential output (new directory, absolute path, etc.)",
294
+ "--simple-output", action="store_true", help="Only print essential output"
298
295
  )
299
296
  parser.add_argument(
300
297
  "--no-output",
301
298
  action="store_true",
302
299
  help="Prevents the console from sending output",
303
300
  )
304
- args = parser.parse_args()
305
301
 
302
+ args = parser.parse_args()
306
303
  output = not args.no_output
307
304
  simple_output = args.simple_output
308
305
 
309
- # Shell function
310
306
  if args.shell:
311
- print(rf"""
312
- function {args.shell}() {{
313
- python3 -m twd "$@"
314
- if [[ -f /tmp/twd_path ]]; then
315
- cd "$(cat /tmp/twd_path)"
316
- /bin/rm -f /tmp/twd_path
317
- fi
318
- }}
319
- """)
307
+ print(rf"""function {args.shell}() {{
308
+ python3 -m twd "$@";
309
+ if [ -f /tmp/twd_path ]; then
310
+ cd "$(cat /tmp/twd_path)";
311
+ /bin/rm -f /tmp/twd_path;
312
+ fi;
313
+ }}""")
320
314
  return 0
321
315
 
322
316
  directory = args.directory or args.dir
323
317
  alias = args.alias or args.ali
324
318
 
325
319
  if args.save:
326
- if not directory:
327
- directory = os.getcwd()
328
-
329
- alias = args.alias or args.ali
330
-
331
320
  save_directory(directory, alias, output, simple_output)
332
321
  elif args.go:
333
- alias = args.go
334
- return show_main(alias, output, simple_output)
322
+ show_main(alias, output, simple_output)
335
323
  elif args.list:
336
324
  show_directory(output, simple_output)
337
325
  elif args.unset:
338
- force = args.force
339
- unset_directory(output, simple_output, force)
326
+ unset_directory(output, simple_output, force=args.force)
340
327
  else:
341
328
  show_main(None, output, simple_output)
342
- return 1
343
329
 
344
330
 
345
331
  if __name__ == "__main__":
346
332
  main()
347
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: twd_m4sc0
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: A tool to temporarily save and go to a working directory
5
5
  Home-page: https://github.com/m4sc0/twd
6
6
  Author: m4sc0
@@ -1,47 +0,0 @@
1
- import os
2
- import time
3
-
4
-
5
- def format_message(message, config):
6
- """Format the log message according to the provided config."""
7
- result = config.get("log_format", "[$T]: $M")
8
- result = result.replace("$T", time.strftime("%Y-%m-%d %H:%M:%S"))
9
- result = result.replace("$M", message)
10
- return result
11
-
12
-
13
- def ensure_directory_exists(file_path):
14
- """Ensure the directory for the given file path exists."""
15
- directory = os.path.dirname(file_path)
16
- if not os.path.exists(directory):
17
- os.makedirs(directory, exist_ok=True)
18
-
19
-
20
- def write_log(message, config):
21
- """Write log message to the log file specified in the config."""
22
- log_file = os.path.expanduser(config.get("log_file"))
23
- log_file = os.path.abspath(log_file)
24
- ensure_directory_exists(log_file) # Ensure the directory exists
25
- with open(log_file, "a+") as f:
26
- f.write(message + "\n")
27
-
28
-
29
- def write_error(message, config):
30
- """Write error message to the error file specified in the config."""
31
- error_file = os.path.expanduser(config.get("error_file"))
32
- error_file = os.path.abspath(error_file)
33
- ensure_directory_exists(error_file) # Ensure the directory exists
34
- with open(error_file, "a+") as f:
35
- f.write(message + "\n")
36
-
37
-
38
- def log(message, config):
39
- """Log the message using the provided config."""
40
- formatted_message = format_message(message, config)
41
- write_log(formatted_message, config)
42
-
43
-
44
- def error(message, config):
45
- """Log the error using the provided config."""
46
- formatted_message = format_message(message, config)
47
- write_error(formatted_message, config)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes