Skip to content

Commit

Permalink
Add user-specified indenting to render()
Browse files Browse the repository at this point in the history
Add pathlib support to logfile.
Add get_prog_name().
In cull(), allow remove to be a collection.
  • Loading branch information
Ken Kundert authored and Ken Kundert committed Nov 5, 2017
1 parent 4c07484 commit 8a4050c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 21 deletions.
13 changes: 7 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -725,16 +725,17 @@ conjoin(iterable, conj=' and ', sep=', '):
cull(collection, [remove]):
Strips items from a list that have a particular value. By default, it strips
a list of values that if casted to a boolean would have a value of False (0,
False, None, '', (), [], etc.). A particular value may be specified using
the 'remove' as a keyword argument. The value of remove may be a function,
in which case it takes a single item as an argument and returns *True* if
that item should be removed from the list.
a list of values that would be False when cast to a boolean (0, False, None,
'', (), [], etc.). A particular value may be specified using the 'remove'
as a keyword argument. The value of remove may be a collection, in which
case any value in the collection is removed, or it may be a function, in
which case it takes a single item as an argument and returns *True* if that
item should be removed from the list.

fmt(msg, \*args, \**kwargs):
Similar to ''.format(), but it can pull arguments from the local scope.

render(obj, sort=None):
render(obj, sort=None, level=0, tab=' '):
Recursively convert an object to a string with reasonable formatting. Has
built in support for the base Python types (None, bool, int, float, str,
set, tuple, list, and dict). If you confine yourself to these types, the
Expand Down
2 changes: 1 addition & 1 deletion inform/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
InformantFactory, Inform, Error,

# inform functions
done, terminate, terminate_if_errors, errors_accrued,
done, terminate, terminate_if_errors, errors_accrued, get_prog_name,

# built-in informants
log, comment, codicil, narrate, display, output,
Expand Down
49 changes: 35 additions & 14 deletions inform/inform.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def cull(collection, **kwargs):
remove = kwargs['remove']
if callable(remove):
return [each for each in collection if not remove(each)]
elif is_collection(remove):
return [each for each in collection if each not in remove]
else:
return [each for each in collection if each != remove]
except KeyError:
Expand Down Expand Up @@ -183,7 +185,7 @@ def fmt(message, *args, **kwargs):
return message.format(*args, **attrs)

# render {{{2
def render(obj, sort=None, _level=0):
def render(obj, sort=None, level=0, tab=' '):
"""
Recursively convert object to string with reasonable formatting.
Has built in support for the base Python types (None, bool, int, float, str,
Expand All @@ -209,21 +211,21 @@ def order(keys):

# define function for computing the amount of indentation needed
def leader(relative_level=0):
return (_level+relative_level)*' '
return (level+relative_level)*tab

code = []
if type(obj) == dict:
endcaps = '{ }'
content = ['%r: %s' % (k, render(obj[k], sort, _level+1)) for k in order(obj)]
content = ['%r: %s' % (k, render(obj[k], sort, level+1)) for k in order(obj)]
elif type(obj) is list:
endcaps = '[ ]'
content = [render(v, sort, _level+1) for v in obj]
content = [render(v, sort, level+1) for v in obj]
elif type(obj) is tuple:
endcaps = '( )'
content = [render(v, sort, _level+1) for v in obj]
content = [render(v, sort, level+1) for v in obj]
elif type(obj) is set:
endcaps = '{ }'
content = [render(v, sort, _level+1) for v in order(obj)]
content = [render(v, sort, level+1) for v in order(obj)]
elif is_str(obj) and '\n' in obj:
endcaps = None
content = [
Expand Down Expand Up @@ -561,7 +563,7 @@ def notify_user(self, informer):
log=True,
)
notify = InformantFactory(
output=lambda inform: not inform.quiet and not inform.mute,
output=False,
notify=True,
log=True,
)
Expand Down Expand Up @@ -739,7 +741,7 @@ def suppress_output(self, mute):
self.mute = bool(mute)

# set_logfile {{{2
def set_logfile(self, logfile):
def set_logfile(self, logfile, encoding='utf-8'):
try:
if self.logfile:
self.logfile.close()
Expand All @@ -748,12 +750,22 @@ def set_logfile(self, logfile):

if logfile is True:
logfile = '.%s.log' % self.prog_name if self.prog_name else '.log'
if is_str(logfile):
try:
logfile = open(logfile, 'w')
except (IOError, OSError) as err:
print(os_error(err), file=sys.stderr)
logfile = None
try:
if is_str(logfile):
try: # python 3
logfile = open(logfile, 'w', encoding=encoding)
except TypeError: # python 2
import codecs
logfile = codecs.open(logfile, 'w', encoding=encoding)
elif logfile: # pathlib
try:
logfile = logfile.open(mode='w', encoding=encoding)
except AttributeError:
pass
except (IOError, OSError) as err:
print(os_error(err), file=sys.stderr)
logfile = None

self.logfile = logfile
if not logfile:
return
Expand Down Expand Up @@ -951,6 +963,11 @@ def errors_accrued(self, reset=False):
self.errors = 0
return count

# get_prog_name {{{2
def get_prog_name(self, default):
"Returns the program name"
return self.prog_name if self.prog_name else default

# disconnect {{{2
def disconnect(self):
"Disconnect informer"
Expand Down Expand Up @@ -984,6 +1001,10 @@ def terminate_if_errors(status=1):
def errors_accrued(reset=False):
return INFORMER.errors_accrued(reset)

# get_prog_name {{{3
def get_prog_name(default):
return INFORMER.get_prog_name(default)


# Instantiate default informer {{{1
DEFAULT_INFORMER = Inform()
Expand Down

0 comments on commit 8a4050c

Please sign in to comment.