2626import shutil
2727import subprocess
2828import platform
29- from re import match , I
29+ import fileinput
30+ import re
31+ from datetime import datetime
3032from clint .textui import colored , prompt
3133import adafruit_platformdetect
3234
@@ -42,6 +44,7 @@ class Shell:
4244
4345 def __init__ (self ):
4446 self ._group = None
47+ self ._dirstack = []
4548
4649 @staticmethod
4750 def select_n (message , selections ):
@@ -80,13 +83,22 @@ def run_command(self, cmd, suppress_message=False):
8083
8184 def info (self , message ):
8285 """
83- Display some inforrmation
86+ Display a message with the group in green
8487 """
8588 if self ._group is not None :
8689 print (colored .green (self ._group ) + " " + message )
8790 else :
8891 print (message )
8992
93+ def warn (self , message ):
94+ """
95+ Display a message with the group in yellow
96+ """
97+ if self ._group is not None :
98+ print (colored .yellow (self ._group ) + " " + message )
99+ else :
100+ print (message )
101+
90102 def bail (self , message = None ):
91103 """
92104 Exit and display an error message if given
@@ -133,10 +145,10 @@ def prompt(self, message, *, default=None, force_arg=None):
133145 if reply == "" and default is not None :
134146 return default == "y"
135147
136- if match ("y(?:es)?" , reply , I ):
148+ if re . match ("y(?:es)?" , reply , re . I ):
137149 return True
138150
139- if match ("n(?:o)?" , reply , I ):
151+ if re . match ("n(?:o)?" , reply , re . I ):
140152 return False
141153
142154 @staticmethod
@@ -164,9 +176,34 @@ def chdir(self, directory):
164176 """
165177 Change directory
166178 """
167- if directory [0 ] != "/" and directory [0 ] != "." :
168- directory = self .getcwd () + "/" + directory
169- return os .chdir (directory )
179+ # if directory[0] != "/" and directory[0] != ".":
180+ # directory = self.getcwd() + "/" + directory
181+ directory = self .path (directory )
182+ if not self .exists (directory ):
183+ raise ValueError ("Directory does not exist" )
184+ if not self .isdir (directory ):
185+ raise ValueError ("Given location is not a directory" )
186+ os .chdir (directory )
187+
188+ def pushd (self , directory ):
189+ """
190+ Change directory
191+ """
192+ # Add current dir to stack
193+ self ._dirstack .append (self .getcwd ())
194+ # change dir
195+ self .chdir (directory )
196+
197+ def popd (self ):
198+ """
199+ Change directory
200+ """
201+ # Add current dir to stack
202+ if len (self ._dirstack ) > 0 :
203+ directory = self ._dirstack .pop ()
204+ self .chdir (directory )
205+ else :
206+ raise RuntimeError ("Directory stack empty" )
170207
171208 @staticmethod
172209 def path (file_path ):
@@ -205,6 +242,81 @@ def grep(self, search_term, location):
205242 "grep {} {}" .format (search_term , location ), suppress_message = True
206243 )
207244
245+ @staticmethod
246+ def date ():
247+ """
248+ Return a string containing the current date and time
249+ """
250+ return datetime .now ().ctime ()
251+
252+ def reconfig (self , file , pattern , replacement ):
253+ """
254+ Given a filename, a regex pattern to match and a replacement string,
255+ perform replacement if found, else append replacement to end of file.
256+ """
257+ if not self .isdir (file ):
258+ if self .pattern_search (file , pattern ):
259+ # Pattern found; replace in file
260+ self .pattern_replace (file , pattern , replacement )
261+ else :
262+ # Not found; append (silently)
263+ self .write_text_file (file , replacement , append = True )
264+
265+ def pattern_search (self , location , pattern , multi_line = False ):
266+ """
267+ Similar to grep, but uses pure python
268+ multi_line will search the entire file as a large text glob,
269+ but certain regex patterns such as ^ and $ will not work on a
270+ line-by-line basis
271+ returns True/False if found
272+ """
273+ location = self .path (location )
274+ found = False
275+
276+ if self .exists (location ) and not self .isdir (location ):
277+ if multi_line :
278+ with open (location , "r+" ) as file :
279+ if re .search (pattern , file .read (), flags = re .DOTALL ):
280+ found = True
281+ else :
282+ for line in fileinput .FileInput (location ):
283+ if re .search (pattern , line ):
284+ found = True
285+
286+ return found
287+
288+ def pattern_replace (self , location , pattern , replace = "" , multi_line = False ):
289+ """
290+ Similar to sed, but uses pure python
291+ multi_line will search the entire file as a large text glob,
292+ but certain regex patterns such as ^ and $ will not work on a
293+ line-by-line basis
294+ """
295+ location = self .path (location )
296+ if self .pattern_search (location , pattern , multi_line ):
297+ if multi_line :
298+ regex = re .compile (pattern , flags = re .DOTALL )
299+ with open (location , "r+" ) as file :
300+ data = file .read ()
301+ file .seek (0 )
302+ file .write (regex .sub (replace , data ))
303+ file .truncate ()
304+ file .close ()
305+ else :
306+ regex = re .compile (pattern )
307+ for line in fileinput .FileInput (location , inplace = True ):
308+ if re .search (pattern , line ):
309+ print (regex .sub (replace , line ), end = "" )
310+ else :
311+ print (line , end = "" )
312+
313+ def isdir (self , location ):
314+ """
315+ Check if a location exists and is a directory
316+ """
317+ location = self .path (location )
318+ return os .path .exists (location ) and os .path .isdir (location )
319+
208320 def exists (self , location ):
209321 """
210322 Check if a path or file exists
@@ -267,7 +379,7 @@ def is_armhf():
267379 Check if Platform.machine() (same as uname -m) returns an ARM platform that
268380 supports hardware floating point
269381 """
270- return bool (match ("armv.l" , platform .machine ()))
382+ return bool (re . match ("armv.l" , platform .machine ()))
271383
272384 @staticmethod
273385 def is_armv6 ():
@@ -376,6 +488,13 @@ def kernel_minimum(version):
376488 """
377489 return platform .release () >= str (version )
378490
491+ @staticmethod
492+ def release ():
493+ """
494+ Return the latest kernel release version
495+ """
496+ return platform .release ()
497+
379498 def argument_exists (self , arg , prefix = "-" ):
380499 """
381500 Check if the given argument was supplied
0 commit comments