skilleter-thingy 0.0.54__py3-none-any.whl → 0.0.56__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.

@@ -12,9 +12,9 @@
12
12
  import sys
13
13
  import re
14
14
  import argparse
15
+ import logging
15
16
 
16
- import thingy.logger as logger
17
- import thingy.docker as docker
17
+ from thingy import docker
18
18
 
19
19
  ################################################################################
20
20
 
@@ -35,11 +35,9 @@ def initialise():
35
35
 
36
36
  # Configure logging
37
37
 
38
- log = logger.init('git-prompt')
39
-
40
38
  if args.debug:
41
- log.setLevel(logger.DEBUG)
42
- log.info('Debug logging enabled')
39
+ logging.basicConfig(level=logging.DEBUG)
40
+ logging.info('Debug logging enabled')
43
41
 
44
42
  # Default is to stop matching images
45
43
 
@@ -53,7 +51,7 @@ def initialise():
53
51
  else:
54
52
  args.images = '|'.join(args.images)
55
53
 
56
- log.info('Arguments: %s', args)
54
+ logging.info('Arguments: %s', args)
57
55
  return args
58
56
 
59
57
  ################################################################################
@@ -66,7 +64,7 @@ def main(args):
66
64
  for instance in docker.instances():
67
65
  if re.match(args.images, instance):
68
66
 
69
- print('Stopping instance: %s' % instance)
67
+ print(f'Stopping instance: {instance}')
70
68
 
71
69
  if not args.list:
72
70
  docker.stop(instance, force=args.force)
@@ -75,7 +73,7 @@ def main(args):
75
73
  for instance in docker.instances(all=True):
76
74
  if re.match(args.images, instance):
77
75
 
78
- print('Removing instance: %s' % instance)
76
+ print(f'Removing instance: {instance}')
79
77
 
80
78
  if not args.list:
81
79
  docker.rm(instance)
@@ -84,7 +82,7 @@ def main(args):
84
82
  for image in docker.images():
85
83
  if re.match(args.images, image):
86
84
 
87
- print('Removing image: %s' % image)
85
+ print(f'Removing image: {image}')
88
86
 
89
87
  if not args.list:
90
88
  docker.rmi(image, force=args.force)
skilleter_thingy/ffind.py CHANGED
@@ -27,16 +27,12 @@ import datetime
27
27
  import re
28
28
  import shlex
29
29
  import copy
30
+ import logging
30
31
 
31
- import thingy.git as git
32
- import thingy.logger as logger
33
- import thingy.run as run
34
- import thingy.dircolors as dircolors
35
- import thingy.colour as colour
36
-
37
- ################################################################################
38
-
39
- log = logger.init(__name__)
32
+ from thingy import git
33
+ from thingy import run
34
+ from thingy import dircolors
35
+ from thingy import colour
40
36
 
41
37
  ################################################################################
42
38
 
@@ -75,7 +71,7 @@ def report_file(args, filepath, filestat, dircolour):
75
71
  cmd = copy.copy(args.exec)
76
72
  cmd[cmd.index('^')] = filepath
77
73
 
78
- log.debug('Running "%s"', ' '.join(cmd))
74
+ logging.debug('Running "%s"', ' '.join(cmd))
79
75
 
80
76
  # Attempt to run the command
81
77
 
@@ -212,9 +208,9 @@ def find_stuff(args, dircolour):
212
208
  onerror=None if args.quiet else report_exception,
213
209
  followlinks=args.follow):
214
210
 
215
- log.debug('Root=%s', root)
216
- log.debug('Dirs=%s', dirs)
217
- log.debug('Files=%s', files)
211
+ logging.debug('Root=%s', root)
212
+ logging.debug('Dirs=%s', dirs)
213
+ logging.debug('Files=%s', files)
218
214
 
219
215
  if root[0:2] == './':
220
216
  root = root[2:]
@@ -284,8 +280,8 @@ def validate_arguments(args):
284
280
  # Enable logging
285
281
 
286
282
  if args.debug:
287
- log.setLevel(logger.DEBUG)
288
- log.debug('Debug logging enabled')
283
+ logging.basicConfig(level=logging.DEBUG)
284
+ logging.debug('Debug logging enabled')
289
285
 
290
286
  # Report conflicting options
291
287
 
@@ -15,10 +15,10 @@
15
15
  import os
16
16
  import argparse
17
17
  import sys
18
+ import logging
18
19
 
19
20
  import thingy.colour as colour
20
21
  import thingy.git as git
21
- import thingy.logger as logger
22
22
 
23
23
  ################################################################################
24
24
 
@@ -50,11 +50,9 @@ def main():
50
50
 
51
51
  # Configure logger
52
52
 
53
- log = logger.init(__name__)
54
-
55
53
  if args.verbose:
56
- log.setLevel(logger.INFO)
57
- log.info('Debug logging enabled')
54
+ logging.basicConfig(level=logging.INFO)
55
+ logging.info('Debug logging enabled')
58
56
 
59
57
  # 'Add' implies 'all'
60
58
 
@@ -85,11 +83,11 @@ def main():
85
83
  # Get the list of locally-modified and untracked files, including
86
84
  # files matching .gitignore, if necessary
87
85
 
88
- log.info('Getting list of changed files')
86
+ logging.info('Getting list of changed files')
89
87
  local_changes = git.status_info(args.ignored)
90
88
 
91
89
  for change in local_changes:
92
- log.info('Changed: %s (%s)', change, local_changes[change])
90
+ logging.info('Changed: %s (%s)', change, local_changes[change])
93
91
 
94
92
  if change in current_commit or (args.added and local_changes[change][0] == 'A'):
95
93
  # Locally changed and already in the commit or, optionally, added to it, so update it
@@ -117,7 +115,7 @@ def main():
117
115
  # Perform the commit running in the foreground in case the user is using a console
118
116
  # mode text editor for commit comments.
119
117
 
120
- log.info('Files to commit: %s', files_to_commit)
118
+ logging.info('Files to commit: %s', files_to_commit)
121
119
 
122
120
  try:
123
121
  git.commit(files_to_commit, amend=True, foreground=True, patch=args.patch, dry_run=args.dry_run)
