patternpythonMinor
Function for finding longest common path and formatting it along with filenames
Viewed 0 times
formattingpathwithfunctionfilenamesforfindingandalonglongest
Problem
This is a function I wrote yesterday and have tested with lots of input. It's been committed and is in use, but no review was done, so it seems like a good candidate for Code Review: it could be more readable and maybe refactored into simpler functions.
Its purpose is to give the longest common path and a string listing filenames for lists of dictionaries with full file paths. It's used to process Bitbucket API results.
```
import os.path
import py # Used for other functions, listed for possible use in refactoring
def getpaths(files, listfiles=False):
"""For a list of files, a common path prefix and optionally list filenames
Returns a tuple (common_prefix, filenames):
common_prefix: Longest common path to all files in the input. If input
is a single file, contains full file path.
Slash-terminated if present and directory, empty string
otherwise.
filenames: String containing the names of modified files, in the format
" M(file1, file2)" if listfiles=True, empty string
if either listfiles=False or no file was modified.
"""
# Handle empty input
if not files:
return '', ''
files = [f['file'] for f in files]
if not any(files):
return '', ''
dirname = os.path.dirname
basename = os.path.basename
common_prefix = [dirname(f) for f in files]
# Single file, show its full path
if len(files) == 1:
common_prefix = files[0]
listfiles = False
else:
common_prefix = [path.split(os.sep) for path in common_prefix]
common_prefix = os.sep.join(os.path.commonprefix(common_prefix))
if common_prefix and not common_prefix.endswith('/'):
common_prefix += '/'
if listfiles:
filenames = [basename(f) for f in files if f and basename(f)]
filenames = ' M(%s)' % ', '.join(filenames)
else:
filenames = ''
return common
Its purpose is to give the longest common path and a string listing filenames for lists of dictionaries with full file paths. It's used to process Bitbucket API results.
```
import os.path
import py # Used for other functions, listed for possible use in refactoring
def getpaths(files, listfiles=False):
"""For a list of files, a common path prefix and optionally list filenames
Returns a tuple (common_prefix, filenames):
common_prefix: Longest common path to all files in the input. If input
is a single file, contains full file path.
Slash-terminated if present and directory, empty string
otherwise.
filenames: String containing the names of modified files, in the format
" M(file1, file2)" if listfiles=True, empty string
if either listfiles=False or no file was modified.
"""
# Handle empty input
if not files:
return '', ''
files = [f['file'] for f in files]
if not any(files):
return '', ''
dirname = os.path.dirname
basename = os.path.basename
common_prefix = [dirname(f) for f in files]
# Single file, show its full path
if len(files) == 1:
common_prefix = files[0]
listfiles = False
else:
common_prefix = [path.split(os.sep) for path in common_prefix]
common_prefix = os.sep.join(os.path.commonprefix(common_prefix))
if common_prefix and not common_prefix.endswith('/'):
common_prefix += '/'
if listfiles:
filenames = [basename(f) for f in files if f and basename(f)]
filenames = ' M(%s)' % ', '.join(filenames)
else:
filenames = ''
return common
Solution
dirname = os.path.dirname
basename = os.path.basenameThis can be written as:
from os.path import dirname, basenameThe from..import will check that os.path is imported (and import it if not), but is otherwise identical. I find it more clear than repeating the names – especially when you get to three or more.
filenames = [basename(f) for f in files if f and basename(f)]This can be simplified, as basename on an empty string gives an empty string:
filenames = filter(None, (basename(f) for f in files))
# or
filenames = [x for x in (basename(f) for f in files) if x]
# or
filenames = [x for x in map(basename, files) if x]Code Snippets
dirname = os.path.dirname
basename = os.path.basenamefrom os.path import dirname, basenamefilenames = [basename(f) for f in files if f and basename(f)]filenames = filter(None, (basename(f) for f in files))
# or
filenames = [x for x in (basename(f) for f in files) if x]
# or
filenames = [x for x in map(basename, files) if x]Context
StackExchange Code Review Q#142, answer score: 9
Revisions (0)
No revisions yet.