Skip to content

Commit

Permalink
feat(commands): label trends report from csv (#315)
Browse files Browse the repository at this point in the history
  • Loading branch information
joe-prosser authored Sep 12, 2024
1 parent 06468c9 commit 07c806b
Show file tree
Hide file tree
Showing 4 changed files with 552 additions and 323 deletions.
37 changes: 33 additions & 4 deletions api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod resources;
pub mod retry;

use chrono::{DateTime, Utc};
use http::Method;
use http::{header::ACCEPT, Method};
use log::debug;
use once_cell::sync::Lazy;
use reqwest::{
Expand Down Expand Up @@ -834,6 +834,7 @@ impl Client {
&None::<()>,
&None::<()>,
&Retry::Yes,
None,
)?;

let mut buffer = Vec::new();
Expand Down Expand Up @@ -1063,6 +1064,26 @@ impl Client {
)
}

pub fn query_dataset_csv(
&self,
dataset_name: &DatasetFullName,
params: &QueryRequestParams,
) -> Result<String> {
let response = self
.raw_request(
&Method::POST,
&self.endpoints.query_dataset(dataset_name)?,
&Some(serde_json::to_value(params).expect("query params serialization error")),
&None::<()>,
&Retry::Yes,
Some(HeaderValue::from_str("text/csv").expect("Could not parse csv header")),
)?
.text()
.expect("Could not get csv text");

Ok(response)
}

pub fn query_dataset(
&self,
dataset_name: &DatasetFullName,
Expand Down Expand Up @@ -1392,17 +1413,25 @@ impl Client {
body: &Option<RequestT>,
query: &Option<QueryT>,
retry: &Retry,
accept_header: Option<HeaderValue>,
) -> Result<reqwest::blocking::Response>
where
LocationT: IntoUrl + Display + Clone,
RequestT: Serialize,
QueryT: Serialize,
{
let mut headers = self.headers.clone();

if let Some(accept_header) = accept_header {
headers.insert(ACCEPT, accept_header);
}

let do_request = || {
let request = self
.http_client
.request(method.clone(), url.clone())
.headers(self.headers.clone());
.headers(headers.clone());

let request = match &query {
Some(query) => request.query(query),
None => request,
Expand Down Expand Up @@ -1499,7 +1528,7 @@ impl Client {
for<'de> SuccessT: Deserialize<'de>,
{
debug!("Attempting {} `{}`", method, url);
let http_response = self.raw_request(method, url, body, query, retry)?;
let http_response = self.raw_request(method, url, body, query, retry, None)?;

let status = http_response.status();

Expand Down Expand Up @@ -2240,7 +2269,7 @@ impl Endpoints {
}
}

const DEFAULT_HTTP_TIMEOUT_SECONDS: u64 = 120;
const DEFAULT_HTTP_TIMEOUT_SECONDS: u64 = 240;

fn build_http_client(config: &Config) -> Result<HttpClient> {
let mut builder = HttpClient::builder()
Expand Down
9 changes: 5 additions & 4 deletions api/src/resources/dataset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ pub struct QueryRequestParams {

pub filter: CommentFilter,

pub limit: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<usize>,

pub order: OrderEnum,
}
Expand Down Expand Up @@ -401,7 +402,7 @@ mod tests {
continuation: Some(Continuation(
"36498883b7f4c2c12cc364be0a44d806-8abb3088feffef3f".to_string(),
)),
limit: 20,
limit: Some(20),
order: OrderEnum::Recent,
};

Expand Down Expand Up @@ -436,7 +437,7 @@ mod tests {
continuation: Some(Continuation(
"36498883b7f4c2c12cc364be0a44d806-8abb3088feffef3f".to_string(),
)),
limit: 20,
limit: Some(20),
order: OrderEnum::ByLabel {
label: "Access Management".to_string(),
},
Expand Down Expand Up @@ -510,7 +511,7 @@ mod tests {
let params = QueryRequestParams {
attribute_filters: Vec::new(),
continuation: None,
limit: 20,
limit: Some(20),
order: OrderEnum::Recent,
filter: CommentFilter {
reviewed: None,
Expand Down
71 changes: 35 additions & 36 deletions cli/src/commands/get/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ pub fn get_single(client: &Client, args: &GetSingleCommentArgs) -> Result<()> {
)
}

const PROPERTY_VALUE_COUNT_CIRCUIT_BREAKER: usize = 256;

pub fn get_user_properties_filter_interactively(summary: &Summary) -> Result<UserPropertiesFilter> {
let string_user_property_selections = MultiSelect::new()
.with_prompt("Select which string user properties you want to set up filters for")
Expand Down Expand Up @@ -226,28 +228,40 @@ pub fn get_user_properties_filter_interactively(summary: &Summary) -> Result<Use
.expect("Could not get property filter action selection from user");

let get_property_value_selections =
|prompt: String,
possible_values: Vec<String>|
-> Result<(Vec<usize>, Vec<PropertyValue>)> {
let selections = MultiSelect::new()
.with_prompt(prompt)
.items(&possible_values)
.interact()?;

Ok((
selections.clone(),
selections
|prompt: String, possible_values: &mut Vec<String>| -> Result<Vec<PropertyValue>> {
if possible_values.len() < PROPERTY_VALUE_COUNT_CIRCUIT_BREAKER {
let selections = MultiSelect::new()
.with_prompt(prompt)
.items(possible_values)
.interact()?;

let values = selections
.iter()
.map(|selection| {
let selection_value = &possible_values[*selection];
PropertyValue::String(selection_value.clone())
})
.collect(),
))
.collect();

for selection in &selections {
possible_values.remove(*selection);
}
Ok(values)
} else {
let comma_sep_values: String = Input::new()
.with_prompt("Please enter your values seperated by comma")
.interact_text()?;

Ok(comma_sep_values
.to_lowercase()
.split(',')
.map(|value| PropertyValue::String(value.trim().to_string()))
.collect())
}
};

let mut filter: PropertyFilter = Default::default();
let possible_values =
let mut possible_values =
get_possible_values_for_string_property(summary, &property.full_name)
.unwrap_or_else(|_| {
panic!(
Expand All @@ -262,53 +276,38 @@ pub fn get_user_properties_filter_interactively(summary: &Summary) -> Result<Use
"What values do you want to include for the property \"{}\"",
property.full_name
),
possible_values,
&mut possible_values,
)
.expect("Could not get property selection from user")
.1
}
"Exclusion" => {
filter.not_one_of = get_property_value_selections(
format!(
"What values do you want to exclude for the property \"{}\"",
property.full_name
),
possible_values,
&mut possible_values,
)
.expect("Could not get property selection from user")
.1
}
"Both" => {
let (idxs, one_ofs) = get_property_value_selections(
let one_ofs = get_property_value_selections(
format!(
"What values do you want to include for the property \"{}\"",
property.full_name
),
possible_values.clone(),
&mut possible_values,
)
.expect("Could not get property selection from user");

let remaining_values: Vec<String> = possible_values
.into_iter()
.enumerate()
.filter_map(|(idx, value)| {
if idxs.contains(&idx) {
None
} else {
Some(value)
}
})
.collect();

let not_one_ofs = get_property_value_selections(
format!(
"What values do you want to exclude for the property \"{}\"",
property.full_name
),
remaining_values,
&mut possible_values,
)
.expect("Could not get property selection from user")
.1;
.expect("Could not get property selection from user");

filter.one_of = one_ofs;
filter.not_one_of = not_one_ofs;
Expand Down Expand Up @@ -830,7 +829,7 @@ fn get_comments_from_uids(
sources: vec![source.id],
messages: options.messages_filter.clone(),
},
limit: DEFAULT_QUERY_PAGE_SIZE,
limit: Some(DEFAULT_QUERY_PAGE_SIZE),
order: if options.shuffle {
OrderEnum::Sample {
seed: rand::thread_rng().gen_range(0..2_i64.pow(31) - 1) as usize,
Expand Down
Loading

0 comments on commit 07c806b

Please sign in to comment.