skilleter-thingy 0.0.38__py3-none-any.whl → 0.0.40__py3-none-any.whl

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 skilleter-thingy might be problematic. Click here for more details.

Files changed (69) hide show
  1. {skilleter_thingy-0.0.38.dist-info → skilleter_thingy-0.0.40.dist-info}/METADATA +1 -1
  2. skilleter_thingy-0.0.40.dist-info/RECORD +6 -0
  3. skilleter_thingy-0.0.40.dist-info/entry_points.txt +43 -0
  4. skilleter_thingy-0.0.40.dist-info/top_level.txt +1 -0
  5. __init__.py +0 -6
  6. addpath.py +0 -107
  7. borger.py +0 -269
  8. console_colours.py +0 -63
  9. diskspacecheck.py +0 -67
  10. docker_purge.py +0 -113
  11. ffind.py +0 -536
  12. ggit.py +0 -90
  13. ggrep.py +0 -154
  14. git_br.py +0 -180
  15. git_ca.py +0 -142
  16. git_cleanup.py +0 -287
  17. git_co.py +0 -220
  18. git_common.py +0 -61
  19. git_hold.py +0 -154
  20. git_mr.py +0 -92
  21. git_parent.py +0 -77
  22. git_review.py +0 -1428
  23. git_update.py +0 -385
  24. git_wt.py +0 -96
  25. gitcmp_helper.py +0 -322
  26. gitprompt.py +0 -274
  27. gl.py +0 -174
  28. gphotosync.py +0 -610
  29. linecount.py +0 -155
  30. moviemover.py +0 -133
  31. photodupe.py +0 -136
  32. phototidier.py +0 -248
  33. py_audit.py +0 -131
  34. readable.py +0 -270
  35. remdir.py +0 -126
  36. rmdupe.py +0 -550
  37. rpylint.py +0 -91
  38. skilleter_thingy-0.0.38.dist-info/RECORD +0 -66
  39. skilleter_thingy-0.0.38.dist-info/entry_points.txt +0 -43
  40. skilleter_thingy-0.0.38.dist-info/top_level.txt +0 -43
  41. splitpics.py +0 -99
  42. strreplace.py +0 -82
  43. sysmon.py +0 -435
  44. tfm.py +0 -920
  45. tfparse.py +0 -101
  46. thingy/__init__.py +0 -0
  47. thingy/colour.py +0 -213
  48. thingy/dc_curses.py +0 -278
  49. thingy/dc_defaults.py +0 -221
  50. thingy/dc_util.py +0 -50
  51. thingy/dircolors.py +0 -308
  52. thingy/docker.py +0 -95
  53. thingy/files.py +0 -142
  54. thingy/git.py +0 -1371
  55. thingy/git2.py +0 -1307
  56. thingy/gitlab.py +0 -193
  57. thingy/logger.py +0 -112
  58. thingy/path.py +0 -156
  59. thingy/popup.py +0 -87
  60. thingy/process.py +0 -112
  61. thingy/run.py +0 -334
  62. thingy/tfm_pane.py +0 -595
  63. thingy/tidy.py +0 -160
  64. trimpath.py +0 -84
  65. window_rename.py +0 -92
  66. xchmod.py +0 -125
  67. yamlcheck.py +0 -89
  68. {skilleter_thingy-0.0.38.dist-info → skilleter_thingy-0.0.40.dist-info}/LICENSE +0 -0
  69. {skilleter_thingy-0.0.38.dist-info → skilleter_thingy-0.0.40.dist-info}/WHEEL +0 -0
