diff --git a/docs/conf.py b/docs/conf.py index 9e7303e5af..1ab3c85c2d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -111,7 +111,7 @@ html_sidebars = {"**": ["versions.html"]} try: - html_context + html_context # noqa: B018 except NameError: html_context = dict() diff --git a/parsons/action_network/action_network.py b/parsons/action_network/action_network.py index 4eb2816b4d..dacb36a7d5 100644 --- a/parsons/action_network/action_network.py +++ b/parsons/action_network/action_network.py @@ -1254,7 +1254,7 @@ def upsert_person( mobile_numbers_field = [{"number": str(mobile_number)}] elif isinstance(mobile_number, list): if len(mobile_number) > 1: - raise ("Action Network allows only 1 phone number per activist") + raise Exception("Action Network allows only 1 phone number per activist") if isinstance(mobile_number[0], list): mobile_numbers_field = [ {"number": re.sub("[^0-9]", "", cell)} for cell in mobile_number @@ -1276,7 +1276,7 @@ def upsert_person( mobile_numbers_field = mobile_number if not email_addresses_field and not mobile_numbers_field: - raise ( + raise Exception( "Either email_address or mobile_number is required and can be formatted " "as a string, list of strings, a dictionary, a list of dictionaries, or " "(for mobile_number only) an integer or list of integers" diff --git a/parsons/auth0/auth0.py b/parsons/auth0/auth0.py index 29049053e5..00f8dbf87c 100644 --- a/parsons/auth0/auth0.py +++ b/parsons/auth0/auth0.py @@ -82,8 +82,8 @@ def upsert_user( username=None, given_name=None, family_name=None, - app_metadata={}, - user_metadata={}, + app_metadata=None, + user_metadata=None, connection="Username-Password-Authentication", ): """ @@ -106,6 +106,10 @@ def upsert_user( Requests Response object """ + if user_metadata is None: + user_metadata = {} + if app_metadata is None: + app_metadata = {} obj = { "email": email.lower(), "username": username, diff --git a/parsons/aws/aws_async.py b/parsons/aws/aws_async.py index cec5c9fc81..e9cf60aab9 100644 --- a/parsons/aws/aws_async.py +++ b/parsons/aws/aws_async.py @@ -46,8 +46,8 @@ def event_command(event, context): def run( func, - args=[], - kwargs={}, + args=None, + kwargs=None, service="lambda", capture_response=False, remote_aws_lambda_function_name=None, @@ -56,6 +56,10 @@ def run( func_class_init_kwargs=None, **task_kwargs, ): + if kwargs is None: + kwargs = {} + if args is None: + args = [] lambda_function_name = remote_aws_lambda_function_name or os.environ.get( "AWS_LAMBDA_FUNCTION_NAME" ) diff --git a/parsons/box/box.py b/parsons/box/box.py index 8f805606f8..946a4e7bde 100644 --- a/parsons/box/box.py +++ b/parsons/box/box.py @@ -399,6 +399,6 @@ def get_item_id(self, path, base_folder_id=DEFAULT_FOLDER_ID) -> str: # recursion, just pass it on up. except ValueError as e: if base_folder_id == DEFAULT_FOLDER_ID: - raise ValueError(f'{e}: "{path}"') + raise ValueError(f'{e}: "{path}"') from e else: raise diff --git a/parsons/copper/copper.py b/parsons/copper/copper.py index 4e3c41882d..06fe46d5ce 100644 --- a/parsons/copper/copper.py +++ b/parsons/copper/copper.py @@ -284,8 +284,8 @@ def process_json(self, json_blob, obj_type, tidy=False): for column in list_cols: # Check for nested data list_rows = obj_table.select_rows( - lambda row: isinstance(row[column], list) - and any(isinstance(x, dict) for x in row[column]) + lambda row: isinstance(row[column], list) # noqa: B023 + and any(isinstance(x, dict) for x in row[column]) # noqa: B023 ) # Add separate long table for each column with nested data if list_rows.num_rows > 0: diff --git a/parsons/databases/alchemy.py b/parsons/databases/alchemy.py index c0e4541f29..393ecde313 100644 --- a/parsons/databases/alchemy.py +++ b/parsons/databases/alchemy.py @@ -77,6 +77,6 @@ def split_table_name(full_table_name): schema, table = full_table_name.split(".") except ValueError as e: if "too many values to unpack" in str(e): - raise ValueError(f"Invalid database table {full_table_name}") + raise ValueError(f"Invalid database table {full_table_name}") from e return schema, table diff --git a/parsons/databases/postgres/postgres_create_statement.py b/parsons/databases/postgres/postgres_create_statement.py index b312349376..348e40a919 100644 --- a/parsons/databases/postgres/postgres_create_statement.py +++ b/parsons/databases/postgres/postgres_create_statement.py @@ -108,7 +108,7 @@ def generate_data_types(self, table): cont = petl.records(table.table) # Populate empty values for the columns - for col in table.columns: + for _col in table.columns: longest.append(0) type_list.append("") diff --git a/parsons/databases/redshift/rs_create_table.py b/parsons/databases/redshift/rs_create_table.py index f6bf4540ec..3d75138523 100644 --- a/parsons/databases/redshift/rs_create_table.py +++ b/parsons/databases/redshift/rs_create_table.py @@ -107,7 +107,7 @@ def generate_data_types(self, table): cont = petl.records(table.table) # Populate empty values for the columns - for col in table.columns: + for _col in table.columns: longest.append(0) type_list.append("") diff --git a/parsons/databases/redshift/rs_table_utilities.py b/parsons/databases/redshift/rs_table_utilities.py index 35f8e7a2fe..dc46e0a826 100644 --- a/parsons/databases/redshift/rs_table_utilities.py +++ b/parsons/databases/redshift/rs_table_utilities.py @@ -755,7 +755,7 @@ def split_full_table_name(full_table_name): schema, table = full_table_name.split(".") except ValueError as e: if "too many values to unpack" in str(e): - raise ValueError(f"Invalid Redshift table {full_table_name}") + raise ValueError(f"Invalid Redshift table {full_table_name}") from e return schema, table diff --git a/parsons/etl/table.py b/parsons/etl/table.py index 82d2d264d2..77ca2bc9df 100644 --- a/parsons/etl/table.py +++ b/parsons/etl/table.py @@ -266,7 +266,7 @@ def is_valid_table(self): return False try: - self.columns + self.columns # noqa: B018 except StopIteration: return False diff --git a/parsons/formstack/formstack.py b/parsons/formstack/formstack.py index 94481b485a..b38681730a 100644 --- a/parsons/formstack/formstack.py +++ b/parsons/formstack/formstack.py @@ -29,7 +29,7 @@ def __init__(self, api_token: Optional[str] = None): self.client = APIConnector(API_URI, headers=headers) def _get_paginated_request( - self, url: str, data_key: str, params: dict = {}, large_request: bool = False + self, url: str, data_key: str, params: dict = None, large_request: bool = False ) -> Table: """ Make a GET request for any endpoint that returns a list of data. Will check pagination. @@ -67,6 +67,8 @@ def _get_paginated_request( Table Class A table with the returned data. """ + if params is None: + params = {} data = Table() page = 1 pages = None diff --git a/parsons/github/github.py b/parsons/github/github.py index 182119fca8..e5e8d49936 100644 --- a/parsons/github/github.py +++ b/parsons/github/github.py @@ -41,10 +41,10 @@ def wrap_github_404(func): def _wrapped_func(*args, **kwargs): try: return (func)(*args, **kwargs) - except UnknownObjectException: + except UnknownObjectException as e: raise ParsonsGitHubError( "Couldn't find the object you referenced, maybe you need to log in?" - ) + ) from e return _wrapped_func @@ -223,7 +223,7 @@ def list_repo_issues( assignee=None, creator=None, mentioned=None, - labels=[], + labels=None, sort="created", direction="desc", since=None, @@ -262,6 +262,8 @@ def list_repo_issues( Table with page of repo issues """ + if labels is None: + labels = [] logger.info(f"Listing page {page} of issues for repo {repo_name}") kwargs_dict = {"state": state, "sort": sort, "direction": direction} diff --git a/parsons/google/google_bigquery.py b/parsons/google/google_bigquery.py index b1454df9c0..5a930f7585 100644 --- a/parsons/google/google_bigquery.py +++ b/parsons/google/google_bigquery.py @@ -155,15 +155,17 @@ def __init__( app_creds: Optional[Union[str, dict, Credentials]] = None, project=None, location=None, - client_options: dict = { - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/bigquery", - "https://www.googleapis.com/auth/cloud-platform", - ] - }, + client_options: dict = None, tmp_gcs_bucket: Optional[str] = None, ): + if client_options is None: + client_options = { + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/bigquery", + "https://www.googleapis.com/auth/cloud-platform", + ] + } self.app_creds = app_creds if isinstance(app_creds, Credentials): @@ -974,7 +976,7 @@ def _stringify_records(self, tbl): if "dict" in field["type"] or "list" in field["type"]: new_petl = tbl.table.addfield( field["name"] + "_replace", - lambda row: json.dumps(row[field["name"]]), + lambda row, field=field: json.dumps(row[field["name"]]), ) new_tbl = Table(new_petl) new_tbl.remove_column(field["name"]) @@ -1034,8 +1036,10 @@ def _prepare_local_upload_job( for column in tbl.columns: try: schema_row = [i for i in job_config.schema if i.name.lower() == column.lower()][0] - except IndexError: - raise IndexError(f"Column found in Table that was not found in schema: {column}") + except IndexError as e: + raise IndexError( + f"Column found in Table that was not found in schema: {column}" + ) from e schema.append(schema_row) job_config.schema = schema diff --git a/parsons/google/google_sheets.py b/parsons/google/google_sheets.py index 9efb55ff8a..d8866049d5 100644 --- a/parsons/google/google_sheets.py +++ b/parsons/google/google_sheets.py @@ -57,8 +57,8 @@ def _get_worksheet(self, spreadsheet_id, worksheet=0): idx = self.list_worksheets(spreadsheet_id).index(worksheet) try: return self.gspread_client.open_by_key(spreadsheet_id).get_worksheet(idx) - except: # noqa: E722 - raise ValueError(f"Couldn't find worksheet {worksheet}") + except Exception as e: # noqa: E722 + raise ValueError(f"Couldn't find worksheet {worksheet}") from e else: raise ValueError(f"Couldn't find worksheet index or title {worksheet}") @@ -288,7 +288,7 @@ def append_to_sheet( cells = [] for row_num, row in enumerate(table.data): - for col_num, cell in enumerate(row): + for col_num, _cell in enumerate(row): # Add 2 to allow for the header row, and for google sheets indexing starting at 1 sheet_row_num = existing_table.num_rows + row_num + 2 cells.append(gspread.Cell(sheet_row_num, col_num + 1, row[col_num])) diff --git a/parsons/newmode/newmode.py b/parsons/newmode/newmode.py index ce821c03e9..68986facc3 100644 --- a/parsons/newmode/newmode.py +++ b/parsons/newmode/newmode.py @@ -53,7 +53,7 @@ def convert_to_table(self, data): return table - def get_tools(self, params={}): + def get_tools(self, params=None): """ Get existing tools. Args: @@ -62,6 +62,8 @@ def get_tools(self, params={}): Returns: Tools information as table. """ + if params is None: + params = {} tools = self.client.getTools(params=params) if tools: return self.convert_to_table(tools) @@ -69,7 +71,7 @@ def get_tools(self, params={}): logging.warning("Empty tools returned") return self.convert_to_table([]) - def get_tool(self, tool_id, params={}): + def get_tool(self, tool_id, params=None): """ Get specific tool. Args: @@ -80,6 +82,8 @@ def get_tool(self, tool_id, params={}): Returns: Tool information. """ + if params is None: + params = {} tool = self.client.getTool(tool_id, params=params) if tool: return tool @@ -87,7 +91,7 @@ def get_tool(self, tool_id, params={}): logging.warning("Empty tool returned") return None - def lookup_targets(self, tool_id, search=None, params={}): + def lookup_targets(self, tool_id, search=None, params=None): """ Lookup targets for a given tool Args: @@ -105,6 +109,8 @@ def lookup_targets(self, tool_id, search=None, params={}): Returns: Targets information as table. """ + if params is None: + params = {} targets = self.client.lookupTargets(tool_id, search, params=params) if targets: data = [] @@ -116,7 +122,7 @@ def lookup_targets(self, tool_id, search=None, params={}): logging.warning("Empty targets returned") return self.convert_to_table([]) - def get_action(self, tool_id, params={}): + def get_action(self, tool_id, params=None): """ Get the action information for a given tool. Args: @@ -127,6 +133,8 @@ def get_action(self, tool_id, params={}): Returns: Tool action information. """ + if params is None: + params = {} action = self.client.getAction(tool_id, params=params) if action: return action @@ -134,7 +142,7 @@ def get_action(self, tool_id, params={}): logging.warning("Empty action returned") return None - def run_action(self, tool_id, payload, params={}): + def run_action(self, tool_id, payload, params=None): """ Run specific action with given payload. Args: @@ -148,6 +156,8 @@ def run_action(self, tool_id, payload, params={}): Returns: Action link (if otl) or sid. """ + if params is None: + params = {} action = self.client.runAction(tool_id, payload, params=params) if action: if "link" in action: @@ -158,7 +168,7 @@ def run_action(self, tool_id, payload, params={}): logging.warning("Error in response") return None - def get_target(self, target_id, params={}): + def get_target(self, target_id, params=None): """ Get specific target. Args: @@ -169,6 +179,8 @@ def get_target(self, target_id, params={}): Returns: Target information. """ + if params is None: + params = {} target = self.client.getTarget(target_id, params=params) if target: return target @@ -176,7 +188,7 @@ def get_target(self, target_id, params={}): logging.warning("Empty target returned") return None - def get_targets(self, params={}): + def get_targets(self, params=None): """ Get all targets @@ -188,6 +200,8 @@ def get_targets(self, params={}): Target information """ + if params is None: + params = {} targets = self.client.getTargets(params=params) if targets: @@ -197,7 +211,7 @@ def get_targets(self, params={}): logging.warning("No targets returned") return None - def get_campaigns(self, params={}): + def get_campaigns(self, params=None): """ Get existing campaigns. Args: @@ -206,6 +220,8 @@ def get_campaigns(self, params={}): Returns: Campaigns information as table. """ + if params is None: + params = {} campaigns = self.client.getCampaigns(params=params) if campaigns: return self.convert_to_table(campaigns) @@ -213,7 +229,7 @@ def get_campaigns(self, params={}): logging.warning("Empty campaigns returned") return self.convert_to_table([]) - def get_campaign(self, campaign_id, params={}): + def get_campaign(self, campaign_id, params=None): """ Get specific campaign. Args: @@ -224,6 +240,8 @@ def get_campaign(self, campaign_id, params={}): Returns: Campaign information. """ + if params is None: + params = {} campaign = self.client.getCampaign(campaign_id, params=params) if campaign: return campaign @@ -231,7 +249,7 @@ def get_campaign(self, campaign_id, params={}): logging.warning("Empty campaign returned") return None - def get_organizations(self, params={}): + def get_organizations(self, params=None): """ Get existing organizations. Args: @@ -240,6 +258,8 @@ def get_organizations(self, params={}): Returns: Organizations information as table. """ + if params is None: + params = {} organizations = self.client.getOrganizations(params=params) if organizations: return self.convert_to_table(organizations) @@ -247,7 +267,7 @@ def get_organizations(self, params={}): logging.warning("Empty organizations returned") return self.convert_to_table([]) - def get_organization(self, organization_id, params={}): + def get_organization(self, organization_id, params=None): """ Get specific organization. Args: @@ -258,6 +278,8 @@ def get_organization(self, organization_id, params={}): Returns: Organization information. """ + if params is None: + params = {} organization = self.client.getOrganization(organization_id, params=params) if organization: return organization @@ -265,7 +287,7 @@ def get_organization(self, organization_id, params={}): logging.warning("Empty organization returned") return None - def get_services(self, params={}): + def get_services(self, params=None): """ Get existing services. Args: @@ -274,6 +296,8 @@ def get_services(self, params={}): Returns: Services information as table. """ + if params is None: + params = {} services = self.client.getServices(params=params) if services: return self.convert_to_table(services) @@ -281,7 +305,7 @@ def get_services(self, params={}): logging.warning("Empty services returned") return self.convert_to_table([]) - def get_service(self, service_id, params={}): + def get_service(self, service_id, params=None): """ Get specific service. Args: @@ -292,6 +316,8 @@ def get_service(self, service_id, params={}): Returns: Service information. """ + if params is None: + params = {} service = self.client.getService(service_id, params=params) if service: return service @@ -299,7 +325,7 @@ def get_service(self, service_id, params={}): logging.warning("Empty service returned") return None - def get_outreaches(self, tool_id, params={}): + def get_outreaches(self, tool_id, params=None): """ Get existing outreaches for a given tool. Args: @@ -310,6 +336,8 @@ def get_outreaches(self, tool_id, params={}): Returns: Outreaches information as table. """ + if params is None: + params = {} outreaches = self.client.getOutreaches(tool_id, params=params) if outreaches: return self.convert_to_table(outreaches) @@ -317,7 +345,7 @@ def get_outreaches(self, tool_id, params={}): logging.warning("Empty outreaches returned") return self.convert_to_table([]) - def get_outreach(self, outreach_id, params={}): + def get_outreach(self, outreach_id, params=None): """ Get specific outreach. Args: @@ -328,6 +356,8 @@ def get_outreach(self, outreach_id, params={}): Returns: Outreach information. """ + if params is None: + params = {} outreach = self.client.getOutreach(outreach_id, params=params) if outreach: return outreach @@ -381,7 +411,7 @@ def base_request( data=None, json=None, data_key=None, - params={}, + params=None, supports_version=True, override_api_version=None, ): @@ -389,6 +419,8 @@ def base_request( Internal method to instantiate OAuth2APIConnector class, make a call to Newmode API, and validate the response. """ + if params is None: + params = {} api_version = override_api_version if override_api_version else self.api_version url = f"{api_version}/{endpoint}" if supports_version else endpoint response = client.request(url=url, req_type=method, json=json, data=data, params=params) @@ -407,7 +439,7 @@ def converted_request( supports_version=True, data=None, json=None, - params={}, + params=None, convert_to_table=True, data_key=None, client=None, @@ -415,6 +447,8 @@ def converted_request( ): """Internal method to make a call to the Newmode API and convert the result to a Parsons table.""" + if params is None: + params = {} client = client if client else self.default_client response = self.base_request( method=method, @@ -433,7 +467,7 @@ def converted_request( else: return response - def get_campaign(self, campaign_id, params={}): + def get_campaign(self, campaign_id, params=None): """ Retrieve a specific campaign by ID. @@ -446,6 +480,8 @@ def get_campaign(self, campaign_id, params={}): `Returns:` Parsons Table containing campaign data. """ + if params is None: + params = {} endpoint = f"/campaign/{campaign_id}/form" data = self.converted_request( endpoint=endpoint, @@ -454,7 +490,7 @@ def get_campaign(self, campaign_id, params={}): ) return data - def get_campaign_ids(self, params={}): + def get_campaign_ids(self, params=None): """ Retrieve all campaigns In v2, a campaign is equivalent to Tools or Actions in V1. @@ -466,6 +502,8 @@ def get_campaign_ids(self, params={}): `Returns:` List containing all campaign ids. """ + if params is None: + params = {} endpoint = "node/action" campaigns_client = OAuth2APIConnector( uri=V2_API_CAMPAIGNS_URL, @@ -494,7 +532,7 @@ def get_recipient( city=None, postal_code=None, region=None, - params={}, + params=None, ): """ Retrieve a specific recipient by ID @@ -514,6 +552,8 @@ def get_recipient( `Returns:` Parsons Table containing recipient data. """ + if params is None: + params = {} address_params = { "street_address": street_address, "city": city, @@ -534,7 +574,7 @@ def get_recipient( ) return response - def run_submit(self, campaign_id, json=None, data=None, params={}): + def run_submit(self, campaign_id, json=None, data=None, params=None): """ Pass a submission from a supporter to a campaign that ultimately fills in a petition, @@ -550,6 +590,8 @@ def run_submit(self, campaign_id, json=None, data=None, params={}): Parsons Table containing submit data. """ + if params is None: + params = {} response = self.converted_request( endpoint=f"campaign/{campaign_id}/submit", method="POST", @@ -560,7 +602,7 @@ def run_submit(self, campaign_id, json=None, data=None, params={}): ) return response - def get_submissions(self, campaign_id, params={}): + def get_submissions(self, campaign_id, params=None): """ Retrieve and sort submissions and contact data for a specified campaign using a range of filters @@ -572,6 +614,8 @@ def get_submissions(self, campaign_id, params={}): `Returns:` Parsons Table containing submit data. """ + if params is None: + params = {} params = {"action": campaign_id} response = self.converted_request(endpoint="submission", method="GET", params=params) return response diff --git a/parsons/ngpvan/events.py b/parsons/ngpvan/events.py index 0d535417d5..3931ac14b4 100644 --- a/parsons/ngpvan/events.py +++ b/parsons/ngpvan/events.py @@ -19,16 +19,7 @@ def get_events( starting_after=None, starting_before=None, district_field=None, - expand_fields=[ - "locations", - "codes", - "shifts", - "roles", - "notes", - "financialProgram", - "ticketCategories", - "onlineForms", - ], + expand_fields=None, ): """ Get events. @@ -56,6 +47,17 @@ def get_events( See :ref:`parsons-table` for output options. """ + if expand_fields is None: + expand_fields = [ + "locations", + "codes", + "shifts", + "roles", + "notes", + "financialProgram", + "ticketCategories", + "onlineForms", + ] if expand_fields: expand_fields = ",".join(expand_fields) @@ -77,16 +79,7 @@ def get_events( def get_event( self, event_id, - expand_fields=[ - "locations", - "codes", - "shifts", - "roles", - "notes", - "financialProgram", - "ticketCategories", - "voterRegistrationBatches", - ], + expand_fields=None, ): """ Get an event. @@ -104,6 +97,17 @@ def get_event( See :ref:`parsons-table` for output options. """ + if expand_fields is None: + expand_fields = [ + "locations", + "codes", + "shifts", + "roles", + "notes", + "financialProgram", + "ticketCategories", + "voterRegistrationBatches", + ] if expand_fields: expand_fields = ",".join(expand_fields) diff --git a/parsons/ngpvan/people.py b/parsons/ngpvan/people.py index c7ce7f2430..90c9aac38a 100644 --- a/parsons/ngpvan/people.py +++ b/parsons/ngpvan/people.py @@ -405,27 +405,7 @@ def get_person( self, id, id_type="vanid", - expand_fields=[ - "contribution_history", - "addresses", - "phones", - "emails", - "codes", - "custom_fields", - "external_ids", - "preferences", - "recorded_addresses", - "reported_demographics", - "suppressions", - "cases", - "custom_properties", - "districts", - "election_records", - "membership_statuses", - "notes", - "organization_roles", - "disclosure_field_values", - ], + expand_fields=None, ): """ Returns a single person record using their VANID or external id. @@ -449,6 +429,28 @@ def get_person( """ # Change end point based on id type + if expand_fields is None: + expand_fields = [ + "contribution_history", + "addresses", + "phones", + "emails", + "codes", + "custom_fields", + "external_ids", + "preferences", + "recorded_addresses", + "reported_demographics", + "suppressions", + "cases", + "custom_properties", + "districts", + "election_records", + "membership_statuses", + "notes", + "organization_roles", + "disclosure_field_values", + ] url = "people/" id_type = "" if id_type in ("vanid", None) else f"{id_type}:" diff --git a/parsons/ngpvan/survey_questions.py b/parsons/ngpvan/survey_questions.py index c1e8252f6f..58574d7ce9 100644 --- a/parsons/ngpvan/survey_questions.py +++ b/parsons/ngpvan/survey_questions.py @@ -12,7 +12,7 @@ def __init__(self, van_connection): self.connection = van_connection def get_survey_questions( - self, statuses=["Active"], name=None, sq_type=None, question=None, cycle=None + self, statuses=None, name=None, sq_type=None, question=None, cycle=None ): """ Get survey questions. @@ -34,6 +34,8 @@ def get_survey_questions( See :ref:`parsons-table` for output options. """ + if statuses is None: + statuses = ["Active"] params = { "statuses": statuses, "$top": self.page_size, diff --git a/parsons/notifications/slack.py b/parsons/notifications/slack.py index 02ab6f4188..6c0e616ec3 100644 --- a/parsons/notifications/slack.py +++ b/parsons/notifications/slack.py @@ -16,18 +16,18 @@ def __init__(self, api_key=None): try: self.api_key = os.environ["SLACK_API_TOKEN"] - except KeyError: + except KeyError as e: raise KeyError( "Missing api_key. It must be passed as an " "argument or stored as environmental variable" - ) + ) from e else: self.api_key = api_key self.client = SlackClient(self.api_key) - def channels(self, fields=["id", "name"], exclude_archived=False, types=["public_channel"]): + def channels(self, fields=None, exclude_archived=False, types=None): """ Return a list of all channels in a Slack team. @@ -48,6 +48,10 @@ def channels(self, fields=["id", "name"], exclude_archived=False, types=["public Parsons Table See :ref:`parsons-table` for output options. """ + if types is None: + types = ["public_channel"] + if fields is None: + fields = ["id", "name"] tbl = self._paginate_request( "conversations.list", "channels", @@ -65,13 +69,7 @@ def channels(self, fields=["id", "name"], exclude_archived=False, types=["public def users( self, - fields=[ - "id", - "name", - "deleted", - "profile_real_name_normalized", - "profile_email", - ], + fields=None, ): """ Return a list of all users in a Slack team. @@ -87,6 +85,8 @@ def users( See :ref:`parsons-table` for output options. """ + if fields is None: + fields = ["id", "name", "deleted", "profile_real_name_normalized", "profile_email"] tbl = self._paginate_request("users.list", "members", include_locale=True) tbl.unpack_dict("profile", include_original=False, prepend=True, prepend_value="profile") diff --git a/parsons/pdi/flags.py b/parsons/pdi/flags.py index 82ad36c438..795ab53b25 100644 --- a/parsons/pdi/flags.py +++ b/parsons/pdi/flags.py @@ -29,8 +29,8 @@ def get_flags(self, start_date, end_date, limit=None): try: start_date = parse(start_date).date().isoformat() end_date = parse(end_date).date().isoformat() - except ValueError: - raise ValueError("Invalid date format.") + except ValueError as e: + raise ValueError("Invalid date format.") from e params = { "startDate": start_date, @@ -61,8 +61,8 @@ def create_flags(self, flag_list: list): flag["flagEntryDate"] = str( datetime.strptime(flag["flagEntryDate"], "%Y-%m-%d").isoformat() ) - except ValueError: - raise ValueError("Invalid date format.") + except ValueError as e: + raise ValueError("Invalid date format.") from e print(flag_list) return self._request(self.url_flags, post_data=flag_list, req_type="POST") diff --git a/parsons/phone2action/p2a.py b/parsons/phone2action/p2a.py index 8c04283a61..b24e4b2e81 100644 --- a/parsons/phone2action/p2a.py +++ b/parsons/phone2action/p2a.py @@ -27,8 +27,8 @@ def __init__(self, app_id=None, app_key=None): def __getattr__(self, name): try: return getattr(self.capitol_canary, name) - except AttributeError: - raise AttributeError(f"{type(self).__name__} object has no attribute {name}") + except AttributeError as e: + raise AttributeError(f"{type(self).__name__} object has no attribute {name}") from e def get_advocates(self, state=None, campaign_id=None, updated_since=None, page=None): """ diff --git a/parsons/utilities/api_connector.py b/parsons/utilities/api_connector.py index d780a09972..24bd5ac5ca 100644 --- a/parsons/utilities/api_connector.py +++ b/parsons/utilities/api_connector.py @@ -108,9 +108,7 @@ def get_request(self, url, params=None, return_format="json"): else: raise RuntimeError(f"{return_format} is not a valid format, change to json or content") - def post_request( - self, url, params=None, data=None, json=None, success_codes=[200, 201, 202, 204] - ): + def post_request(self, url, params=None, data=None, json=None, success_codes=None): """ Make a POST request. @@ -129,6 +127,8 @@ def post_request( A requests response object """ + if success_codes is None: + success_codes = [200, 201, 202, 204] r = self.request(url, "POST", params=params, data=data, json=json) # Validate the response and lift up an errors. @@ -142,7 +142,7 @@ def post_request( else: return r.status_code - def delete_request(self, url, params=None, success_codes=[200, 201, 204]): + def delete_request(self, url, params=None, success_codes=None): """ Make a DELETE request. @@ -157,6 +157,8 @@ def delete_request(self, url, params=None, success_codes=[200, 201, 204]): A requests response object or status code """ + if success_codes is None: + success_codes = [200, 201, 204] r = self.request(url, "DELETE", params=params) self.validate_response(r) @@ -169,7 +171,7 @@ def delete_request(self, url, params=None, success_codes=[200, 201, 204]): else: return r.status_code - def put_request(self, url, data=None, json=None, params=None, success_codes=[200, 201, 204]): + def put_request(self, url, data=None, json=None, params=None, success_codes=None): """ Make a PUT request. @@ -186,6 +188,8 @@ def put_request(self, url, data=None, json=None, params=None, success_codes=[200 A requests response object """ + if success_codes is None: + success_codes = [200, 201, 204] r = self.request(url, "PUT", params=params, data=data, json=json) self.validate_response(r) @@ -196,7 +200,7 @@ def put_request(self, url, data=None, json=None, params=None, success_codes=[200 else: return r.status_code - def patch_request(self, url, params=None, data=None, json=None, success_codes=[200, 201, 204]): + def patch_request(self, url, params=None, data=None, json=None, success_codes=None): """ Make a PATCH request. @@ -215,6 +219,8 @@ def patch_request(self, url, params=None, data=None, json=None, success_codes=[2 A requests response object """ + if success_codes is None: + success_codes = [200, 201, 204] r = self.request(url, "PATCH", params=params, data=data, json=json) self.validate_response(r) diff --git a/parsons/utilities/check_env.py b/parsons/utilities/check_env.py index 284d99538d..1103cf4a80 100644 --- a/parsons/utilities/check_env.py +++ b/parsons/utilities/check_env.py @@ -11,9 +11,9 @@ def check(env: str, field: Optional[str], optional: Optional[bool] = False) -> U if not field: try: return os.environ[env] - except KeyError: + except KeyError as e: if not optional: raise KeyError( f"No {env} found. Store as environment variable or pass as an argument." - ) + ) from e return field diff --git a/parsons/zoom/zoom.py b/parsons/zoom/zoom.py index 698a618c8c..5dc3aede0b 100644 --- a/parsons/zoom/zoom.py +++ b/parsons/zoom/zoom.py @@ -574,7 +574,7 @@ class ZoomV2(ZoomV1): def __init__(self, account_id=None, client_id=None, client_secret=None): super().__init__(account_id, client_id, client_secret) - def _get_request(self, endpoint: str, data_key: str, params: dict = {}, **kwargs): + def _get_request(self, endpoint: str, data_key: str, params: dict = None, **kwargs): """ `Args`: endpoint: str @@ -590,6 +590,8 @@ def _get_request(self, endpoint: str, data_key: str, params: dict = {}, **kwargs See :ref:`parsons-table` for output options. """ + if params is None: + params = {} if not params: params = {"page_size": 300} diff --git a/pyproject.toml b/pyproject.toml index 77c691fcb3..be75fc8384 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ target-version = "py39" # Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or # McCabe complexity (`C901`) by default. select = [ + "B", # flake8-bugbear (B) "E", # pycodestyle errors (E) "W", # pycodestyle warnings (W) "F", # Pyflakes (F) diff --git a/test/test_airmeet.py b/test/test_airmeet.py index 5b75c1d628..bd7e506da6 100644 --- a/test/test_airmeet.py +++ b/test/test_airmeet.py @@ -280,7 +280,7 @@ def test_fetch_session_attendance_exception_202(self): } ) - with pytest.raises(Exception): + with pytest.raises(Exception): # noqa: B017 self.airmeet.fetch_session_attendance("test_session_id") def test_fetch_session_attendance_exception_400(self): @@ -294,7 +294,7 @@ def test_fetch_session_attendance_exception_400(self): } ) - with pytest.raises(Exception): + with pytest.raises(Exception): # noqa: B017 self.airmeet.fetch_session_attendance("test_session_id") def test_fetch_airmeet_booths(self): @@ -506,5 +506,5 @@ def test_fetch_event_replay_attendance_exception_400(self): } ) - with pytest.raises(Exception): + with pytest.raises(Exception): # noqa: B017 self.airmeet.fetch_event_replay_attendance("test_airmeet_id") diff --git a/test/test_databases/test_bigquery.py b/test/test_databases/test_bigquery.py index 6474b911ba..67968c2be5 100644 --- a/test/test_databases/test_bigquery.py +++ b/test/test_databases/test_bigquery.py @@ -236,7 +236,7 @@ def test_copy_gcs__if_exists_fail(self): bq.table_exists.return_value = True # call the method being tested - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 bq.copy_from_gcs( self.default_table, "dataset.table", diff --git a/test/test_databases/test_sqlite.py b/test/test_databases/test_sqlite.py index 5887184c39..9b16d1a80c 100644 --- a/test/test_databases/test_sqlite.py +++ b/test/test_databases/test_sqlite.py @@ -35,7 +35,7 @@ def test_copy_fail(self) -> None: # This line should raise a ValueError self.sqlite.copy(self.tbl, "tbl1", if_exists="fail") # so this line should not be executed - assert False, "should have failed" + raise AssertionError("should have failed") except ValueError: pass diff --git a/test/test_targetsmart/test_targetsmart_api.py b/test/test_targetsmart/test_targetsmart_api.py index 7454c4bae2..afa3d52c13 100644 --- a/test/test_targetsmart/test_targetsmart_api.py +++ b/test/test_targetsmart/test_targetsmart_api.py @@ -102,15 +102,15 @@ def test_data_enhance(self, m): self.assertTrue(validate_list(expected, self.ts.data_enhance("IL-12568678"))) # Assert exception on missing state - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 self.ts.data_enhance("vb0001", search_id_type="votebuilder") # Assert exception on missing state - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 self.ts.data_enhance("vb0001", search_id_type="smartvan") # Assert exception on missing state - with self.assertRaises(Exception): + with self.assertRaises(Exception): # noqa: B017 self.ts.data_enhance("vb0001", search_id_type="voter") # Assert works with state provided diff --git a/test/test_van/test_ngpvan.py b/test/test_van/test_ngpvan.py index 6183fc763d..4d1b98412f 100644 --- a/test/test_van/test_ngpvan.py +++ b/test/test_van/test_ngpvan.py @@ -105,7 +105,7 @@ def test_get_supporter_groups(self, m): m.get(self.van.connection.uri + "supporterGroups", json=json) - ["id", "name", "description"] + ["id", "name", "description"] # noqa: B018 self.van.get_supporter_groups() diff --git a/useful_resources/sample_code/apply_activist_code.py b/useful_resources/sample_code/apply_activist_code.py index b11a78c536..9692d8c5d0 100644 --- a/useful_resources/sample_code/apply_activist_code.py +++ b/useful_resources/sample_code/apply_activist_code.py @@ -62,10 +62,10 @@ # Apply codes segmented by state (different API Keys) for state, key in myv_keys.items(): - state_set = records.select_rows(lambda row: row.vb_vf_source_state == state) + state_set = records.select_rows(lambda row: row.vb_vf_source_state == state) # noqa: B023 if len(state_set) > 0: logger.info(f"Applying {str(len(state_set))} Activist Codes in {state}...") - for vanid in state_set: + for _vanid in state_set: # TODO: row undefined, select row form record? row = None key.toggle_activist_code(row["vb_smartvan_id"], row["activist_code_id"], "apply") diff --git a/useful_resources/sample_code/mysql_to_googlesheets.py b/useful_resources/sample_code/mysql_to_googlesheets.py index 4b70f46480..4969578fc4 100644 --- a/useful_resources/sample_code/mysql_to_googlesheets.py +++ b/useful_resources/sample_code/mysql_to_googlesheets.py @@ -49,7 +49,7 @@ def try_overwrite(table, request_count, sheet_id, tab_index): except APIError as e: print(f"trying to overwrite {tab_index} for the {request_count}th time") if request_count > 60: - raise APIError(e) + raise APIError from e time.sleep(80) request_count += 1 try_overwrite(table, request_count, sheet_id, tab_index) @@ -60,7 +60,7 @@ def main(): try: new_sheet = gsheets.create_spreadsheet(title=TITLE, editor_email=None, folder_id=FOLDER_ID) - # If successful new_sheet will be the spreadsheet's ID in a string + # If successful new_sheet will be the sprkeadsheet's ID in a string if isinstance(new_sheet, str): logger.info(f"Successfully created sheet {TITLE}!") # If we do not get a string back from the create_spreadsheet call diff --git a/useful_resources/sample_code/ngpvan_sample_printed_list.py b/useful_resources/sample_code/ngpvan_sample_printed_list.py index 1b6a608a7e..6621ec4e31 100644 --- a/useful_resources/sample_code/ngpvan_sample_printed_list.py +++ b/useful_resources/sample_code/ngpvan_sample_printed_list.py @@ -102,7 +102,7 @@ def to_pdf(saved_printed_merged): pdf = FPDF() pdf.set_font("Arial", size=14) - for index, row in saved_printed_merged.iterrows(): + for _index, row in saved_printed_merged.iterrows(): pdf.add_page() precinct_txt = f"Turf Name: {row[0]}" diff --git a/useful_resources/sample_code/opt_outs_everyaction.py b/useful_resources/sample_code/opt_outs_everyaction.py index 237810cbc4..7beb4cd279 100644 --- a/useful_resources/sample_code/opt_outs_everyaction.py +++ b/useful_resources/sample_code/opt_outs_everyaction.py @@ -1,7 +1,7 @@ +import datetime import json import os import time -from datetime import datetime import requests @@ -164,7 +164,7 @@ def main(): # Here we narrow the all_opt_outs table to only the rows that correspond # to this committee. - opt_outs = all_opt_outs.select_rows(lambda row: str(row.committeeid) == committeeid) + opt_outs = all_opt_outs.select_rows(lambda row: str(row.committeeid) == committeeid) # noqa: B023 logger.info(f"Found {opt_outs.num_rows} phones to opt out in {committee_name} committee...") @@ -172,7 +172,7 @@ def main(): if opt_outs.num_rows > 0: for opt_out in opt_outs: - applied_at = str(datetime.now()).split(".")[0] + applied_at = str(datetime.datetime.now(tz=datetime.timezone.utc)).split(".")[0] attempt_optout( every_action, opt_out,