@@ -24,8 +24,8 @@ import logging
24
24
  import sys
25
25
  import argparse
26
26
 
27
- import thingy.git as git
28
- import thingy.colour as colour
27
+ from thingy import git
28
+ from thingy import colour
29
29
 
30
30
  assert sys.version_info.major >= 3 and sys.version_info.minor >= 6
31
31
 
@@ -18,10 +18,12 @@ import thingy.colour as colour
18
18
  def main():
19
19
  """ Main function """
20
20
 
21
+ current_branch = git.branch()
22
+
21
23
  parser = argparse.ArgumentParser(description='Attempt to determine the parent branch for the specified branch (defaulting to the current one)')
22
24
  parser.add_argument('-a', '--all', action='store_true', help='Include feature branches as possible parents')
23
25
  parser.add_argument('-v', '--verbose', action='store_true', help='Report verbose results (includes number of commits between branch and parent)')
24
- parser.add_argument('branch', action='store', nargs='?', type=str, default='HEAD', help='Branch, commit or commit')
26
+ parser.add_argument('branch', action='store', nargs='?', type=str, default=current_branch, help=f'Branch, commit or commit (defaults to current branch; {current_branch})')
25
27
 
26
28
  args = parser.parse_args()
27
29
 
@@ -53,7 +55,7 @@ def main():
53
55
  if len(parents) == 1:
54
56
  colour.write(f'Parent branch [BLUE:{parents[0]}] is [BLUE:{distance}] commits away from [BLUE:{args.branch}]')
55
57
  else:
56
- colour.write(f'Parent branches [BLUE:%s] are [BLUE:{distance}] commits away from [BLUE:{args.branch}[' % (', '.join(parents)))
58
+ colour.write(f'Parent branches [BLUE:%s] are [BLUE:{distance}] commits away from [BLUE:{args.branch}]' % (', '.join(parents)))
57
59
  else:
58
60
  print(', '.join(parents))
59
61
  else:
@@ -78,16 +78,20 @@ def branch_rebase(args, results, branch):
78
78
  colour.error(exc.msg)
79
79
  sys.exit(1)
80
80
 
81
- parents, _ = git.parents()
82
-
83
81
  # Ignore feature branches as potential alternative parents unless told otherwise
84
82
  # If they are the only possible parent(s) then we still consider them.
85
83
 
86
- if not args.all_parents:
87
- filtered_parents = [p for p in parents if not p.startswith('feature/')]
84
+ if args.all_parents:
85
+ parents, _ = git.parents()
86
+ else:
87
+ parents, _ = git.parents(ignore='feature/*' )
88
+
89
+ logging.debug('Probable parents of %s: %s', branch, parents)
90
+
91
+ if not parents:
92
+ parents, _ = git.parents()
88
93
 
89
- if filtered_parents:
90
- parents = filtered_parents
94
+ logging.debug('No non-feature-branch parents found for %s. Feature branch parents could be: %s', branch, parents)
91
95
 
92
96
  # Cheat - if we have multiple possible parents and one is 'develop', 'main' or 'master'
93
97
  # choose it.
@@ -184,10 +188,11 @@ def branch_pull(args, results, branch, fail=True):
184
188
  output = git.pull()
185
189
 
186
190
  colour.write(output, indent=4)
191
+
187
192
  if output[0] == 'Already up-to-date.':
188
193
  results['unchanged'].add(branch)
189
- else:
190
- results['pulled'].add(branch)
194
+
195
+ results['pulled'].add(branch)
191
196
 
192
197
  except git.GitError as exc:
193
198
  if exc.msg.startswith('There is no tracking information for the current branch.'):
@@ -345,6 +350,8 @@ def main():
345
350
  for entry in ('rebased', 'unchanged', 'pulled', 'failed', 'no-tracking'):
346
351
  results[entry] -= results['deleted']
347
352
 
353
+ results['pulled'] -= results['unchanged']
354
+
348
355
  if results['rebased']:
349
356
  report_branches('[BOLD:The following branches have been rebased:]', results['rebased'])
350
357
 
@@ -42,13 +42,13 @@ import os
42
42
  import argparse
43
43
  import filecmp
44
44
  import re
45
+ import logging
45
46
 
46
- import thingy.logger as logger
47
- import thingy.colour as colour
48
- import thingy.run as run
49
- import thingy.files as files
50
- import thingy.git as git
51
- import thingy.dircolors as dircolors
47
+ from thingy import colour
48
+ from thingy import run
49
+ from thingy import files
50
+ from thingy import git
51
+ from thingy import dircolors
52
52
 
53
53
  ################################################################################
54
54
  # Constants
@@ -88,10 +88,6 @@ def report_permissions(perm):
88
88
  def main():
89
89
  """ Main function - does everything """
90
90
 
91
- # Set up logging
92
-
93
- log = logger.init('gitcmp')
94
-
95
91
  # Allow the log level to be configured in git config, as well as via the
96
92
  # GITCMP_DEBUG
97
93
 
@@ -99,7 +95,7 @@ def main():
99
95
  env_debug = os.getenv('GITCMP_DEBUG', '0')
100
96
 
101
97
  if txt_debug.lower() in ('true', '1') or env_debug.lower() in ('true', '1'):
102
- log.setLevel(logger.DEBUG)
98
+ logging.basicConfig(level=logging.INFO)
103
99
 
104
100
  # Parse the command line
105
101
 
@@ -129,17 +125,17 @@ def main():
129
125
 
130
126
  # Debug output
131
127
 
