Skip to content

Commit 6790edf

Browse files
author
Juliya Smith
authored
Bugfix/Win-Newlines-and-use-pager (#269)
1 parent 79e292d commit 6790edf

File tree

12 files changed

+45
-38
lines changed

12 files changed

+45
-38
lines changed

CHANGELOG.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
The intended audience of this file is for py42 consumers -- as such, changes that don't affect
99
how a consumer would use the library (e.g. adding unit tests, updating documentation, etc) are not captured here.
1010

11+
## Unreleased
12+
13+
### Fixed
14+
15+
- Bug where some CSV outputs on Windows would have an extra newline between the rows.
16+
17+
- Issue where outputting or sending an alert or file-event with a timestamp without
18+
decimals would error.
19+
20+
### Changed
21+
22+
- `code42 alert-rules list` now outputs via a pager when results contain more than 10 rules.
23+
24+
- `code42 cases list` now outputs via a pager when results contain more than 10 cases.
25+
1126
## 1.4.1 - 2021-04-15
1227

1328
### Added
@@ -18,8 +33,6 @@ how a consumer would use the library (e.g. adding unit tests, updating documenta
1833
- `--end` filters based on an end timestamp.
1934
- `--event-type` filters based on a list of event types.
2035

21-
## 1.4.1 - 2021-04-15
22-
2336
### Fixed
2437

2538
- Arguments/options that read data from files now attempt to autodetect file encodings.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"click>=7.1.1",
3535
"click_plugins>=1.1.1",
3636
"colorama>=0.4.3",
37-
"c42eventextractor==0.4.0",
37+
"c42eventextractor==0.4.1",
3838
"keyring==18.0.1",
3939
"keyrings.alt==3.2.0",
4040
"pandas>=1.1.3",

src/code42cli/cmds/alert_rules.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ def remove_user(state, rule_id, username):
8080
@alert_rules.command("list")
8181
@format_option
8282
@sdk_options()
83-
def list_alert_rules(state, format=None):
83+
def list_alert_rules(state, format):
8484
"""Fetch existing alert rules."""
8585
formatter = OutputFormatter(format, _HEADER_KEYS_MAP)
8686
selected_rules = _get_all_rules_metadata(state.sdk)
87+
8788
if selected_rules:
8889
formatter.echo_formatted_list(selected_rules)
8990

src/code42cli/cmds/auditlogs.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,7 @@ def search(
155155
if not events:
156156
click.echo("No results found.")
157157
return
158-
elif len(events) > 10:
159-
click.echo_via_pager(formatter.get_formatted_output(events))
160-
else:
161-
formatter.echo_formatted_list(events)
158+
formatter.echo_formatted_list(events)
162159

163160

164161
@audit_logs.command(cls=SendToCommand)

src/code42cli/cmds/detectionlists/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,7 @@ def list_employees(employee_generator, output_format, additional_header_items=No
3434
employee_list.append(employee)
3535
if employee_list:
3636
formatter = OutputFormatter(output_format, header)
37-
if len(employee_list) > 10:
38-
output = formatter.get_formatted_output(employee_list)
39-
click.echo_via_pager(output)
40-
else:
41-
formatter.echo_formatted_list(employee_list)
37+
formatter.echo_formatted_list(employee_list)
4238
else:
4339
click.echo("No users found.")
4440

src/code42cli/cmds/devices.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from code42cli.options import format_option
2323
from code42cli.options import sdk_options
2424
from code42cli.output_formats import DataFrameOutputFormatter
25+
from code42cli.output_formats import OutputFormat
2526
from code42cli.output_formats import OutputFormatter
2627

2728

@@ -154,11 +155,11 @@ def _change_device_name(sdk, guid, name):
154155
@devices.command()
155156
@device_guid_argument
156157
@sdk_options()
157-
def show(state, device_guid, format=None):
158+
def show(state, device_guid):
158159
"""Print individual device details. Requires device GUID."""
159160

160-
formatter = OutputFormatter(format, _device_info_keys_map())
161-
backup_set_formatter = OutputFormatter(format, _backup_set_keys_map())
161+
formatter = OutputFormatter(OutputFormat.TABLE, _device_info_keys_map())
162+
backup_set_formatter = OutputFormatter(OutputFormat.TABLE, _backup_set_keys_map())
162163
device_info = _get_device_info(state.sdk, device_guid)
163164
formatter.echo_formatted_list([device_info])
164165
backup_usage = device_info.get("backupUsage")

src/code42cli/cmds/legal_hold.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,7 @@ def search_events(state, matter_id, event_type, begin, end, format):
165165
events = _get_all_events(state.sdk, matter_id, begin, end)
166166
if event_type:
167167
events = [event for event in events if event["eventType"] == event_type]
168-
if len(events) > 10:
169-
output = formatter.get_formatted_output(events)
170-
click.echo_via_pager(output)
171-
else:
172-
formatter.echo_formatted_list(events)
168+
formatter.echo_formatted_list(events)
173169

174170

175171
@legal_hold.group(cls=OrderedGroup)

src/code42cli/cmds/search/extraction.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,7 @@ def handle_response(response):
101101
events = _get_events(sdk, handlers, extractor._key, response)
102102
total_events = len(events)
103103
handlers.TOTAL_EVENTS += total_events
104-
105-
if total_events > 10 or force_pager:
106-
click.echo_via_pager(formatter.get_formatted_output(events))
107-
else:
108-
formatter.echo_formatted_list(events)
104+
formatter.echo_formatted_list(events, force_pager=force_pager)
109105

110106
# To make sure the extractor records correct timestamp event when `CTRL-C` is pressed.
111107
if total_events:

src/code42cli/output_formats.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
CEF_DEFAULT_PRODUCT_NAME = "Advanced Exfiltration Detection"
1414
CEF_DEFAULT_SEVERITY_LEVEL = "5"
15+
OUTPUT_VIA_PAGER_THRESHOLD = 10
1516

1617

1718
class JsonOutputFormat:
@@ -66,12 +67,15 @@ def get_formatted_output(self, output):
6667
for item in output:
6768
yield self._format_output(item)
6869

69-
def echo_formatted_list(self, output_list):
70+
def echo_formatted_list(self, output_list, force_pager=False):
7071
formatted_output = self.get_formatted_output(output_list)
71-
for output in formatted_output:
72-
click.echo(output, nl=False)
73-
if self.output_format in [OutputFormat.TABLE]:
74-
click.echo()
72+
if len(output_list) > OUTPUT_VIA_PAGER_THRESHOLD or force_pager:
73+
click.echo_via_pager(formatted_output)
74+
else:
75+
for output in formatted_output:
76+
click.echo(output, nl=False)
77+
if self.output_format in [OutputFormat.TABLE]:
78+
click.echo()
7579

7680
@property
7781
def _requires_list_output(self):
@@ -124,7 +128,7 @@ def get_formatted_output(self, df, **kwargs):
124128

125129
def echo_formatted_dataframe(self, df, **kwargs):
126130
str_output = self.get_formatted_output(df, **kwargs)
127-
if len(df) <= 10:
131+
if len(df) <= OUTPUT_VIA_PAGER_THRESHOLD:
128132
click.echo(str_output)
129133
else:
130134
click.echo_via_pager(str_output)
@@ -135,7 +139,7 @@ def to_csv(output):
135139

136140
if not output:
137141
return
138-
string_io = io.StringIO()
142+
string_io = io.StringIO(newline=None)
139143
fieldnames = list({k for d in output for k in d.keys()})
140144
writer = csv.DictWriter(string_io, fieldnames=fieldnames)
141145
writer.writeheader()

tests/cmds/search/test_extraction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def _get_timestamp_from_item(self, item):
6464
http_response.text = '{{"{0}": [{{"property": "bar"}}]}}'.format(key)
6565
py42_response = Py42Response(http_response)
6666
handlers.handle_response(py42_response)
67-
formatter.echo_formatted_list.assert_called_once_with(events)
67+
formatter.echo_formatted_list.assert_called_once_with(events, force_pager=False)
6868

6969

7070
def test_send_to_handlers_creates_handlers_that_pass_events_to_logger(

0 commit comments

Comments
 (0)