Skip to content

Commit

Permalink
Merge pull request #34 from raimon49/release-1.15.0
Browse files Browse the repository at this point in the history
Release 1.15.0

Close #33
  • Loading branch information
raimon49 authored May 11, 2019
2 parents 49daf63 + 1df2d44 commit c7643d7
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## CHANGELOG

### 1.15.0

* Implement new option `--format=csv`

### 1.14.0

* Implement new option `--from=mixed` as a mixed mode
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Dump the software license list of Python packages installed with pip.
* [Confluence](#confluence)
* [HTML](#html)
* [JSON](#json)
* [CSV](#csv)
* [Deprecated options](#deprecated-options)
* [Option: summary](#option-summary)
* [More Information](#more-information)
Expand Down Expand Up @@ -291,6 +292,17 @@ When executed with the `--format=json` option, you can output list in JSON forma

```

#### CSV

When executed with the `--format=csv` option, you can output list in quoted CSV format. Useful when you want to copy/paste the output to an excel sheet.

```bash
(venv) $ pip-licenses --format=csv
"Name","Version","License"
"Django","2.0.2","BSD"
"pytz","2017.3","MIT"
```

#### Deprecated options

The following options will be deprecated in version 2.0.0. Please migrate to `--format` option.
Expand Down
4 changes: 2 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile -U dev-requirements.in
# pip-compile dev-requirements.in
#
apipkg==1.5 # via execnet
atomicwrites==1.3.0 # via pytest
Expand Down Expand Up @@ -42,4 +42,4 @@ tqdm==4.31.1 # via twine
twine==1.13.0
urllib3==1.24.3 # via requests
webencodings==0.5.1 # via bleach
wheel==0.33.2
wheel==0.33.3
42 changes: 40 additions & 2 deletions piplicenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
HEADER as RULE_HEADER, NONE as RULE_NONE)

__pkgname__ = 'pip-licenses'
__version__ = '1.14.0'
__version__ = '1.15.0'
__author__ = 'raimon'
__license__ = 'MIT License'
__summary__ = ('Dump the software license list of '
Expand Down Expand Up @@ -253,6 +253,39 @@ def get_string(self, **kwargs):
return json.dumps(lines, indent=2, sort_keys=True)


class CSVPrettyTable(PrettyTable):
"""PrettyTable-like class exporting to CSV"""

def get_string(self, **kwargs):

def esc_quotes(val):
"""
Meta-escaping double quotes
https://tools.ietf.org/html/rfc4180
"""
try:
return val.replace('"', '""')
except UnicodeDecodeError: # pragma: no cover
return val.decode('utf-8').replace('"', '""')
except UnicodeEncodeError: # pragma: no cover
return val.encode('unicode_escape').replace('"', '""')

options = self._get_options(kwargs)
rows = self._get_rows(options)
formatted_rows = self._format_rows(rows, options)

lines = []
formatted_header = ','.join(['"%s"' % (esc_quotes(val), )
for val in self._field_names])
lines.append(formatted_header)
for row in formatted_rows:
formatted_row = ','.join(['"%s"' % (esc_quotes(val), )
for val in row])
lines.append(formatted_row)

return '\n'.join(lines)


def factory_styled_table_with_args(args, output_fields=DEFAULT_OUTPUT_FIELDS):
table = PrettyTable()
table.field_names = output_fields
Expand All @@ -272,6 +305,8 @@ def factory_styled_table_with_args(args, output_fields=DEFAULT_OUTPUT_FIELDS):
table.hrules = RULE_NONE
elif args.format == 'json':
table = JsonPrettyTable(table.field_names)
elif args.format == 'csv':
table = CSVPrettyTable(table.field_names)

return table

Expand Down Expand Up @@ -444,6 +479,9 @@ def _compatible_format_args(self, args):
if format_input in ('json', 'j'):
args.format = 'json'

if format_input in ('csv', ):
args.format = 'csv'

if args.from_classifier:
setattr(args, 'from', 'classifier')

Expand Down Expand Up @@ -512,7 +550,7 @@ def create_parser():
default='plain', metavar='STYLE',
help=('dump as set format style\n'
'"plain", "markdown", "rst", "confluence",\n'
'"html", "json"\n'
'"html", "json", "csv"\n'
'default: --format=plain'))
parser.add_argument('-m', '--format-markdown',
action='store_true',
Expand Down
9 changes: 9 additions & 0 deletions test_piplicenses.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,15 @@ def test_format_json(self):
self.assertIn('"Author":', output_string)
self.assertNotIn('"URL":', output_string)

def test_format_csv(self):
format_csv_args = ['--format=csv', '--with-authors']
args = self.parser.parse_args(format_csv_args)
output_string = create_output_string(args)

obtained_header = output_string.split('\n', 1)[0]
expected_header = '"Name","Version","License","Author"'
self.assertEqual(obtained_header, expected_header)

def test_from_compatibility(self):
from_old_style_args = ['--from-classifier']
args = self.parser.parse_args(from_old_style_args)
Expand Down

0 comments on commit c7643d7

Please sign in to comment.