132
- log.info('Parameters to gitcmp-helper:')
133
- log.info('1: path: %s', args.file_path)
134
- log.info('2: old file: %s', args.old_file)
135
- log.info('3: old sha1: %s', args.old_sha1)
136
- log.info('4: old perm: %s', args.old_perm)
137
- log.info('5: new file: %s', args.new_file)
138
- log.info('6: new sha1: %s', args.new_sha1)
139
- log.info('7: new perm: %s', args.new_perm)
140
- log.info('8: new name: %s', args.new_name)
141
- log.info('9: rename : %s', args.rename)
142
- log.info('path count: %d/%d', path_count, path_total)
128
+ logging.info('Parameters to gitcmp-helper:')
129
+ logging.info('1: path: %s', args.file_path)
130
+ logging.info('2: old file: %s', args.old_file)
131
+ logging.info('3: old sha1: %s', args.old_sha1)
132
+ logging.info('4: old perm: %s', args.old_perm)
133
+ logging.info('5: new file: %s', args.new_file)
134
+ logging.info('6: new sha1: %s', args.new_sha1)
135
+ logging.info('7: new perm: %s', args.new_perm)
136
+ logging.info('8: new name: %s', args.new_name)
137
+ logging.info('9: rename : %s', args.rename)
138
+ logging.info('path count: %d/%d', path_count, path_total)
143
139
 
144
140
  # Sanity checks
145
141
 
@@ -178,7 +174,7 @@ def main():
178
174
 
179
175
  current_file_path = os.path.relpath(args.file_path if args.new_name is None else args.new_name, current_path)
180
176
 
181
- log.info('file path: %s', current_file_path)
177
+ logging.info('file path: %s', current_file_path)
182
178
 
183
179
  # Heading printed first
184
180
 
@@ -20,30 +20,37 @@ import os
20
20
  import re
21
21
  import filecmp
22
22
  import shutil
23
+ import logging
23
24
 
24
- import thingy.tidy as tidy
25
- import thingy.files as files
25
+ from thingy import tidy
26
+ from thingy import files
26
27
 
27
28
  ################################################################################
28
29
 
29
- TF_OBJECTS_CHANGED_END = 'Terraform detected the following changes made outside of Terraform since the last "terraform apply":'
30
30
  TF_IGNORE_MSG = 'Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to these changes.'
31
31
 
32
32
  TF_REFRESHING_AND_READING = re.compile(r'.*: (?:Refreshing state\.\.\.|Reading\.\.\.|Still reading\.\.\.|Read complete after |Preparing import\.\.\.).*')
33
33
  TF_FINDING_AND_INSTALLING = re.compile(r'- (?:Finding .*[.]{3}|Installing .*[.]{3}|Installed .*)')
34
34
 
35
- TF_HAS_CHANGED = re.compile(r' # .* has changed')
36
- TF_READ_DURING_APPLY = re.compile(r' +# [-a-z_.0-9\[\]]+ will be read during apply')
37
35
  TF_UNCHANGED_TAG = re.compile(r' +".*" += +".*"')
38
-
39
- TF_OBJECTS_CHANGED = 'Note: Objects have changed outside of Terraform'
40
36
  TF_UNCHANGED_HIDDEN = re.compile(r' +# \(\d+ unchanged (?:attribute|block|element)s? hidden\)')
41
37
 
38
+ TF_HAS_CHANGED = re.compile(r' # .* has changed')
39
+ TF_HAS_CHANGED_END = re.compile(r' [}]')
40
+
41
+ TF_READ_DURING_APPLY = re.compile(r' +# [-a-z_.0-9\[\]]+ will be read during apply')
42
+ TF_READ_DURING_APPLY_END = re.compile(r' [}]')
43
+
42
44
  TF_MISC_REGEX = \
43
45
  [
44
46
  { 'regex': re.compile(r'(Read complete after) \d+s'), 'replace': r'\1 {SECONDS}'}
45
47
  ]
46
48
 
49
+ TF_IGNORE_LIST = [
50
+ {'start': TF_HAS_CHANGED, 'end': TF_HAS_CHANGED_END},
51
+ {'start': TF_READ_DURING_APPLY, 'end': TF_READ_DURING_APPLY_END},
52
+ ]
53
+
47
54
  ################################################################################
48
55
 
49
56
  def parse_command_line():
@@ -63,10 +70,17 @@ def parse_command_line():
63
70
  parser.add_argument('-a', '--aws', action='store_true', help='Remove AWS resource IDs')
64
71
  parser.add_argument('-T', '--terraform', action='store_true', help='Clean Terraform plan/apply log files')
65
72
  parser.add_argument('-R', '--replace', action='append', default=None, help='Additional regex replacements in the form "REGEX=REPLACEMENT"')
73
+ parser.add_argument('-v', '--verbose', action='store_true', help='Output verbose status')
66
74
  parser.add_argument('files', nargs='*', default=None, help='The files to convert (use stdin/stout if no input files are specified)')
67
75
 
68
76
  args = parser.parse_args()
69
77
 
78
+ # Enable logging, if requested
79
+
80
+ if args.verbose:
81
+ logging.basicConfig(level=logging.INFO)
82
+ logging.info('Logging enabled')
83
+
70
84
  # Can't do more than one transformation
71
85
 
72
86
  if args.light + args.dark + args.none + args.debug > 1:
@@ -77,10 +91,11 @@ def parse_command_line():
77
91
  print('ERROR: The tidy and colour conversion options cannot be specified together')
78
92
  sys.exit(1)
79
93
 
80
- # Default to doing cleanup - removing colour codes, times,
94
+ # Default to doing cleanup - removing colour codes, times & Terraform cleanup
81
95
 
82
96
  if not args.light and not args.dark and not args.tidy and not args.strip_blank and not args.terraform:
83
97
  args.strip_blank = args.none = args.tidy = args.terraform = True
98
+ logging.info('No options specified - defaulting to stripping blanks, removing colour codes, tidying and cleaning Terraform data')
84
99
 
85
100
  # Terraform option also removes ANSI, etc.
86
101
 
@@ -90,6 +105,8 @@ def parse_command_line():
90
105
  # Create the output directory, if required
91
106
 
92
107
  if args.dir and not os.path.isdir(args.dir):
108
+ logging.info('Creating output directory %s', args.dir)
109
+
93
110
  os.mkdir(args.dir)
94
111
 
95
112
  # Handle additional regex replacements
@@ -112,13 +129,16 @@ def cleanfile(args, infile, outfile):
112
129
  """ Clean infile, writing to outfile.
113
130
  Returns True if any changes were made. """
114
131
 