rmdupe.py DELETED
@@ -1,550 +0,0 @@
1
- #! /usr/bin/env python3
2
-
3
- ################################################################################
4
- """ Find duplicate files and do things with them.
5
-
6
- Uses the 'jdupes' utility
7
-
8
- TODO: Option to ignore by filetype
9
- TODO: Ignore folder.jpg files
10
-
11
- NOTE: The option to ignore directories in jdupes doesn't work (at least in the version in Ubuntu 18.04) so we do this after searching for duplicates
12
- """
13
- ################################################################################
14
-
15
- import os
16
- import argparse
17
- import logging
18
- import subprocess
19
- import sys
20
- import re
21
- import pickle
22
- import copy
23
- import fnmatch
24
-
25
- ################################################################################
26
-
27
- ALWAYS_IGNORE_DIRS = ['.git']
28
-
29
- ################################################################################
30
-
31
- def error(msg):
32
- """ Report an error and exit """
33
-
34
- sys.stderr.write('%s\n' % msg)
35
- sys.exit(1)
36
-
37
- ################################################################################
38
-
39
- def parse_command_line():
40
- """ Parse the command line """
41
-
42
- parser = argparse.ArgumentParser(description='Find duplicate files created by SyncThing or in temporary directories in a given path')
43
- parser.add_argument('--debug', action='store_true', help='Debug output')
44
- parser.add_argument('--save', action='store', help='Save duplicate file list')
45
- parser.add_argument('--load', action='store', help='Load duplicate file list')
46
- parser.add_argument('--script', action='store', help='Generate a shell script to delete the duplicates')
47
- parser.add_argument('--exclude', action='append', help='Directories to skip when looking for duplicates')
48
- parser.add_argument('--ignore', action='append', help='Wildcards to ignore when looking for duplicates')
49
- parser.add_argument('path', nargs='?', default='.', help='Path(s) to search for duplicates')
50
-
51
- args = parser.parse_args()
52
-
53
- logging.basicConfig(level=logging.DEBUG if args.debug else logging.ERROR)
54
-
55
- if args.save and args.load:
56
- error('The save and load options are mutually exclusive')
57
-
58
- return args
59
-
60
- ################################################################################
61
-
62
- def jdupes(path,
63
- one_file_system=False,
64
- no_hidden=False,
65
- check_permissions=False,
66
- quick=False,
67
- recurse=True,
68
- follow_symlinks=False,
69
- exclude=None,
70
- zero_match=False):
71
- """ Run jdupes with the specified options """
72
-
73
- cmd = ['jdupes', '--quiet']
74
-
75
- if one_file_system:
76
- cmd.append('--one-file-system')
77
-
78
- if no_hidden:
79
- cmd.append('--nohidden')
80
-
81
- if check_permissions:
82
- cmd.append('--permissions')
83
-
84
- if quick:
85
- cmd.append('--quick')
86
-
87
- if recurse:
88
- cmd += ['--recurse', path]
89
- else:
90
- cmd.append(path)
91
-
92
- if follow_symlinks:
93
- cmd.append('--symlinks')
94
-
95
- if exclude:
96
- cmd += ['--exclude', exclude]
97
-
98
- if zero_match:
99
- cmd.append('--zeromatch')
100
-
101
- logging.debug('Running %s', ' '.join(cmd))
102
-
103
- result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
104
-
105
- results = [[]]
106
- for output in result.stdout.split('\n'):
107
- output = output.strip()
108
-
109
- logging.debug(output)
110
-
111
- if output:
112
- results[-1].append(output)
113
- else:
114
- results.append([])
115
-
116
- while results and results[-1] == []:
117
- results = results[:-1]
118
-
119
- logging.debug('Found %d duplicated files', len(results))
120
- for entry in results:
121
- logging.debug(' %s', ', '.join(entry))
122
-
123
- return results
124
-
125
- ################################################################################
126
-
127
- def remove_excluded_entries(args, duplicates):
128
- """ Now filter out enties in the duplicates lists that are in the
129
- directories that we are supposed to be ignoring """
130
-
131
- # Build the list of directories to ignore - add the default list
132
-
133
- ignore_dirs = ALWAYS_IGNORE_DIRS
134
- if args.exclude:
135
- ignore_dirs += args.exclude
136
-
137
- # Build the list of absolute and relative paths to ignore
138
- # both are in the form '/path/'
139
-
140
- ignore_prefixes = []
141
- ignore_subdirs = []
142
-
143
- for ignore in ignore_dirs:
144
- if ignore[-1] != '/':
145
- ignore = '%s/' % ignore
146
-
147
- if ignore[0] == '/':
148
- ignore_prefixes.append(ignore)
149
- else:
150
- ignore_subdirs.append('/%s' % ignore)
151
-
152
- # Now remove entries from the duplicate list that are within the ignored
153
- # directories. If the resultant duplicate record is empty or only contains
154
- # one entry, then remove it.
155
-
156
- filtered_duplicates = []
157
-
158
- for duplicate in duplicates:
159
- # Set of entries in the record to remove
160
-
161
- remove_entries = set()
162
-
163
- for entry in duplicate:
164
- # If the entry is in an excluded directory tree, remove it
165
-
166
- for ignore in ignore_prefixes:
167
- if entry.startswith(ignore):
168
- remove_entries.add(entry)
169
-
170
- # If the entry is in an excluded subdirectory tree, remove it
171
-
172
- for ignore in ignore_subdirs:
173
- if ignore in entry:
174
- remove_entries.add(entry)
175
-
176
- # If we have a list of files to ignore then check each entry against the list
177
- # and remove any matches.
178
-
179
- for ignore in args.ignore or []:
180
- if fnmatch.fnmatch(os.path.basename(entry), ignore):
181
- remove_entries.add(entry)
182
-
183
- # If we loaded a saved list and the entry doesn't exist, remove it
184
-
185
- if args.load and entry not in remove_entries and not os.path.isfile(entry):
186
- remove_entries.add(entry)
187
-
188
- # If we have entries to remove from the record, then remove them
189
-
190
- if remove_entries:
191
- for entry in remove_entries:
192
- duplicate.remove(entry)
193
-
194
- # Only add to the filtered duplicate list if we have more than one duplicate in the entry
195
-
196
- if len(duplicate) >= 2:
197
- filtered_duplicates.append(duplicate)
198
-
199
- return filtered_duplicates
200
-
201
- ################################################################################
202
-
203
- def find_duplicates(args):
204
- """ Find duplicates, or load them from a saved status file """
205
-
206
- if args.load:
207
- logging.debug('Loading duplicate file data from %s', args.load)
208
-
209
- with open(args.load, 'rb') as infile:
210
- duplicates = pickle.load(infile)
211
-
212
- logging.debug('Data loaded, %d duplicates', len(duplicates))
213
- else:
214
- duplicates = jdupes(args.path)
215
-
216
- if args.save:
217
- logging.debug('Saving duplicate file data to %s', args.save)
218
-
219
- with open(args.save, 'wb') as outfile:
220
- pickle.dump(duplicates, outfile)
221
-
222
- print('Duplicate file data saved')
223
- sys.exit(0)
224
-
225
- return remove_excluded_entries(args, duplicates)
226
-
227
- ################################################################################
228
-
229
- def check_duplicates(duplicate):
230
- """ Given a list of duplicate files work out what to do with them.
231
- Returns:
232
- List of files (if any) to keep
233
- List of files (if any) to be deleted
234
- Name of a file that is similar to the duplicates (both in name and content)
235
- True if the files being removed are .ini files with mangled names
236
- Any error/warning message associated with processing the duplicates
237
- """
238
-
239
- keep = set()
240
- remove = set()
241
- similar = None
242
- error_msg = None
243
-
244
- # We can just delete entries that are conflicting picasa.ini files
245
-
246
- for entry in duplicate:
247
- if re.fullmatch(r'.*/\.?[pP]icasa.sync-conflict-.*\.ini', entry):
248
- logging.debug('Remove picasa.ini sync conflict: %s', entry)
249
-
250
- remove.add(entry)
251
-
252
- if remove:
253
- for item in remove:
254
- duplicate.remove(item)
255
-
256
- ini_file_purge = (len(remove) > 0)
257
-
258
- # If all of the files are called 'picasa.ini' then we skip them as it is valid to have multiple picasa.ini files
259
-
260
- if duplicate:
261
- for entry in duplicate:
262
- if os.path.basename(entry).lower() not in ('picasa.ini', '.picasa.ini'):
263
- break
264
- else:
265
- print('Keeping picasa.ini files: %s' % (', '.join(duplicate)))
266
- duplicate = []
267
-
268
- # Skip other checks if we don't have any files that aren't conflicting picasa.ini files
269
-
270
- if duplicate:
271
- # Look for entries that are in known temporary directories
272
-
273
- for entry in duplicate:
274
- if re.match(r'.*/(\$RECYCLE\.BIN|.Picasa3Temp|.Picasa3Temp_[0-9]+|.picasaoriginals)/.*', entry):
275
- logging.debug('Removing temporary directory item: %s', entry)
276
- remove.add(entry)
277
- else:
278
- keep.add(entry)
279
-
280
- # Look for lists of copies where some are marked as copies with _X appended to the file name
281
-
282
- if len(keep) > 1:
283
- copies = set()
284
- originals = set()
285
-
286
- for entry in keep:
287
- if re.fullmatch(r'.*_[1-9][0-9]{0,2}\.[^/]+', entry):
288
- copies.add(entry)
289
- else:
290
- originals.add(entry)
291
-
292
- # If we have at least one original, then we can remove the copies
293
-
294
- if originals:
295
- if copies:
296
- logging.debug('Removing copies: %s', list(copies))
297
- logging.debug('Keeping originals: %s', originals)
298
-
299
- remove |= copies
300
- keep = originals
301
- else:
302
- error_msg = 'No originals found in %s' % (', '.join(keep))
303
-
304
- # Looks for lists of copies where some are marked as copies with (N) appended to the file name
305
-
306
- copies = set()
307
- originals = set()
308
-
309
- for entry in keep:
310
- if re.fullmatch(r'.*\([0-9]+\)\.[^/]+', entry):
311
- copies.add(entry)
312
- else:
313
- originals.add(entry)
314
-
315
- # If we have at least one original, then we can remove the copies
316
-
317
- if originals:
318
- if copies:
319
- logging.debug('Removing copies: %s', list(copies))
320
- logging.debug('Keeping originals: %s', originals)
321
-
322
- remove |= copies
323
- keep = originals
324
- else:
325
- error_msg = 'No originals found in %s' % (', '.join(keep))
326
-
327
- # Now look for sync conflicts
328
-
329
- if len(keep) > 1:
330
- conflicts = set()
331
-
332
- for entry in keep:
333
- if re.fullmatch(r'.*(\.sync-conflict-|/.stversions/).*', entry):
334
- conflicts.add(entry)
335
-
336
- if conflicts:
337
- keep = keep.difference(conflicts)
338
-
339
- if keep:
340
- logging.debug('Removing sync conflicts: %s', conflicts)
341
- logging.debug('Keeping: %s', keep)
342
-
343
- remove |= conflicts
344
- else:
345
- logging.debug('No non-conflicting files found in %s', (', '.join(conflicts)))
346
-
347
- originals = set()
348
-
349
- for entry in conflicts:
350
- originals.add(re.sub(r'(\.sync-conflict-[0-9]{8}-[0-9]{6}-[A-Z]{7}|/.stversions/)', '', entry))
351
-
352
- if len(originals) == 1:
353
- original = originals.pop()
354
- if os.path.isfile(original):
355
-
356
- similar = original
357
- remove = conflicts
358
-
359
- # Now look for files that differ only by case
360
-
361
- if len(keep) > 1:
362
- # Take a copy of the set, then compare the lower case versions of the entries
363
- # and remove any that match
364
- # TODO: We only check for a match against a lower case version of the first entry
365
-
366
- keep_c = copy.copy(keep)
367
- name_lc = keep_c.pop().lower()
368
-
369
- for entry in keep_c:
370
- if entry.lower() == name_lc:
371
- logging.debug('Removing duplicate mixed-case entry: %s', entry)
372
-
373
- remove.add(entry)
374
-
375
- keep = keep.difference(remove)
376
-
377
- # Now look for files with '~' in the name
378
-
379
- if len(keep) > 1:
380
- tilde = set()
381
-
382
- for k in keep:
383
- if '~' in k:
384
- tilde.add(k)
385
-
386
- if tilde != keep:
387
- remove |= tilde
388
- keep = keep.difference(tilde)
389
-
390
- # Now remove entries with the shorter subdirectory names
391
-
392
- if len(keep) > 1:
393
- longest = ""
394
- longest_name = None
395
-
396
- for k in sorted(list(keep)):
397
- subdir = os.path.split(os.path.dirname(k))[1]
398
-
399
- if len(subdir) > len(longest):
400
- longest = subdir
401
- longest_name = k
402
-
403
- if longest_name:
404
- for k in keep:
405
- if k != longest_name:
406
- remove.add(k)
407
-
408
- keep = keep.difference(remove)
409
-
410
- # Now remove entries with the shorter file names
411
-
412
- if len(keep) > 1:
413
- longest = ""
414
- longest_name = None
415
-
416
- for k in sorted(list(keep)):
417
- filename = os.path.basename(k)
418
-
419
- if len(filename) > len(longest):
420
- longest = filename
421
- longest_name = k
422
-
423
- if longest_name:
424
- for k in keep:
425
- if k != filename:
426
- remove.add(k)
427
-
428
- keep = keep.difference(remove)
429
-
430
- # Don't allow files called 'folder.jpg' to be removed - multiple directories can
431
- # have the same cover art.
432
-
433
- if remove:
434
- for r in remove:
435
- if os.path.basename(r) in ('folder.jpg', 'Folder.jpg', 'cover.jpg', 'Cover.jpg'):
436
- keep.add(r)
437
-
438
- remove = remove.difference(keep)
439
-
440
- return sorted(list(keep)), sorted(list(remove)), similar, ini_file_purge, error_msg
441
-
442
- ################################################################################
443
-
444
- def process_duplicates(args, duplicates):
445
- """ Process the duplicate file records """
446
-
447
- # Optionally generate the shell script
448
-
449
- if args.script:
450
- script = open(args.script, 'wt')
451
-
452
- script.write('#! /usr/bin/env bash\n\n'
453
- '# Auto-generated shell script to delete duplicate files\n\n'
454
- 'set -o pipefail\n'
455
- 'set -o errexit\n'
456
- 'set -o nounset\n\n')
457
-
458
- # List of errors - we report everything that doesn't work at the end
459
-
460
- errors = []
461
-
462
- # Decide what to do with each duplication record
463
-
464
- for duplicate in duplicates:
465
- keep, remove, similar, ini_file_purge, error_msg = check_duplicates(duplicate)
466
-
467
- if error_msg:
468
- errors.append(error_msg)
469
-
470
- # Report what we'd do
471
-
472
- if args.script and (remove or keep):
473
- script.write('\n')
474
-
475
- for k in keep:
476
- script.write('# Keep %s\n' % k)
477
-
478
- if ini_file_purge:
479
- script.write('# Remove conflicting, renamed picasa.ini files\n')
480
-
481
- if similar:
482
- script.write('# Similar file: %s\n' % similar)
483
-
484
- for r in remove:
485
- r = r.replace('$', '\\$')
486
- script.write('rm -- "%s"\n' % r)
487
-
488
- if remove:
489
- print('Duplicates found:')
490
-
491
- if keep:
492
- print(' Keep: %s' % (', '.join(keep)))
493
-
494
- if similar:
495
- print(' Similar: %s' % similar)
496
-
497
- print(' Delete: %s' % (', '.join(remove)))
498
-
499
- elif keep and not remove:
500
- errors.append('Keeping all copies of %s' % (', '.join(keep)))
501
-
502
- elif len(keep) > 1:
503
- print('Keeping %d copies of %s' % (len(keep), ', '.join(keep)))
504
- print(' Whilst removing %s' % (', '.join(remove)))
505
-
506
- elif duplicate and remove and not keep:
507
- errors.append('All entries classified for removal: %s' % (', '.join(remove)))
508
-
509
- if errors:
510
- errors.sort()
511
-
512
- print('-' * 80)
513
- print('Problems:')
514
-
515
- for error in errors:
516
- print(error)
517
-
518
- if args.script:
519
- script.write('\n'
520
- '# %s\n'
521
- '# There are a number of duplicates where it is not clear which one should be kept,\n'
522
- '# or whether all copies should be kept. These are listed below.\n'
523
- '# %s\n\n' % ('-' * 80, '-' * 80))
524
-
525
- for error in errors:
526
- script.write('# %s\n' % error)
527
-
528
- ################################################################################
529
-
530
- def rmdupe():
531
- """ Main function """
532
-
533
- try:
534
- args = parse_command_line()
535
-
536
- duplicates = find_duplicates(args)
537
-
538
- process_duplicates(args, duplicates)
539
-
540
- except KeyboardInterrupt:
541
- sys.exit(1)
542
-
543
- except BrokenPipeError:
544
- sys.exit(2)
545
-
546
- ################################################################################
547
- # Entry point
548
-
549
- if __name__ == '__main__':
550
- rmdupe()
rpylint.py DELETED
@@ -1,91 +0,0 @@
1
- #! /usr/bin/env python3
2
-
3
- ################################################################################
4
- """ Run pylint on all the Python source files in the current tree
5
-
6
- Copyright (C) 2017-18 John Skilleter """
7
- ################################################################################
8
-
9
- import os
10
- import sys
11
- import argparse
12
- import glob
13
-
14
- # TODO: Convert to use thingy.proc
15
- import thingy.process as process
16
-
17
- ################################################################################
18
-
19
- def main():
20
- """ Main code. Exits directly on failure to locate source files, or returns
21
- the status code from Pylint otherwise. """
22
-
23
- # Parse the comand line
24
-
25
- parser = argparse.ArgumentParser(description='Run pylint in the current (or specified) directory/ies')
26
-
27
- parser.add_argument('paths', nargs='*', help='List of files or paths to lint')
28
-
29
- args = parser.parse_args()
30
-
31
- if not args.paths:
32
- args.paths = ['.']
33
-
34
- sourcefiles = []
35
-
36
- # Use rgrep to find source files that have a Python 3 #!
37
-
38
- for entry in args.paths:
39
- if os.path.isdir(entry):
40
- try:
41
- sourcefiles += process.run(['rgrep', '-E', '--exclude-dir=.git', '-l', '#![[:space:]]*/usr/bin/(env[[:space:]])?python3'] + args.paths)
42
- except process.RunError as exc:
43
- if exc.status == 1:
44
- sys.stderr.write('No Python3 source files found\n')
45
- sys.exit(2)
46
- else:
47
- sys.stderr.write('%d: %s\n' % (exc.status, exc.msg))
48
- sys.exit(1)
49
- elif os.path.isfile(entry):
50
- sourcefiles.append(entry)
51
- else:
52
- files = glob.glob(entry)
53
-
54
- if not files:
55
- sys.stderr.write('No files found matching "%s"' % entry)
56
- sys.exit(2)
57
-
58
- sourcefiles += files
59
-
60
- # Run pylint on all the files
61
-
62
- try:
63
- process.run(['pylint3', '--output-format', 'parseable'] + sourcefiles, foreground=True)
64
- except process.RunError as exc:
65
- status = exc.status
66
- else:
67
- status = 0
68
-
69
- if status >= 64:
70
- sys.stderr.write('Unexpected error: %d\n' % status)
71
-
72
- # Function return code is the status return from pylint
73
-
74
- return status
75
-
76
- ################################################################################
77
-
78
- def rpylint():
79
- """Entry point"""
80
-
81
- try:
82
- sys.exit(main())
83
- except KeyboardInterrupt:
84
- sys.exit(1)
85
- except BrokenPipeError:
86
- sys.exit(2)
87
-
88
- ################################################################################
89
-
90
- if __name__ == '__main__':
91
- rpylint()
@@ -1,66 +0,0 @@
1
- __init__.py,sha256=rVPTxm8L5w52U0YdTd7r_D44SBP7pS3JCJtsf0iIsow,110
2
- addpath.py,sha256=4Yhhgjjz1XDI98j0dAiQpNA2ejLefeWUTeSg3nIXQq0,3842
3
- borger.py,sha256=AQX7OHeGXcUjkgyXEWE2h_oOey9eczZBbKjrreXvRAs,7832
4
- console_colours.py,sha256=BOS9mo3jChx_FE8L1j488MDoVNgib11KjTRhrz_YRYE,1781
5
- diskspacecheck.py,sha256=7xsj4egXXV6jPhXZTe2b5rS03XAmm5uLC5TeiO1NJoE,2072
6
- docker_purge.py,sha256=2t6yjlxmHCHKMAejLViYyOQNzyqSXGiV59df4Wlojaw,3349
7
- ffind.py,sha256=1MQGnzr-n3TUH2yFphfj4SjYNR3b-6LsdmLjhHJy2e0,19345
8
- ggit.py,sha256=AIhW3S7HC9smgBcHmDsbTLnO6j9VASkeLsBeA0hnCvM,2480
9
- ggrep.py,sha256=Mxme8gliQms9-_uf7CLqD9Zd3ZAVFWjamsK6dWw58jg,5863
10
- git_br.py,sha256=NUCqe85VCgouzEpbMVODaScPIsbCrC4pe7zDMDz02Ro,5799
11
- git_ca.py,sha256=0SluqsJaNSaPdcS4c94648ELAm7aHB3aWgIdF1sngT8,4963
12
- git_cleanup.py,sha256=TnUPYAUnByVyY_dwANzDg2BGGNh3jskNF1DgU3pc8Jk,10201
13
- git_co.py,sha256=gBES0ltlomy7vXX8IHh0-Vt1af54t2Ie5UnRYYfP4tM,8212
14
- git_common.py,sha256=ZjNkvIBRDGNLFYwOu9FjeqdDKJdm0sndX5QATtmq290,1879
15
- git_hold.py,sha256=yXpbpwH0cKpRiSAwxsYZncF4XHkJREUiLEyxCWzN8Rg,4617
16
- git_mr.py,sha256=BCE68hhz2bV0zwHkEv5tyfRY0aXoUdb_aJ-yWYDu_Wo,3087
17
- git_parent.py,sha256=D47D01dPs6kActusA0ircJYTv8tBjDoe8MzMpJVWJpA,2683
18
- git_review.py,sha256=1_vGcEgy6TvzoXIIDqsOeRZ4qeweDeNPuLwDQsEH08k,51769
19
- git_update.py,sha256=2SAGeqL2LjdsXTYak3nvPtNfhSOWJdXZfAUx6bqC8Qw,13972
20
- git_wt.py,sha256=pe2VNmNZTlc4su9I1-xnDcui7QVBQ7X3kOIJWQrrfic,3128
21
- gitcmp_helper.py,sha256=_3ji-PyIF2oI6a4zyUPjLeCFgAtACykxPpOrbjD6-aw,11245
22
- gitprompt.py,sha256=SzSMd0EGI7ftPko80Q2PipwbVA-qjU1jsmdpmTCM5GI,8912
23
- gl.py,sha256=9zbGpKxw6lX9RghLkdy-Q5sZlqtbB3uGFO04qTu1dH8,5954
24
- gphotosync.py,sha256=TBxGEwhbMKv47tw1R-9roGPXZE_XYfZTNEe8FsA4AxI,22035
25
- linecount.py,sha256=5voQtjJjDCVx4zjPwVRy620NpuLiwwFitzxjIsRGtxQ,4310
26
- moviemover.py,sha256=j_Xb9_jFdgpFBAXcF4tEqbnKH_FonlnUU39LiCK980k,4470
27
- photodupe.py,sha256=FssLgbLnqHPuSvMGtRyOa7bRdowufJOQaJJ56f9ybxk,4195
28
- phototidier.py,sha256=5gSjlINUxf3ZQl3NG0o7CsWwODvTbokIMIafLFvn8Hc,7818
29
- py_audit.py,sha256=ZyKN8O0fM4xnwVspk1qH_Dnv5ujM7lJfKxC87xWilr0,4395
30
- readable.py,sha256=eZ6nI5TDMncwP74sdPMXrvGTNR7M51-NUGOxRwJpAvA,9474
31
- remdir.py,sha256=-C-LAOaphdKLbBwm--rEwrsDdyldXps-C4s8iDNOKw8,4610
32
- rmdupe.py,sha256=tcX3w8XvliGwBMdSt9BUu07kuDtQEc0IiU8sCxmgzHA,17117
33
- rpylint.py,sha256=TzZ5GvWrqgTKYKZwadTvzdbX-DJ8ll4WfVJqtN6IzO0,2635
34
- splitpics.py,sha256=qRlJrqet7TEI6SodS4bkuKXQUpOdMaqmjE4c1CR7ouo,3266
35
- strreplace.py,sha256=xsIWw0hc452rYEBtNEQFKIzmV03xjm_Taz-eDTmFFKI,2539
36
- sysmon.py,sha256=XRZG6EVSzoVYan_N16qVB1l1RaU51uvLWlRA0CDjC54,11348
37
- tfm.py,sha256=3ejKNI2P65lGz-50mxRMxW_o5NmoeMDcmhji_0uALhI,33703
38
- tfparse.py,sha256=u1IZH2J_WH1aORyMozKSI2JKok7_S1MMJhiobzmhlUI,2988
39
- trimpath.py,sha256=IJU3zl4Hg08g0eU24LZyDlGfNa-5k-TZM5s9zR4OIdA,2385
40
- window_rename.py,sha256=dCBgZqih_3YKHt35hsOAhARFp3QxOi8w8huC63sqJK8,3128
41
- xchmod.py,sha256=F9_lxKuLqVlHHr3oBI3dkMoFOuwRzYDlpQMTmDcjpBI,4590
42
- yamlcheck.py,sha256=FXylZ5NtHirDlPVhVEUZUZkTugVR-g51BbjaN06akAc,2868
43
- thingy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- thingy/colour.py,sha256=D-RTYsND6Xm6m3xl0mOe9QSrTNYsyY0K_a8x3id2gvg,7031
45
- thingy/dc_curses.py,sha256=fuuQPR11zV_akAhygL_cAhVLC5YAgKgowzlITVbETE8,8539
46
- thingy/dc_defaults.py,sha256=ahcteQvoWZrO5iTU68zkIY1Zex6iX5uR5ubwI4CCYBk,6170
47
- thingy/dc_util.py,sha256=Df73imXhHx3HzcPHiRcHAoea0e3HURdLcrolUsMhOFs,1783
48
- thingy/dircolors.py,sha256=5NbXMsGWdABLvvZfB70VPmN6N5HyyihfpgoQq1NRJbg,12264
49
- thingy/docker.py,sha256=9EFatudoVPfB1UbDEtzdJDB3o6ToHiNHv8-oLsUeqiQ,2449
50
- thingy/files.py,sha256=8wXUHEGALhHvYtJewjSNwHFw-hGHFYbWH9_40lJj5ZY,4257
51
- thingy/git.py,sha256=9y58KhFx6t9nNyqMbixM5cl8LBcD2sdCh9UgyVPv4bo,38043
52
- thingy/git2.py,sha256=xfQrOpOk4SLdE6T-pr0FTuYGn0gSY92VMDpmqvX3gDM,35751
53
- thingy/gitlab.py,sha256=uXAF918xnPk6qQyiwPQDbMZfqtJzhiRqDS7yEtJEIAg,6079
54
- thingy/logger.py,sha256=xKgPAq8KGXmtaXIFjFs1AmZJXtYrXJn2sqL3oxHZjfQ,3107
55
- thingy/path.py,sha256=me__Ukw-7NiD70Yd9tOWyj7QX79-deFvsQaQ9AGzWzU,4732
56
- thingy/popup.py,sha256=jW-nbpdeswqEMTli7OmBv1J8XQsvFoMI0J33O6dOeu8,2529
57
- thingy/process.py,sha256=88pKHQZXBP1m3Ja7t3DtKJ4Njn7HS2OtcI0Z0i1KwUs,3560
58
- thingy/run.py,sha256=051lGahG4liYLckQFpmSaGuE9Chd-lFdmJO85LdmeXE,12607
59
- thingy/tfm_pane.py,sha256=40DmQeLMEUPiKKIJkgN1MEpIen00V70I1HB7Q6git44,19814
60
- thingy/tidy.py,sha256=wzkyxzCsHXyY46G3Rjqu4ZrqiL8QMbRXyJEeYOmpy-o,5402
61
- skilleter_thingy-0.0.38.dist-info/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
62
- skilleter_thingy-0.0.38.dist-info/METADATA,sha256=EaLUGKWfalGIZRtHNclkIBAGlumvclBiS9KhQDKjx98,5210
63
- skilleter_thingy-0.0.38.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
64
- skilleter_thingy-0.0.38.dist-info/entry_points.txt,sha256=uML6YXxwLAqsei9dtRTL8E0A-ckylZkowrLZkiRwg_U,1425
65
- skilleter_thingy-0.0.38.dist-info/top_level.txt,sha256=6b-j7cVbNvY_GM72zfBa6gSHa83iCpET98CT4YRZ8Ls,393
66
- skilleter_thingy-0.0.38.dist-info/RECORD,,