115
- # Set if we are ignoring a block of adata
116
-
117
- ignore_until = False
132
+ # Keep the previous line so that we can skip multiple blank lines
118
133
 
119
134
  prev_line = None
120
135
 
136
+ # Set if we are ignoring a block - contains a regex for the end-of-ignore marker
137
+
121
138
  ignore_until = None
139
+
140
+ # Collects data that we are going to output in alphabetical order
141
+
122
142
  collection = []
123
143
 
124
144
  # Read, process and write stdin to stdout, converting appropriately
@@ -173,39 +193,41 @@ def cleanfile(args, infile, outfile):
173
193
  if args.terraform:
174
194
  clean = tidy.regex_replace(clean, TF_MISC_REGEX)
175
195
 
176
- if TF_HAS_CHANGED.fullmatch(clean):
177
- ignore_until = ' }'
178
-
179
- elif TF_READ_DURING_APPLY.fullmatch(clean):
180
- ignore_until = ' }'
196
+ for ignore in TF_IGNORE_LIST:
197
+ if ignore['start'].fullmatch(clean):
198
+ ignore_until = ignore['end']
181
199
 
182
- elif clean == TF_OBJECTS_CHANGED:
183
- ignore_until = TF_OBJECTS_CHANGED_END
200
+ logging.info('Found ignore start marker: "%s"', clean)
201
+ logging.info('Skipping until end marker: "%s"', ignore_until.pattern)
202
+ break
203
+ else:
204
+ if TF_UNCHANGED_HIDDEN.fullmatch(clean):
205
+ clean = None
184
206
 
185
- elif TF_UNCHANGED_HIDDEN.fullmatch(clean):
186
- clean = None
207
+ elif clean == TF_IGNORE_MSG:
208
+ clean = None
187
209
 
188
- elif clean == TF_IGNORE_MSG:
189
- clean = None
210
+ elif TF_UNCHANGED_TAG.fullmatch(clean):
211
+ clean = None
190
212
 
191
- elif TF_UNCHANGED_TAG.fullmatch(clean):
192
- clean = None
213
+ elif TF_REFRESHING_AND_READING.match(clean) or TF_FINDING_AND_INSTALLING.fullmatch(clean):
214
+ # Collect a block of non-deterministically-ordered data
193
215
 
194
- elif TF_REFRESHING_AND_READING.match(clean) or TF_FINDING_AND_INSTALLING.fullmatch(clean):
195
- # Collect a block of non-deterministically-ordered data
216
+ logging.info('Adding "%s" to collection', clean)
217
+ collection.append(clean)
218
+ clean = None
196
219
 
197
- collection.append(clean)
198
- clean = None
220
+ elif collection:
221
+ # If we collected a block, write it out in sorted order
199
222
 
200
- elif collection:
201
- # If we collected a block, write it out in sorted order
223
+ logging.info('Outputting collection of %d lines of sorted text', len(collection))
202
224
 
203
- collection.sort()
204
- for entry in collection:
205
- outfile.write(entry)
206
- outfile.write('\n')
225
+ collection.sort()
226
+ for entry in collection:
227
+ outfile.write(entry)
228
+ outfile.write('\n')
207
229
 
208
- collection = []
230
+ collection = []
209
231
 
210
232
  # Write normal output, skipping >1 blank lines
211
233
 
@@ -218,8 +240,15 @@ def cleanfile(args, infile, outfile):
218
240
 
219
241
  # Clear the ignore flag if we've hid the end marker of the block
220
242
 
221
- if ignore_until and clean == ignore_until:
243
+ if ignore_until and clean and ignore_until.fullmatch(clean):
222
244
  ignore_until = None
245
+ logging.info('Hit end of ignore section')
246
+
247
+ # If we've hit the end and are still ignoring stuff, something's up!
248
+
249
+ if ignore_until:
250
+ print(f'INTERNAL ERROR: Code never found end of ignore-block marker "{ignore_until.pattern}" - either the Terraform output format has changed, or the log file is incomplete!')
251
+ sys.exit(2)
223
252
 
224
253
  ################################################################################
225
254
 
@@ -25,11 +25,9 @@ import os
25
25
  import argparse
26
26
  import fnmatch
27
27
  import shutil
28
+ import logging
28
29
 
29
30
  import thingy.colour as colour
30
- import thingy.logger as logger
31
-
32
- log = logger.init('remdir')
33
31
 
34
32
  ################################################################################
35
33
 
@@ -48,7 +46,10 @@ def main():
48
46
  args = parser.parse_args()
49
47
 
50
48
  if args.debug:
51
- log.setLevel(logger.DEBUG)
49
+ logging.basicConfig(level=logging.DEBUG)
50
+
51
+ if not args.keep:
52
+ args.keep = []
52
53
 
53
54
  # Go through each directory
54
55
 
@@ -60,15 +61,15 @@ def main():
60
61
  # Walk through the directory tree in bottom-up order
61
62
 
62
63
  for root, dirs, files in os.walk(directory, topdown=False):
63
- log.debug('')
64
- log.debug('Directory: %s', root)
65
- log.debug(' Sub-directories : %s', dirs)
66
- log.debug(' Files : %s', files)
64
+ logging.debug('')
65
+ logging.debug('Directory: %s', root)
66
+ logging.debug(' Sub-directories : %s', dirs)
67
+ logging.debug(' Files : %s', files)
67
68
 
68
69
  # Only consider directories with no subdirectories
69
70
 
70
71
  if dirs:
71
- log.debug('Ignoring directory "%s" as it has %d subdirectories', root, len(dirs))
72
+ logging.debug('Ignoring directory "%s" as it has %d subdirectories', root, len(dirs))
72
73
  else:
73
74
  # Count of files (if any) to preserve in the directory
74
75
 
@@ -95,7 +96,7 @@ def main():
95
96
  if keep_dir:
96
97
  colour.write(f'Keeping empty directory [BLUE:{root}]')
97
98
  else:
98
- log.debug('Deleting directory: %s', root)
99
+ logging.debug('Deleting directory: %s', root)
99
100
  colour.write(f'Deleting "[BLUE:{root}]"')
100
101
 
101
102
  if not args.dry_run:
@@ -106,7 +107,7 @@ def main():
106
107
  except OSError:
107
108
  colour.error('Unable to delete "[BLUE:{root}]"')
108
109
  else:
109
- log.debug('Ignoring directory "%s" as it has %d non-ignorable files', root, filecount)
110
+ logging.debug('Ignoring directory "%s" as it has %d non-ignorable files', root, filecount)
110
111
 
111
112
  ################################################################################
112
113
 
@@ -10,8 +10,7 @@
10
10
  ################################################################################
11
11
 
12
12
  import os
13
-
14
- import thingy.logger as logger
13
+ import logging
15
14
 
16
15
  ################################################################################
17
16
 
@@ -30,8 +29,8 @@ def is_subdirectory(root_path, sub_path):
30
29
  abs_sub_path = os.path.abspath(sub_path)
31
30
  abs_root_path = os.path.abspath(root_path)
32
31
 
33
- log.debug('root path: %s', abs_root_path)
34
- log.debug('sub path : %s', abs_sub_path)
32
+ logging.debug('root path: %s', abs_root_path)
33
+ logging.debug('sub path : %s', abs_sub_path)
35
34
 
36
35
  return abs_sub_path.startswith('%s/' % abs_root_path)
37
36
 
@@ -41,8 +40,8 @@ def trimpath(full_path, trim_width):
41
40
  """ Trim a path to a specified maximum width, but always leaving the
42
41
  lowest-level directory (even if it exceeds the trim width). """
43
42
 
44
- log.debug('Path: "%s"', full_path)
45
- log.debug('Required width: %d', trim_width)
43
+ logging.debug('Path: "%s"', full_path)
44
+ logging.debug('Required width: %d', trim_width)
46
45
 
47
46
  full_path = os.path.abspath(full_path)
48
47
 
@@ -58,12 +57,12 @@ def trimpath(full_path, trim_width):
58
57
 
59
58
  if full_path == home_dir:
60
59
  full_path = '~'
61
- log.debug('Converted path to "~"')
60
+ logging.debug('Converted path to "~"')
62
61
 
63
62
  elif is_subdirectory(home_dir, full_path):
64
63
  full_path = "~/%s" % full_path[len(home_dir) + 1:]
65
64
 
66
- log.debug('Converted path to "%s"', full_path)
65
+ logging.debug('Converted path to "%s"', full_path)
67
66
 
68
67
  # If the path is too long then slice it into directories and cut sub-directories
69
68
  # out of the middle until it is short enough. Always leave the last element
@@ -71,7 +70,7 @@ def trimpath(full_path, trim_width):
71
70
 
72
71
  path_len = len(full_path)
73
72
 
74
- log.debug('Path length: %d', path_len)
73
+ logging.debug('Path length: %d', path_len)
75
74
 
76
75
  # Already within maximum width, so just return it
77
76
 
@@ -82,18 +81,18 @@ def trimpath(full_path, trim_width):
82
81
 
83
82
  directories = full_path.split('/')
84
83
 
85
- log.debug('Path has %d elements: "%s"', len(directories), directories)
84
+ logging.debug('Path has %d elements: "%s"', len(directories), directories)
86
85
 
87
86
  if len(directories) == 1:
88
87
  # If there's only one element in the path, just give up
89
88
 
90
- log.debug('Only 1 directory in the path, leaving it as-is')
89
+ logging.debug('Only 1 directory in the path, leaving it as-is')
91
90
 
92
91
  elif len(directories) == 2:
93
92
  # If there's only two elements in the path then replace the first
94
93
  # element with '...' and give up
95
94
 
96
- log.debug('Only 2 directories in the path, so setting the first to "..."')
95
+ logging.debug('Only 2 directories in the path, so setting the first to "..."')
97
96
 
98
97
  directories[0] = '...'
99
98
 
@@ -126,20 +125,18 @@ def trimpath(full_path, trim_width):
126
125
 
127
126
  left -= 1
128
127
 
129
- log.debug('Removing entries %d..%d from the path', left, right)
128
+ logging.debug('Removing entries %d..%d from the path', left, right)
130
129
 
131
130
  directories = directories[0:left + 1] + ['...'] + directories[right:]
132
131
 
133
132
  full_path = '/'.join(directories)
134
133
 
135
- log.debug('Calculated width is %d and actual width is %d', path_len, len(full_path))
134
+ logging.debug('Calculated width is %d and actual width is %d', path_len, len(full_path))
136
135
 
137
136
  return full_path
138
137
 
139
138
  ################################################################################
140
139
 
141
- log = logger.init('tgy_path')
142
-
143
140
  if __name__ == '__main__':
144
141
  PARENT = '/1/2/3/5'
145
142
  CHILD = '/1/2/3/5/6'
@@ -11,8 +11,7 @@
11
11
 
12
12
  import subprocess
13
13
  import sys
14
-
15
- import thingy.logger as logger
14
+ import logging
16
15
 
17
16
  ################################################################################
18
17
 
@@ -36,7 +35,7 @@ def run(command, foreground=False, shell=False):
36
35
 
37
36
  # TODO: for background use subprocess.Popen but use devnull = open('/dev/null', 'w') for stdio and return proc instead of communicating with it?
38
37
 
39
- log.info('Running "%s"', ' '.join(command))
38
+ logging.info('Running "%s"', ' '.join(command))
40
39
 
41
40
  # If running in the foreground, run the command and either return an empty value
42
41
  # on success (output is to the console) or raise a RunError
@@ -62,8 +61,8 @@ def run(command, foreground=False, shell=False):
62
61
  except OSError as exc:
63
62
  raise RunError(exc)
64
63
 
65
- log.info('Stdout: %s', proc.stdout)
66
- log.info('Stderr: %s', proc.stderr)
64
+ logging.info('Stdout: %s', proc.stdout)
65
+ logging.info('Stderr: %s', proc.stderr)
67
66
 
68
67
  # If it returned an error raise a RunError exception with the stdout text as the
69
68
  # exception message
@@ -83,14 +82,14 @@ def run(command, foreground=False, shell=False):
83
82
  while output and output[-1] == '':
84
83
  output = output[:-1]
85
84
 
86
- log.info('Output: %s', output)
85
+ logging.info('Output: %s', output)
87
86
  return output
88
87
 
89
88
  ################################################################################
90
89
 
91
- log = logger.init('tgy_process')
92
-
93
90
  if __name__ == '__main__':
91
+ logging.basicConfig(level=logging.INFO)
92
+
94
93
  print('Run ls -l:')
95
94
 
96
95
  cmd_output = run(['ls', '-l'])
@@ -13,9 +13,9 @@ import sys
13
13
  import os
14
14
  import argparse
15
15
  import shutil
16
+ import logging
16
17
 
17
- import thingy.path as path
18
- import thingy.logger as logger
18
+ from thingy import path
19
19
 
20
20
  ################################################################################
21
21
 
@@ -32,11 +32,8 @@ def main():
32
32
 
33
33
  args = parser.parse_args()
34
34
 
35
- log = logger.init('trimpath')
36
-
37
35
  if args.debug:
38
- if log.getEffectiveLevel() < logger.DEBUG:
39
- log.setLevel(logger.DEBUG)
36
+ logging.basicConfig(level=logging.DEBUG)
40
37
 
41
38
  # Set the width, defaulting to 25% of the console width
42
39
 
@@ -47,7 +44,7 @@ def main():
47
44
  trim_width = -1
48
45
 
49
46
  if trim_width <= 0:
50
- log.critical('Invalid width: "%s"', args.width)
47
+ logging.critical('Invalid width: "%s"', args.width)
51
48
  sys.exit(1)
52
49
  else:
53
50
  console = shutil.get_terminal_size()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: skilleter_thingy
3
- Version: 0.0.54
3
+ Version: 0.0.56
4
4
  Summary: A collection of useful utilities, mainly aimed at making Git more friendly
5
5
  Author-email: John Skilleter <john@skilleter.org.uk>
6
6
  Project-URL: Home, https://skilleter.org.uk
@@ -4,22 +4,22 @@ skilleter_thingy/borger.py,sha256=AQX7OHeGXcUjkgyXEWE2h_oOey9eczZBbKjrreXvRAs,78
4
4
  skilleter_thingy/box.py,sha256=WJlviIvPtpdDUt4MfSMcnIo9OxV3j-ua_CAtR8CTYnc,745
5
5
  skilleter_thingy/console_colours.py,sha256=BOS9mo3jChx_FE8L1j488MDoVNgib11KjTRhrz_YRYE,1781
6
6
  skilleter_thingy/diskspacecheck.py,sha256=7xsj4egXXV6jPhXZTe2b5rS03XAmm5uLC5TeiO1NJoE,2072
7
- skilleter_thingy/docker_purge.py,sha256=2t6yjlxmHCHKMAejLViYyOQNzyqSXGiV59df4Wlojaw,3349
8
- skilleter_thingy/ffind.py,sha256=1MQGnzr-n3TUH2yFphfj4SjYNR3b-6LsdmLjhHJy2e0,19345
7
+ skilleter_thingy/docker_purge.py,sha256=Qsykf_xR9ekn2u5n0ZNK84jMJbp08CilcCw1EAZKX2I,3307
8
+ skilleter_thingy/ffind.py,sha256=XJwH27rTLI0-zGD-7s8viyg7_SZjJaq5Q7VBbJPSYSI,19235
9
9
  skilleter_thingy/ggit.py,sha256=AIhW3S7HC9smgBcHmDsbTLnO6j9VASkeLsBeA0hnCvM,2480
10
10
  skilleter_thingy/ggrep.py,sha256=Mxme8gliQms9-_uf7CLqD9Zd3ZAVFWjamsK6dWw58jg,5863
11
11
  skilleter_thingy/git_br.py,sha256=NUCqe85VCgouzEpbMVODaScPIsbCrC4pe7zDMDz02Ro,5799
12
- skilleter_thingy/git_ca.py,sha256=0SluqsJaNSaPdcS4c94648ELAm7aHB3aWgIdF1sngT8,4963
12
+ skilleter_thingy/git_ca.py,sha256=wzYFaQmT1MyOF-Caz0daAUv7OUvrNKCyemIWMEBW-dA,4944
13
13
  skilleter_thingy/git_cleanup.py,sha256=TnUPYAUnByVyY_dwANzDg2BGGNh3jskNF1DgU3pc8Jk,10201
14
- skilleter_thingy/git_co.py,sha256=gBES0ltlomy7vXX8IHh0-Vt1af54t2Ie5UnRYYfP4tM,8212
14
+ skilleter_thingy/git_co.py,sha256=VhgfUU-rNeEYh4ZQNlQRRusxDrnEOVmWCB1OQWj5WT4,8205
15
15
  skilleter_thingy/git_common.py,sha256=ZjNkvIBRDGNLFYwOu9FjeqdDKJdm0sndX5QATtmq290,1879
16
16
  skilleter_thingy/git_hold.py,sha256=Zk6YUhr08znUOdpVJkJAt0rOtrCXnKE0NHoZzoaEEGo,4616
17
17
  skilleter_thingy/git_mr.py,sha256=2vLzpd5waddNBRlOvQUxwqHVQaK9Rg6FYHb4VMEpS8c,3086
18
- skilleter_thingy/git_parent.py,sha256=D47D01dPs6kActusA0ircJYTv8tBjDoe8MzMpJVWJpA,2683
18
+ skilleter_thingy/git_parent.py,sha256=znw0ehKau-YocFJu2jLBsYSnLJfUvSNFKSDBdQ9_OTo,2774
19
19
  skilleter_thingy/git_review.py,sha256=WCBw49OP3WHiaxku8jUUk6I_NqtjScLGaQHvPxX6LnU,52053
20
- skilleter_thingy/git_update.py,sha256=uYd4ubnDbHzkwwrtzVatNIg-L15ap1X8UMO-2PafseY,13971
20
+ skilleter_thingy/git_update.py,sha256=6mXHSF7fxhKzFxsG3-78JOHYKdmAEE68iq39-Ho5WQU,14181
21
21
  skilleter_thingy/git_wt.py,sha256=dnJSkZGGMaSGeHARQ1ZYwf9yeFLbag-c4w4HwpA2od0,3522
22
- skilleter_thingy/gitcmp_helper.py,sha256=_3ji-PyIF2oI6a4zyUPjLeCFgAtACykxPpOrbjD6-aw,11245
22
+ skilleter_thingy/gitcmp_helper.py,sha256=wutDHpBPOX8ZsXbsC5ApHxMY5tOKgD3P0eyFVs_mSAI,11214
23
23
  skilleter_thingy/gitprompt.py,sha256=SzSMd0EGI7ftPko80Q2PipwbVA-qjU1jsmdpmTCM5GI,8912
24
24
  skilleter_thingy/gl.py,sha256=9zbGpKxw6lX9RghLkdy-Q5sZlqtbB3uGFO04qTu1dH8,5954
25
25
  skilleter_thingy/gphotosync.py,sha256=Vb2zYTEFp26BYdkG810SRg9afyfDqvq4CLHTk-MFf60,22388
@@ -28,8 +28,8 @@ skilleter_thingy/moviemover.py,sha256=j_Xb9_jFdgpFBAXcF4tEqbnKH_FonlnUU39LiCK980
28
28
  skilleter_thingy/photodupe.py,sha256=l0hbzSLb2Vk2ceteg-x9fHXCEE1uUuFo84hz5rsZUPA,4184
29
29
  skilleter_thingy/phototidier.py,sha256=5gSjlINUxf3ZQl3NG0o7CsWwODvTbokIMIafLFvn8Hc,7818
30
30
  skilleter_thingy/py_audit.py,sha256=xJm5k5qyeA6ii8mODa4dOkmP8L1drv94UHuxR54RsIM,4384
31
- skilleter_thingy/readable.py,sha256=pz6g0Rh91SnzzpzrPoYELkBGwljuPiwhb33yANIjAAw,10462
32
- skilleter_thingy/remdir.py,sha256=-C-LAOaphdKLbBwm--rEwrsDdyldXps-C4s8iDNOKw8,4610
31
+ skilleter_thingy/readable.py,sha256=PPR3kBr36-ArFvKumdGB8T04RCvoN_lejabR9BBIFzs,11812
32
+ skilleter_thingy/remdir.py,sha256=SkN9xEc1ckFGRP4zS2LUbx7Ihw697YMV0ybr_-afiyE,4653
33
33
  skilleter_thingy/rmdupe.py,sha256=tcX3w8XvliGwBMdSt9BUu07kuDtQEc0IiU8sCxmgzHA,17117
34
34
  skilleter_thingy/rpylint.py,sha256=TzZ5GvWrqgTKYKZwadTvzdbX-DJ8ll4WfVJqtN6IzO0,2635
35
35
  skilleter_thingy/splitpics.py,sha256=qRlJrqet7TEI6SodS4bkuKXQUpOdMaqmjE4c1CR7ouo,3266
@@ -37,7 +37,7 @@ skilleter_thingy/strreplace.py,sha256=xsIWw0hc452rYEBtNEQFKIzmV03xjm_Taz-eDTmFFK
37
37
  skilleter_thingy/sysmon.py,sha256=XRZG6EVSzoVYan_N16qVB1l1RaU51uvLWlRA0CDjC54,11348
38
38
  skilleter_thingy/tfm.py,sha256=3ejKNI2P65lGz-50mxRMxW_o5NmoeMDcmhji_0uALhI,33703
39
39
  skilleter_thingy/tfparse.py,sha256=u1IZH2J_WH1aORyMozKSI2JKok7_S1MMJhiobzmhlUI,2988
40
- skilleter_thingy/trimpath.py,sha256=IJU3zl4Hg08g0eU24LZyDlGfNa-5k-TZM5s9zR4OIdA,2385
40
+ skilleter_thingy/trimpath.py,sha256=25On5OHTT1rXTzTuRWQeS3FWtTd0XZr5NFDDACR6AGM,2294
41
41
  skilleter_thingy/venv_create.py,sha256=lMcGvWNwP-ZlyPJ1eZU-PHNOnscZHjtjhoT6sLfhIU4,1153
42
42
  skilleter_thingy/window_rename.py,sha256=dCBgZqih_3YKHt35hsOAhARFp3QxOi8w8huC63sqJK8,3128
43
43
  skilleter_thingy/xchmod.py,sha256=F9_lxKuLqVlHHr3oBI3dkMoFOuwRzYDlpQMTmDcjpBI,4590
@@ -53,17 +53,16 @@ skilleter_thingy/thingy/files.py,sha256=oW6E6WWwVFSUPdrZnKMx7P_w_hh3etjoN7RrqvYH
53
53
  skilleter_thingy/thingy/git.py,sha256=qXWIduF4jbP5pKFYt_hW9Ex5iL9mSBBrcNKBkULhRTg,38834
54
54
  skilleter_thingy/thingy/git2.py,sha256=UgdAC1rZWf6Tdl9xB6PAIT6K_3OjD2juCOEQSHEEb90,35530
55
55
  skilleter_thingy/thingy/gitlab.py,sha256=uXAF918xnPk6qQyiwPQDbMZfqtJzhiRqDS7yEtJEIAg,6079
56
- skilleter_thingy/thingy/logger.py,sha256=xKgPAq8KGXmtaXIFjFs1AmZJXtYrXJn2sqL3oxHZjfQ,3107
57
- skilleter_thingy/thingy/path.py,sha256=me__Ukw-7NiD70Yd9tOWyj7QX79-deFvsQaQ9AGzWzU,4732
56
+ skilleter_thingy/thingy/path.py,sha256=8uM2Q9zFRWv_SaVOX49PeecQXttl7J6lsmBuRXWsXKY,4732
58
57
  skilleter_thingy/thingy/popup.py,sha256=jW-nbpdeswqEMTli7OmBv1J8XQsvFoMI0J33O6dOeu8,2529
59
- skilleter_thingy/thingy/process.py,sha256=88pKHQZXBP1m3Ja7t3DtKJ4Njn7HS2OtcI0Z0i1KwUs,3560
58
+ skilleter_thingy/thingy/process.py,sha256=WJLg3js1zdgI7Nlkt7e5ICltkjXcA9P1f-LWPSZCdWs,3570
60
59
  skilleter_thingy/thingy/run.py,sha256=6SNKWF01fSxzB10GMU9ajraXYZqAL1w0PXkqjJdr1Uo,12611
61
60
  skilleter_thingy/thingy/tfm_pane.py,sha256=oqy5zBzKwfbjbGqetbbhpKi4x5He7sl4qkmhUeqtdZc,19789
62
61
  skilleter_thingy/thingy/tidy.py,sha256=0EVUP2XyUTtoIpqaDwvrHL58YxM4Elvu5MO1nzhwLG4,5854
63
62
  skilleter_thingy/thingy/venv_template.py,sha256=SsVNvSwojd8NnFeQaZPCRQYTNdwJRplpZpygbUEXRnY,1015
64
- skilleter_thingy-0.0.54.dist-info/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
65
- skilleter_thingy-0.0.54.dist-info/METADATA,sha256=iR7kxxHCn2O7GdaQt8BTr1VINMx2RPDpRtp1byf7PlQ,5313
66
- skilleter_thingy-0.0.54.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
67
- skilleter_thingy-0.0.54.dist-info/entry_points.txt,sha256=IT6cZSbGHrd2UzIQbiMRotKiTJnYJBkESC4fAe8gjsE,2026
68
- skilleter_thingy-0.0.54.dist-info/top_level.txt,sha256=8-JhgToBBiWURunmvfpSxEvNkDHQQ7r25-aBXtZv61g,17
69
- skilleter_thingy-0.0.54.dist-info/RECORD,,
63
+ skilleter_thingy-0.0.56.dist-info/LICENSE,sha256=ljOS4DjXvqEo5VzGfdaRwgRZPbNScGBmfwyC8PChvmQ,32422
64
+ skilleter_thingy-0.0.56.dist-info/METADATA,sha256=z_KocDUM-WXKzF608kNO9FVKx_sqn2vDB8oyJTUAkXI,5313
65
+ skilleter_thingy-0.0.56.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
66
+ skilleter_thingy-0.0.56.dist-info/entry_points.txt,sha256=IT6cZSbGHrd2UzIQbiMRotKiTJnYJBkESC4fAe8gjsE,2026
67
+ skilleter_thingy-0.0.56.dist-info/top_level.txt,sha256=8-JhgToBBiWURunmvfpSxEvNkDHQQ7r25-aBXtZv61g,17
68
+ skilleter_thingy-0.0.56.dist-info/RECORD,,
@@ -1,112 +0,0 @@
1
- #! /usr/bin/env python3
2
-
3
- ################################################################################
4
- """ Thingy logging functionality - wraps the Pythong logging module
5
-
6
- Copyright (c) 2017 John Skilleter
7
-
8
- Licence: GPL v3 or later
9
- """
10
- ################################################################################
11
-
12
- import os
13
-
14
- import logging
15
-
16
- ################################################################################
17
-
18
- CRITICAL = logging.CRITICAL
19
- ERROR = logging.ERROR
20
- WARNING = logging.WARNING
21
- INFO = logging.INFO
22
- DEBUG = logging.DEBUG
23
- NOTSET = logging.NOTSET
24
-
25
- LOG_LEVELS = {
26
- 'CRITICAL': CRITICAL, 'ERROR': ERROR, 'WARNING': WARNING, 'INFO': INFO,
27
- 'DEBUG': DEBUG, 'NOTSET': NOTSET
28
- }
29
-
30
- __config_done__ = False
31
-
32
- ################################################################################
33
-
34
- def set_logging(log, name):
35
- """ If an environment variable called NAME_DEBUG is set and defines a
36
- log level that is more verbose than the current level then set
37
- that level (you can only increase verbosity via the variable, not
38
- decrease it). """
39
-
40
- # Check whether there is an environment variable setting the debug level
41
-
42
- env_name = '%s_DEBUG' % name.upper()
43
-
44
- value = os.getenv(env_name, None)
45
-
46
- if value is not None:
47
- value = value.upper()
48
-
49
- current = log.getEffectiveLevel()
50
-
51
- # Check for a textual level in the value and if no match, try
52
- # for an integer level ignoring invalid values.
53
-
54
- if value in LOG_LEVELS:
55
- if current > LOG_LEVELS[value]:
56
- log.setLevel(LOG_LEVELS[value])
57
- else:
58
- try:
59
- intlevel = int(value)
60
-
61
- if current > intlevel:
62
- log.setLevel(intlevel)
63
-
64
- except ValueError:
65
- pass
66
-
67
- return log
68
-
69
- ################################################################################
70
-
71
- def init(name):
72
- """ Initilise logging and create a logger.
73
- If the environment variable NAME_DEBUG is set to a value in LOG_LEVELS
74
- then the log level is set to that level. If NAME_DEBUG is an integer
75
- then the same applies, otherwise, by default, the log level is CRITICAL """
76
-
77
- # Create the new logger
78
-
79
- log = logging.getLogger(name)
80
-
81
- # Default log level is CRITICAL
82
-
83
- log.setLevel(CRITICAL)
84
-
85
- # Set logging according to the value of THINGY_DEBUG (if set) then
86
- # override with the logger-specific variable (again, if set)
87
-
88
- set_logging(log, 'THINGY')
89
- set_logging(log, name)
90
-
91
- return log
92
-
93
- ################################################################################
94
- # Entry point
95
-
96
- # Ensure that the logging module is initialise
97
-
98
- if not __config_done__:
99
- logging.basicConfig()
100
- __config_done__ = True
101
-
102
- if __name__ == '__main__':
103
- demo = init('wombat')
104
-
105
- demo.critical('Critical error')
106
-
107
- # These messages should only appear if the WOMBAT_DEBUG environment variable
108
- # is set to an appropriate value (ERROR, WARNING or INFO)
109
-
110
- demo.error('Error message')
111
- demo.warning('Warning message')
112
- demo.info('Info message')