diff --git a/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal b/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal index cec491e5f10..8975d7a8604 100755 --- a/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal +++ b/build/pyinstaller/macOS_package_assets/OpenBB Terminal/OpenBB Terminal @@ -15,7 +15,17 @@ echo " |___/ " BOOTUP_MESSAGE=" The boot up process might take a while. Please be patient... + +Have you checked out Community Routines yet? You can access them through the OpenBB Hub! +Get started in less than 3 minutes: https://www.youtube.com/watch?v=UFh_Ku0fdtY + " echo "$BOOTUP_MESSAGE" +# Add some messages we can print out +messages=("" "" "" "" "Did you know that you can search for stocks from a given country by running stocks/search --exchangecountry COUNTRY") +# Pick a random one +index=$((RANDOM % ${#messages[@]})) +echo ${messages[$index]} + "$SCRIPTDIR"/.OpenBB/OpenBBTerminal diff --git a/openbb_terminal/alternative/alt_controller.py b/openbb_terminal/alternative/alt_controller.py index cc4e7e1713d..4352e8193df 100644 --- a/openbb_terminal/alternative/alt_controller.py +++ b/openbb_terminal/alternative/alt_controller.py @@ -22,7 +22,7 @@ class AlternativeDataController(BaseController): """Alternative Controller class""" CHOICES_COMMANDS: List[str] = ["hn"] - CHOICES_MENUS = ["covid", "oss", "realestate"] + CHOICES_MENUS = ["covid", "oss", "realestate", "companieshouse"] PATH = "/alternative/" CHOICES_GENERATION = True @@ -41,6 +41,7 @@ class AlternativeDataController(BaseController): mt.add_menu("covid") mt.add_menu("oss") mt.add_menu("realestate") + mt.add_menu("companieshouse") mt.add_raw("\n") mt.add_cmd("hn") console.print(text=mt.menu_text, menu="Alternative") @@ -94,3 +95,12 @@ class AlternativeDataController(BaseController): ) self.queue = self.load_class(RealEstateController, self.queue) + + @log_start_end(log=logger) + def call_companieshouse(self, _): + """Process companieshouse command.""" + from openbb_terminal.alternative.companieshouse.companieshouse_controller import ( + CompaniesHouseController, + ) + + self.queue = self.load_class(CompaniesHouseController, self.queue) diff --git a/openbb_terminal/alternative/companieshouse/companieshouse_controller.py b/openbb_terminal/alternative/companieshouse/companieshouse_controller.py new file mode 100644 index 00000000000..40353ba5b00 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/companieshouse_controller.py @@ -0,0 +1,337 @@ +"""Companies House Controller.""" +__docformat__ = "numpy" + +import argparse +import logging +from typing import List, Optional + +from openbb_terminal.alternative.companieshouse import companieshouse_view +from openbb_terminal.core.session.current_user import get_current_user +from openbb_terminal.custom_prompt_toolkit import NestedCompleter +from openbb_terminal.decorators import check_api_key, log_start_end +from openbb_terminal.helper_funcs import ( + EXPORT_ONLY_RAW_DATA_ALLOWED, + check_positive, +) +from openbb_terminal.menu import session +from openbb_terminal.parent_classes import BaseController +from openbb_terminal.rich_config import MenuText, console + +logger = logging.getLogger(__name__) + + +class CompaniesHouseController(BaseController): + + """Companies House Controller class.""" + + CHOICES_COMMANDS = [ + "search", + "load", + "officers", + "signifcontrol", + "filings", + "filingdocument", + "charges", + ] + PATH = "/alternative/companieshouse/" + CHOICES_GENERATION = True + + def __init__(self, queue: Optional[List[str]] = None): + """Construct Data.""" + super().__init__(queue) + + self.companyNo = "" + self.companyName = "" + self.filingCategory = "" + self.filing_total_count = 0 + self.filing_end_index = 0 + self.filing_start_index = 0 + if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: + choices: dict = self.choices_default + self.completer = NestedCompleter.from_nested_dict(choices) + + def print_help(self): + """Print help""" + company_string = ( + f"{self.companyNo} ({self.companyName})" if self.companyNo else "" + ) + + mt = MenuText("alternative/companieshouse/") + mt.add_param("_company", company_string) + mt.add_raw("\n") + mt.add_cmd("search") + mt.add_cmd("load") + mt.add_cmd("officers") + mt.add_cmd("signifcontrol") + mt.add_cmd("filings") + mt.add_cmd("filingdocument") + mt.add_cmd("charges") + + console.print(text=mt.menu_text, menu="UK Companies House Data") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_search(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="search", + description="Select the company name to search for. [Source: UK Companies House]", + ) + parser.add_argument( + "-n", + "--name", + help="name", + type=str.upper, + required="-h" not in other_args, + dest="name", + metavar="name", + nargs="+", + ) + + parser.add_argument( + "-l", + "--limit", + help="Number of entries to return", + type=check_positive, + required=False, + dest="limit", + metavar="limit", + default=20, + ) + + if ( + other_args + and "-n" not in other_args[0] + and "--name" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-n") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser: + if ns_parser.name: + query = " ".join(ns_parser.name) + companieshouse_view.display_search( + query, ns_parser.limit, export=ns_parser.export + ) + else: + console.print("[red]No entries found for search string[/red]\n") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_load(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="load", + description="Select the company number to get detailed info on. [Source: UK Companies House]", + ) + parser.add_argument( + "-c", + "--companyNo", + help="companyNo", + type=str.upper, + required="-h" not in other_args, + dest="companyNo", + metavar="companyNo", + ) + + if ( + other_args + and "-c" not in other_args[0] + and "--companyNo" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-c") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if ns_parser and ns_parser.companyNo: + self.companyNo = ns_parser.companyNo + company = companieshouse_view.display_company_info( + ns_parser.companyNo, export=ns_parser.export + ) + if company.dataAvailable(): + self.companyName = company.name + self.filing_total_count = 0 + self.filing_end_index = 0 + console.print(company.name) + console.print(company.address) + console.print(company.lastAccounts) + else: + console.print( + f"[red]No data found for company number {ns_parser.companyNo}[/red]\n" + ) + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_officers(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="officers", + description="Select the company number to retrieve officers for. [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_officers( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_signifcontrol(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="signifcontrol", + description="Select the company number to retrieve persons with significant control of company. \ + [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_persons_with_significant_control( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_filings(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="filings", + description="Select the company number to retrieve filling history for. [Source: UK Companies House]", + ) + + parser.add_argument( + "-k", + "--category", + help="category", + type=str.lower, + required=False, + dest="category", + metavar="category", + choices=[ + "accounts", + "address", + "capital", + "incorporation", + "officers", + "resolution", + ], + ) + + parser.add_argument( + "-l", + "--limit", + help="Number of entries to return", + type=check_positive, + required=False, + dest="limit", + metavar="limit", + default=100, + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + category = ns_parser.category if ns_parser.category else "" + self.filingCategory = category + filing_data = companieshouse_view.display_filings( + self.companyNo, category, ns_parser.limit, export=ns_parser.export + ) + self.filing_total_count = filing_data.total_count + self.filing_end_index = filing_data.end_index + self.filing_start_index = filing_data.start_index + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_filingdocument(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="filingdocument", + description="Select the company number and transaction ID to retrieve filling history for. \ + [Source: UK Companies House]", + ) + + parser.add_argument( + "-t", + "--transactionID", + help="transactionID", + action="store", + required=("-h" not in other_args), + dest="transactionID", + metavar="transactionID", + ) + + if ( + other_args + and "-t" not in other_args[0] + and "--transactionID" not in other_args[0] + and "-h" not in other_args + ): + other_args.insert(0, "-t") + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.download_filing_document( + self.companyNo, + self.companyName, + ns_parser.transactionID, + export=ns_parser.export, + ) + else: + console.print("Must load a company prior to using this command") + + @log_start_end(log=logger) + @check_api_key(["API_COMPANIESHOUSE_KEY"]) + def call_charges(self, other_args: List[str]): + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="charges", + description="Select the company number to retrieve officers for. [Source: UK Companies House]", + ) + + ns_parser = self.parse_known_args_and_warn( + parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED + ) + + if self.companyNo: + if ns_parser: + companieshouse_view.display_charges( + self.companyNo, export=ns_parser.export + ) + else: + console.print("Must load a company prior to using this command") diff --git a/openbb_terminal/alternative/companieshouse/companieshouse_model.py b/openbb_terminal/alternative/companieshouse/companieshouse_model.py new file mode 100644 index 00000000000..462553956f8 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/companieshouse_model.py @@ -0,0 +1,481 @@ +""" UK Companies House Model """ +__docformat__ = "numpy" + +import logging + +import pandas as pd +import requests + +from openbb_terminal.alternative.companieshouse.company import Company +from openbb_terminal.alternative.companieshouse.company_doc import CompanyDocument +from openbb_terminal.alternative.companieshouse.filing_data import Filing_data +from openbb_terminal.core.session.constants import ( + TIMEOUT, +) +from openbb_terminal.core.session.current_user import get_current_user +from openbb_terminal.decorators import check_api_key, log_start_end + +logger = logging.getLogger(__name__) + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_search_results(searchStr: str, limit: int = 20) -> pd.DataFrame: + """All companies with searchStr in their name. + + Parameters + ---------- + searchStr : str + The search string + limit : int + number of rows to return + + Returns + ------- + pd.DataFrame + All comapanies with the search string in their name. + + Example + ------- + >>> from openbb_terminal.sdk import openbb + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + """ + + df = pd.DataFrame() + + if not searchStr: + return df + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + "https://api.company-information.service.gov.uk/search/companies?q=" + + searchStr + + f"&items_per_page={limit}", + auth=auth, + timeout=TIMEOUT, + ) + returned_data = r.json() + company_data = [] + for index, item in enumerate(returned_data["items"]): + company_data.append( + { + "Name": item["title"], + "Company Number": item["company_number"], + "Status": item["company_status"], + } + ) + + df = pd.DataFrame(company_data) + return df + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_company_info(company_number: str) -> Company: + """Gets company info by company number + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + + Returns + ------- + self.address: str + Company address. + self.name: str + Company name. + self.dataAvailable(): bool + True if data is available. + self.lastAccounts: str + Period start and end. + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> company_info = openbb.alt.companieshouse.get_company_info("02723534") + >>> name = company_info.name + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}", + auth=auth, + timeout=TIMEOUT, + ) + + last_accounts = {} + returned_data = r.json() + if returned_data.get("company_name"): + company_name = returned_data["company_name"] + if returned_data.get("accounts"): + last_accounts = returned_data["accounts"]["last_accounts"] + address = returned_data["registered_office_address"] + address_lines = [] + if address.get("address_line_1"): + address_lines.append(address.get("address_line_1")) + if address.get("address_line_2"): + address_lines.append(address.get("address_line_2")) + if address.get("locality"): + address_lines.append(address.get("locality")) + if address.get("region"): + address_lines.append(address.get("region")) + if address.get("postal_code"): + address_lines.append(address.get("postal_code")) + pretty_address = ( + ",".join(address_lines) + if len(address_lines) > 0 + else "No address data found" + ) + + if last_accounts: + pretty_accounts = "Period Start On : " + ( + last_accounts.get("period_start_on") or "" + ) + " - " + "Type : " + ( + last_accounts.get("type") or "" + ) + " - " + "Made Up To : " + ( + last_accounts.get("made_up_to") or "" + ) + " - " "Period End On : " + ( + last_accounts.get("period_end_on") or "" + ) + else: + pretty_accounts = "No accounting period data found" + + data = Company(company_name, pretty_address, pretty_accounts) + return data + else: + return Company() + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_officers(company_number: str) -> pd.DataFrame: + """Gets information on company officers + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + + Returns + ------- + pd.Dataframe + All officers for given company number + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> officer_info = openbb.alt.companieshouse.get_officers("02723534") + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}/officers?items_per_page=100", + auth=auth, + timeout=TIMEOUT, + ) + returned_data = r.json() + + officers = [] + if returned_data.get("items"): + for index, item in enumerate(returned_data["items"]): + officers.append( + { + "Officer Role": (item.get("officer_role") or " - "), + "Appointed On": (item.get("appointed_on") or " - "), + "Resigned On": (item.get("resigned_on") or " - "), + "Name": (item.get("name") or " - "), + } + ) + + df = pd.DataFrame(officers) + + return df + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_persons_with_significant_control(company_number: str) -> pd.DataFrame: + """Gets information on persons with significant control over the company + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + + Returns + ------- + pd.Dataframe + All persons with significant control over given company number + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> signif_control_info = openbb.alt.companieshouse.get_persons_with_significant_control("02723534") + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}/persons-with-significant-control?items_per_page=100", + auth=auth, + timeout=TIMEOUT, + ) + returned_data = r.json() + + controllers = [] + if returned_data.get("items"): + for index, item in enumerate(returned_data["items"]): + controllers.append( + { + "Kind": (item.get("kind") or " - "), + "Name": (item.get("name") or " - "), + "Natures of Control": (item.get("natures_of_control") or " - "), + "Notified On": (item.get("notified_on") or " - "), + } + ) + + df = pd.DataFrame(controllers) + + return pd.DataFrame(df) + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_filings(company_number: str, category: str = "", start_index=0) -> Filing_data: + """Gets information on filings for given company, e.g. accounts, etc + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + + Returns + ------- + pd.Dataframe + All information on all filings for company + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> signif_control_info = openbb.alt.companieshouse.get_filings("02723534") + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + url = ( + f"https://api.company-information.service.gov.uk/company/{company_number}/filing-history" + + f"?start_index={start_index}&items_per_page=100" + ) + if category: + url = ( + f"https://api.company-information.service.gov.uk/company/{company_number}/filing-history" + + f"?category={category}&start_index={start_index}&items_per_page=100" + ) + + r = requests.get( + url, + auth=auth, + timeout=TIMEOUT, + ) + returned_data = r.json() + + filings = [] + for index, item in enumerate(returned_data["items"]): + filings.append( + { + "Category": (item.get("category") or " - "), + "Date": (item.get("date") or " - "), + "Description": (item.get("description") or " - "), + "Type": (item.get("type") or " - "), + "Pages": (item.get("pages") or " - "), + "Transaction ID": (item.get("transaction_id") or " - "), + "Download": "https://find-and-update.company-information.service.gov.uk/company/" + f"{company_number}" + "/filing-history/" + f"{item.get('transaction_id')}" + "/document?format=pdf&download=0", + } + ) + start_index = int(returned_data.get("start_index")) + total_count = int(returned_data.get("total_count")) + end_index = start_index + 100 + if end_index > total_count: + end_index = total_count + data = Filing_data(pd.DataFrame(filings), start_index, end_index, total_count) + + return data + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_filing_document(company_number: str, transactionID: str) -> CompanyDocument: + """Download given filing document pdf + + Parameters + ---------- + company_number : str + The company number. Use get_search_results() to lookup company numbers. + transactionID : str + The filing transaction id. Use get_filings() to get id for each document + + Returns + ------- + self.category: str + document category, e.g.confirmation-statement-with-updates, accounts-with-accounts-type-dormant, etc. + self.date: str + date document filed. + self.description: str + description of document files. + self.paper_filed: str + True if documents filed in paper format. + self.pages: str + Number of pages in document. + self.transaction_id: str + Document transaction id. + self.content: bytes + contents of the document. + + Example + ------- + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> company_doc_info = openbb.alt.companieshouse.get_filing_document("02723534","MzM1NzQ0NzI5NWFkaXF6a2N4") + """ + + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}/filing-history/{transactionID}", + auth=auth, + timeout=TIMEOUT, + ) + + returned_data = r.json() + + category = date = description = paper_filed = pages = transaction_id = "" + content = b"" + if returned_data.get("links") and returned_data.get("links").get( + "document_metadata" + ): + url = returned_data.get("links").get("document_metadata") + "/content" + response = requests.get( + url, auth=auth, headers={"Accept": "application/pdf"}, timeout=TIMEOUT + ) + + if returned_data.get("category"): + category = returned_data["category"] + if returned_data.get("date"): + date = returned_data["date"] + if returned_data.get("description"): + description = returned_data["description"] + if returned_data.get("paper_filed"): + paper_filed = returned_data["paper_filed"] + if returned_data.get("pages"): + pages = returned_data["pages"] + if returned_data.get("transaction_id"): + transaction_id = returned_data["transaction_id"] + + content = bytes(response.content) + + return CompanyDocument( + category, date, description, paper_filed, pages, transaction_id, content + ) + else: + return CompanyDocument( + category, date, description, paper_filed, pages, transaction_id, content + ) + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_charges(company_number: str) -> pd.DataFrame: + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}/charges", + auth=auth, + timeout=TIMEOUT, + ) + + returned_data = r.json() + + charges = pd.DataFrame() + for index, item in enumerate(returned_data["items"]): + url = item.get("links").get("self") + id = url[url.rfind("/") + 1 :] + charges = pd.concat( + [charges, get_charge(company_number, id)], ignore_index=True + ) + + return charges + + +@log_start_end(log=logger) +@check_api_key(["API_COMPANIESHOUSE_KEY"]) +def get_charge(company_number: str, charge_id: str) -> pd.DataFrame: + auth = requests.auth.HTTPBasicAuth( + get_current_user().credentials.API_COMPANIESHOUSE_KEY, "" + ) + r = requests.get( + f"https://api.company-information.service.gov.uk/company/{company_number}/charges/{charge_id}", + auth=auth, + timeout=TIMEOUT, + ) + + returned_data = r.json() + + charge = {} + if returned_data.get("acquired_on"): + charge.update({"acquired_on": returned_data.get("acquired_on")}) + if returned_data.get("assests_ceased_released"): + charge.update( + {"assests_ceased_released": returned_data.get("assests_ceased_released")} + ) + + if returned_data.get("charge_number"): + charge.update({"charge_number": returned_data.get("charge_number")}) + + if returned_data.get("covering_instrument_date"): + charge.update( + {"covering_instrument_date": returned_data.get("covering_instrument_date")} + ) + + if returned_data.get("created_on"): + charge.update({"created_on": returned_data.get("created_on")}) + + if returned_data.get("delivered_on"): + charge.update({"delivered_on": returned_data.get("delivered_on")}) + + if returned_data.get("id"): + charge.update({"id": returned_data.get("id")}) + + if returned_data.get("status"): + charge.update({"status": returned_data.get("status")}) + + if returned_data.get("particulars"): + part = returned_data.get("particulars") + + if part.get("description"): + charge.update({"description": part.get("description")}) + if part.get("floating_charge_covers_all"): + charge.update( + {"floating_charge_covers_all": part.get("floating_charge_covers_all")} + ) + if part.get("type"): + charge.update({"type": part.get("type")}) + + if returned_data.get("persons_entitled"): + for entitled in returned_data.get("persons_entitled"): + charge.update({"persons_entitled_name": entitled.get("name")}) + + return pd.DataFrame([charge]) diff --git a/openbb_terminal/alternative/companieshouse/companieshouse_view.py b/openbb_terminal/alternative/companieshouse/companieshouse_view.py new file mode 100644 index 00000000000..d7e88ad69a6 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/companieshouse_view.py @@ -0,0 +1,253 @@ +""" UK Companies House View """ +__docformat__ = "numpy" + +import logging +import os + +import pandas as pd + +from openbb_terminal.alternative.companieshouse import companieshouse_model +from openbb_terminal.alternative.companieshouse.company import Company +from openbb_terminal.alternative.companieshouse.filing_data import Filing_data +from openbb_terminal.core.session.current_user import get_current_user +from openbb_terminal.decorators import log_start_end +from openbb_terminal.helper_funcs import export_data, print_rich_table +from openbb_terminal.rich_config import console + +logger = logging.getLogger(__name__) + + +@log_start_end(log=logger) +def display_search(search_str: str, limit: int, export: str = "") -> None: + """Display company search results. + + Parameters + ---------- + search_str : str + Company name to search for + + limit : int + number of rows to return + + """ + results = companieshouse_model.get_search_results(search_str, limit) + + if results.empty or len(results) == 0: + console.print( + "[red]" + "No data loaded.\n" + "Try different search string." + "[/red]\n" + ) + return + + console.print(f"Retrieved {len(results)} records") + print_rich_table( + results, + show_index=False, + title=f"[bold]{search_str}[/bold]", + export=bool(export), + columns_keep_types=["Company Number"], + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "results", + results, + ) + + +@log_start_end(log=logger) +def display_company_info(company_number: str, export: str = "") -> Company: + """Display company search results. + + Parameters + ---------- + company_number : str + company_number to retrieve info for + + + """ + return companieshouse_model.get_company_info(company_number) + + +@log_start_end(log=logger) +def display_officers(company_number: str, export: str = "") -> None: + """Display company officers results. + + Parameters + ---------- + company_number : str + company_number to retrieve officers for + + + """ + results = companieshouse_model.get_officers(company_number) + + if len(results) > 0: + console.print(f"Retrieved {len(results)} records") + print_rich_table( + results, + show_index=False, + title=f"[bold]{company_number}[/bold]", + export=bool(export), + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "results", + results, + ) + else: + console.print("[red]No Data Found[/red]") + + +@log_start_end(log=logger) +def display_persons_with_significant_control( + company_number: str, export: str = "" +) -> None: + """Display company officers results. + + Parameters + ---------- + company_number : str + company_number to retrieve officers for + + + """ + results = companieshouse_model.get_persons_with_significant_control(company_number) + + if len(results) > 0: + console.print(f"Retrieved {len(results)} records") + print_rich_table( + results, + show_index=False, + title=f"[bold]{company_number}[/bold]", + export=bool(export), + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "results", + results, + ) + else: + console.print("[red]No Data Found[/red]") + + +@log_start_end(log=logger) +def display_filings( + company_number: str, + category: str = "", + limit: int = 100, + export: str = "", +) -> Filing_data: + """Display company's filing history. + + Parameters + ---------- + company_number : str + company_number to retrieve filing history for + + """ + start_index = 0 + results = companieshouse_model.get_filings(company_number, category, start_index) + + start = int(results.start_index) + + data = results + total = int(results.total_count) if int(results.total_count) < limit else limit + + while start < total - 100: + results = companieshouse_model.get_filings( + company_number, start_index=start + 100 + ) + data.filings = pd.concat([data.filings, results.filings], ignore_index=True) + start = start + 100 + + data.filings = data.filings.head(limit) + console.print(f"Retrieved {len(data.filings)} filings") + + print_rich_table( + data.filings, + show_index=False, + title=f"[bold]{company_number}[/bold]", + export=bool(export), + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "results", + data.filings, + ) + + return results + + +def download_filing_document( + company_number: str, company_name: str, transactionID: str, export: str = "" +) -> None: + """Download company's filing document. + + Parameters + ---------- + company_number : str + company_number to retrieve filing history for + + company_name : str + company_name to retrieve filing document for, this is used to name the downloaded file for easy access + + transactionID : str + transaction id for filing + + >>> companies = openbb.alt.companieshouse.get_search_results("AstraZeneca") + >>> openbb.alt.companieshouse.get_filing_document("02723534","AstraZeneca","MzM1NzQ0NzI5NWFkaXF6a2N4") + """ + + results = companieshouse_model.get_filing_document(company_number, transactionID) + + if results.dataAvailable(): + filename = ( + company_name.replace(" ", "_") + + "_" + + results.category + + "_" + + transactionID + + ".pdf" + ) + with open( + f"{get_current_user().preferences.USER_COMPANIES_HOUSE_DIRECTORY}/{filename}", + "wb", + ) as f: + f.write(results.content) + console.print( + f"File [green] {filename}[/green] downloaded to \ + {get_current_user().preferences.USER_COMPANIES_HOUSE_DIRECTORY}" + ) + else: + console.print("[red]" + "Document not found" + "[/red]\n") + + +@log_start_end(log=logger) +def display_charges(company_number: str, export: str = "") -> None: + results = companieshouse_model.get_charges(company_number) + + if len(results) > 0: + print_rich_table( + results, + show_index=False, + title=f"[bold]{company_number}[/bold]", + export=bool(export), + ) + + export_data( + export, + os.path.dirname(os.path.abspath(__file__)), + "results", + results, + ) + else: + console.print("[red]" + "No Charges found" + "[/red]\n") + + return results diff --git a/openbb_terminal/alternative/companieshouse/company.py b/openbb_terminal/alternative/companieshouse/company.py new file mode 100644 index 00000000000..c4e0ae1f126 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/company.py @@ -0,0 +1,14 @@ +class Company: + """Holder class for company information""" + + name = "" + address = "" + lastAccounts = "" + + def __init__(self, name="", address: str = "", lastAccounts: str = ""): + self.name = name + self.address = address + self.lastAccounts = lastAccounts + + def dataAvailable(self) -> bool: + return len(self.name) > 0 diff --git a/openbb_terminal/alternative/companieshouse/company_doc.py b/openbb_terminal/alternative/companieshouse/company_doc.py new file mode 100644 index 00000000000..2b473989288 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/company_doc.py @@ -0,0 +1,31 @@ +class CompanyDocument: + """Holder class for company document information""" + + category = "" + date = "" + description = "" + paper_filed = "" + pages = "" + transaction_id = "" + content = b"" + + def __init__( + self, + category="", + date: str = "", + description: str = "", + paper_filed: str = "", + pages: str = "", + transaction_id: str = "", + content=b"", + ): + self.category = category + self.date = date + self.description = description + self.paper_filed = paper_filed + self.pages = pages + self.transaction_id = transaction_id + self.content = content + + def dataAvailable(self) -> bool: + return len(self.content) > 0 diff --git a/openbb_terminal/alternative/companieshouse/filing_data.py b/openbb_terminal/alternative/companieshouse/filing_data.py new file mode 100644 index 00000000000..d6b7da7f893 --- /dev/null +++ b/openbb_terminal/alternative/companieshouse/filing_data.py @@ -0,0 +1,19 @@ +import pandas as pd + + +class Filing_data: + """Holder class for company filings information""" + + filings = pd.DataFrame() + total_count = 0 + start_index = 0 + end_index = 0 + + def __init__(self, filings, start_index, end_index, total_count): + self.filings = filings + self.start_index = start_index + self.end_index = end_index + self.total_count = total_count + + def dataAvailable(self) -> bool: + return len(self.filings) > 0 diff --git a/openbb_terminal/core/config/paths_helper.py b/openbb_terminal/core/config/paths_helper.py index 3f5dad67a6c..0a5a08c18e5 100644 --- a/openbb_terminal/core/config/paths_helper.py +++ b/openbb_terminal/core/config/paths_helper.py @@ -42,6 +42,7 @@ dirs_list = [ current_user.preferences.USER_DATA_DIRECTORY / "styles", current_user.preferences.USER_DATA_DIRECTORY / "reports", current_user.preferences.USER_DATA_DIRECTORY / "reports" / "custom reports", + current_user.preferences.USER_DATA_DIRECTORY / "companies_house", current_user.preferences.USER_CUSTOM_IMPORTS_DIRECTORY, current_user.preferences.USER_CUSTOM_IMPORTS_DIRECTORY / "econometrics", current_user.preferences.USER_CUSTOM_IMPORTS_DIRECTORY / "stocks", diff --git a/openbb_terminal/core/models/preferences_model.py b/openbb_terminal/core/models/preferences_model.py index e92e855eb35..86c43bd954f 100644 --- a/openbb_terminal/core/models/preferences_model.py +++ b/openbb_terminal/core/models/preferences_model.py @@ -85,6 +85,7 @@ class PreferencesModel(BaseModel): USER_FORECAST_MODELS_DIRECTORY = USER_DATA_DIRECTORY / "exports" / "forecast_models" USER_FORECAST_WHISPER_DIRECTORY = USER_DATA_DIRECTORY / "exports" / "whisper" USER_STYLES_DIRECTORY = USER_DATA_DIRECTORY / "styles" + USER_COMPANIES_HOUSE_DIRECTORY = USER_DATA_DIRECTORY / "companies_house" def __repr__(self) -> str: # pylint: disable=useless-super-delegation return super().__repr__() diff --git a/openbb_terminal/core/sdk/controllers/alt_sdk_controller.py b/openbb_terminal/core/sdk/controllers/alt_sdk_controller.py index 4fa0bb70289..478cf6fb7e6 100644 --- a/openbb_terminal/core/sdk/controllers/alt_sdk_controller.py +++ b/openbb_terminal/core/sdk/controllers/alt_sdk_controller.py @@ -11,6 +11,7 @@ class AltController(model.AltRoot): `covid`: Covid Module `oss`: Oss Module `realestate`: Realestate Module + `companieshouse`: CompaniesHouse Module Attributes: `hn`: Get top stories from HackerNews.\n @@ -66,3 +67,19 @@ class AltController(model.AltRoot): """ return model.AltRealestate() + + @property + def companieshouse(self): + """Alternative CompaniesHouse Submodule + + Attributes: + `get_search_results`: Search for companies by name\n + `get_company_info`: Get details of company by registration number\n + `get_officers`: Get company officers\n + `get_persons_with_significant_control`: Get people/organisations with significant control over company\n + `get_filings`: Get company filing details\n + `get_filing_document`: Get company filed document\n + `download_filing_document`: Download company filed document\n + """ + + return model.AltCompaniesHouse() diff --git a/openbb_terminal/core/sdk/models/alt_sdk_model.py b/openbb_terminal/core/sdk/models/alt_sdk_model.py index cc77efb4f5e..1aa4781dc4d 100644 --- a/openbb_terminal/core/sdk/models/alt_sdk_model.py +++ b/openbb_terminal/core/sdk/models/alt_sdk_model.py @@ -103,3 +103,40 @@ class AltRealestate(Category): self.get_towns_sold_prices = ( lib.alt_realestate_landRegistry_model.get_towns_sold_prices ) + + +class AltCompaniesHouse(Category): + """CompaniesHouse Module. + + Attributes: + `get_search_results`: Search for company by name\n + `get_company_info`: Get details of company by registration number\n + `get_officers`: Get company officers\n + `get_persons_with_significant_control`: Get people/organisations with significant control over company\n + `get_charges`: Get company charges\n + `get_filings`: Get company filing details\n + `get_filing_document`: Get company filed document\n + """ + + _location_path = "alt.companieshouse" + + def __init__(self): + super().__init__() + self.get_search_results = ( + lib.alt_companieshouse_companieshouse_model.get_search_results + ) + self.get_company_info = ( + lib.alt_companieshouse_companieshouse_model.get_company_info + ) + self.get_officers = lib.alt_companieshouse_companieshouse_model.get_officers + self.get_persons_with_significant_control = ( + lib.alt_companieshouse_companieshouse_model.get_persons_with_significant_control + ) + self.get_charges = lib.alt_companieshouse_companieshouse_model.get_charges + self.get_filings = lib.alt_companieshouse_companieshouse_model.get_filings + self.get_filing_document = ( + lib.alt_companieshouse_companieshouse_model.get_filing_document + ) + self.download_filing_document = ( + lib.alt_companieshouse_companieshouse_view.download_filing_document + ) diff --git a/openbb_terminal/core/sdk/sdk_init.py b/openbb_terminal/core/sdk/sdk_init.py index e075c597bb2..2396d8ceb3c 100644 --- a/openbb_terminal/core/sdk/sdk_init.py +++ b/openbb_terminal/core/sdk/sdk_init.py @@ -2,6 +2,8 @@ # noqa: F401 # Alternative +import openbb_terminal.alternative.companieshouse.companieshouse_model as alt_companieshouse_companieshouse_model +import openbb_terminal.alternative.companieshouse.companieshouse_view as alt_companieshouse_companieshouse_view import openbb_terminal.alternative.hackernews_model as alt_hackernews_model import openbb_terminal.alternative.hackernews_view as alt_hackernews_view import openbb_terminal.alternative.oss.github_model as alt_oss_github_model diff --git a/openbb_terminal/core/sdk/trail_map.csv b/openbb_terminal/core/sdk/trail_map.csv index ebb70a1affa..02a7223d87c 100644 --- a/openbb_terminal/core/sdk/trail_map.csv +++ b/openbb_terminal/core/sdk/trail_map.csv @@ -16,6 +16,14 @@ alt.oss.top,alt_oss_github_model.get_top_repos,alt_oss_github_view.display_top_r alt.realestate.get_estate_sales,alt_realestate_landRegistry_model.get_estate_sales, alt.realestate.get_region_stats,alt_realestate_landRegistry_model.get_region_stats, alt.realestate.get_towns_sold_prices,alt_realestate_landRegistry_model.get_towns_sold_prices, +alt.companieshouse.get_search_results,alt_companieshouse_companieshouse_model.get_search_results, +alt.companieshouse.get_company_info,alt_companieshouse_companieshouse_model.get_company_info, +alt.companieshouse.get_officers,alt_companieshouse_companieshouse_model.get_officers, +alt.companieshouse.get_persons_with_significant_control,alt_companieshouse_companieshouse_model.get_persons_with_significant_control, +alt.companieshouse.get_filings,alt_companieshouse_companieshouse_model.get_filings, +alt.companieshouse.get_filing_document,alt_companieshouse_companieshouse_model.get_filing_document, +alt.companieshouse.download_filing_document,alt_companieshouse_companieshouse_view.download_filing_document, +alt.companieshouse.get_charges,alt_companieshouse_companieshouse_view.display_charges crypto.candle,crypto_helpers.plot_candles, crypto.chart,crypto_helpers.plot_chart, crypto.dd.active,crypto_dd_glassnode_model.get_active_addresses,crypto_dd_glassnode_view.display_active_addresses diff --git a/openbb_terminal/keys_controller.py b/openbb_terminal/keys_controller.py index 558faf4c014..b9d81023028 100644 --- a/openbb_terminal/keys_controller.py +++ b/openbb_terminal/keys_controller.py @@ -1281,6 +1281,36 @@ class KeysController(BaseController): # pylint: disable=too-many-public-methods key=ns_parser.key, persist=True, show_output=True ) + @log_start_end(log=logger) + def call_companieshouse(self, other_args: List[str]): + """Process companies house command""" + parser = argparse.ArgumentParser( + add_help=False, + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + prog="companieshouse", + description="Set Companies House API key.", + ) + parser.add_argument( + "-k", + "--key", + type=str, + dest="key", + help="key", + ) + if not other_args: + console.print( + "For your API Key, visit: https://developer.company-information.service.gov.uk/overview" + ) + return + + if other_args and "-" not in other_args[0][0]: + other_args.insert(0, "-k") + ns_parser = self.parse_simple_args(parser, other_args) + if ns_parser: + self.status_dict["companieshouse"] = keys_model.set_companieshouse_key( + key=ns_parser.key, persist=True, show_output=True + ) + @log_start_end(log=logger) def call_nixtla(self, other_args: List[str]): """Process nixtla command""" diff --git a/openbb_terminal/keys_model.py b/openbb_terminal/keys_model.py index 7e62daa9b99..45af3419a00 100644 --- a/openbb_terminal/keys_model.py +++ b/openbb_terminal/keys_model.py @@ -83,6 +83,7 @@ API_DICT: Dict = { "tokenterminal": "TOKEN_TERMINAL", "stocksera": "STOCKSERA", "dappradar": "DAPPRADAR", + "companieshouse": "COMPANIES_HOUSE", "openai": "OPENAI", "nixtla": "NIXTLA", } @@ -2750,6 +2751,82 @@ def check_dappradar_key(show_output: bool = False) -> str: return str(status) +def set_companieshouse_key( + key: str, + persist: bool = False, + show_output: bool = False, +) -> str: + """Set Companies House key + + Parameters + ---------- + key: str + API ID + + persist: bool, optional + If False, api key change will be contained to where it was changed. For example, a Jupyter notebook session. + If True, api key change will be global, i.e. it will affect terminal environment variables. + By default, False. + show_output: bool, optional + Display status string or not. By default, False. + + Returns + ------- + str + Status of key set + + Examples + -------- + >>> from openbb_terminal.sdk import openbb + >>> openbb.keys.companieshouse( + api_id="example_id", + ) + """ + + handle_credential("API_COMPANIESHOUSE_KEY", key, persist) + return check_companieshouse_key(show_output) + + +def check_companieshouse_key(show_output: bool = False) -> str: + """Check Companies House key + + Parameters + ---------- + show_output: bool + Display status string or not. By default, False. + + Returns + ------- + str + Status of key set + """ + + current_user = get_current_user() + + if current_user.credentials.API_COMPANIESHOUSE_KEY == "REPLACE_ME": + logger.info("Companies House key not defined") + status = KeyStatus.NOT_DEFINED + else: + r = request( + "https://api.company-information.service.gov.uk/company/00000118", + auth=(f"{current_user.credentials.API_COMPANIESHOUSE_KEY}", ""), + ) + if r.status_code in [403, 401, 429]: + logger.warning("Companies House key defined, test failed") + status = KeyStatus.DEFINED_TEST_FAILED + elif r.status_code == 200: + logger.info("Companies House key defined, test passed") + status = KeyStatus.DEFINED_TEST_PASSED + else: + logger.warning("Companies House key defined, test inconclusive") + status = KeyStatus.DEFINED_TEST_INCONCLUSIVE + + if show_output: + console.print(status.colorize()) + + return str(status) + + # Set OpenAI key def set_openai_key(key: str, persist: bool = False, show_output: bool = False) -> str: """Set OpenAI key diff --git a/openbb_terminal/miscellaneous/i18n/en.yml b/openbb_terminal/miscellaneous/i18n/en.yml index 8c229af0b87..9197ef8f0d0 100644 --- a/openbb_terminal/miscellaneous/i18n/en.yml +++ b/openbb_terminal/miscellaneous/i18n/en.yml @@ -921,9 +921,10 @@ en: funds/exclusion: exclusion policy funds/_country_ms: Current Country MorningStar alternative/hn: Hacker News most popular stories - alternative/covid: COVID menu cases, deaths, rates - alternative/oss: Open Source menu star history, repos information - alternative/realestate: Real Estate menu sold prices, HPIs + alternative/covid: COVID menu, cases, deaths, rates + alternative/oss: Open Source menu, star history, repos information + alternative/realestate: Real Estate menu, sold prices, HPIs + alternative/companieshouse: Companies House menu, UK company information alternative/covid/slopes: get countries with highest slope in cases alternative/covid/country: select country for data alternative/covid/_country: Country @@ -943,6 +944,14 @@ en: alternative/realestate/_enddate: End Date alternative/realestate/regionstats: retrieve UK sold house price stats by region alternative/realestate/_region: Region + alternative/companieshouse/_company: Current Company + alternative/companieshouse/search: search for companies by name + alternative/companieshouse/load: retrieve basic company details by company registration number + alternative/companieshouse/officers: retrieve company officies + alternative/companieshouse/signifcontrol: retrieve those with significant control over the company + alternative/companieshouse/filings: retrieve list of documents filed with Companies House (Default 100) + alternative/companieshouse/filingdocument: download filed document + alternative/companieshouse/charges: registered charges against the company econometrics/_data_loc: Looking for data in econometrics/load: load a dataset (also works with StatsModels datasets) econometrics/export: export a processed dataset diff --git a/openbb_terminal/miscellaneous/models/hub_credentials.json b/openbb_terminal/miscellaneous/models/hub_credentials.json index a3ca194184a..10bdc74c068 100644 --- a/openbb_terminal/miscellaneous/models/hub_credentials.json +++ b/openbb_terminal/miscellaneous/models/hub_credentials.json @@ -35,6 +35,7 @@ "API_TWITTER_KEY": "", "API_TWITTER_SECRET_KEY": "", "API_TWITTER_BEARER_TOKEN": "", + "API_COMPANIESHOUSE_KEY": "", "API_DAPPRADAR_KEY": "", "API_KEY_NIXTLA": "" } diff --git a/openbb_terminal/sdk.py b/openbb_terminal/sdk.py index 6fb8c4260b5..7a0f8d24c2f 100644 --- a/openbb_terminal/sdk.py +++ b/openbb_terminal/sdk.py @@ -95,6 +95,7 @@ class OpenBBSDK: `covid`: Covid Module `oss`: Oss Module `realestate`: Realestate Module + `companieshouse`: CompaniesHouse Module Attributes: `hn`: Get top stories from HackerNews.\n diff --git a/poetry.lock b/poetry.lock index 4be97be82fb..e7fca534320 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "absl-py" @@ -7226,24 +7226,24 @@ files = [ [[package]] name = "pywry" -version = "0.5.13" +version = "0.5.14" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "pywry-0.5.13-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:fc2d39cbaa7479ba2170192930288d94cdf17a9e3f9cf44b3884903f264b70fa"}, - {file = "pywry-0.5.13-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:de9e75a2b24433c5a12adcf0ba4bf6e29c50edcaac3bae09c0073ba3484237a9"}, - {file = "pywry-0.5.13-cp310-none-win_amd64.whl", hash = "sha256:c284428dceb64063026541b37d7786136ce4b281d0cd7aa716ced1e64a276c13"}, - {file = "pywry-0.5.13-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0d1f94bcfc9713c6194667f14f472be34640e9f3e8013faa02aea276d4571c8a"}, - {file = "pywry-0.5.13-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a3627d92bed1a8e02bf87b18ef0a12868f8468a18b0b74925a73c507b1b8964f"}, - {file = "pywry-0.5.13-cp311-none-win_amd64.whl", hash = "sha256:7d8f884e853466fb1ee8003aaf0ea1c643721adb2d0c75300ebc0f314008420b"}, - {file = "pywry-0.5.13-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ba97dc7406086748a16e4f21efc73c006d4f02f71941fcbbd11e17946ab878cb"}, - {file = "pywry-0.5.13-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:c142839551c5e468cae3171dee7b230ba753cb38027a03079f3fa283671e190a"}, - {file = "pywry-0.5.13-cp38-none-win_amd64.whl", hash = "sha256:646e41c18d3a0f762d2b59e14281fca223d7fe1f0b2a882ecf054840ee28d10d"}, - {file = "pywry-0.5.13-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9e950d076f1a2d7980753576c65e6540ea05f6b5b0a29b734035aaae64027dea"}, - {file = "pywry-0.5.13-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:d6654cd7d45d66f359872d4e9dd2e70372daf96ea2458706eeafda198471a45e"}, - {file = "pywry-0.5.13-cp39-none-win_amd64.whl", hash = "sha256:03b5fa018f1e5be8d42aff2f969b4cc068d13c894521341e8e59ec33af794324"}, - {file = "pywry-0.5.13.tar.gz", hash = "sha256:b5344ddbe63b72ed22c5a3f7f6c4a59a5bd27f250fbca7af979f3972d3a1855c"}, + {file = "pywry-0.5.14-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bf30e8e6e59863614fe06144e90c3c95c43256f944222d070be07e71c0303ad6"}, + {file = "pywry-0.5.14-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:46fc00c02dfbbd3d81aa0f43cb9c5111c06e748a850cc795dfcd800a3b78958f"}, + {file = "pywry-0.5.14-cp310-none-win_amd64.whl", hash = "sha256:ecd8e4c4d95f5fb114d0baa6572d2392ae0cc866f200c5fccd6c4bfa3b1a29cc"}, + {file = "pywry-0.5.14-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:db5a298d57b80cc33c6a03f572b80f14d0018b2c4204e2137072ee9dfb23b1c1"}, + {file = "pywry-0.5.14-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:335e97b0f242bfa6037ec7fdc90b3625611be0ad40496a8cf152dae0c6ae6605"}, + {file = "pywry-0.5.14-cp311-none-win_amd64.whl", hash = "sha256:66cba8d3144bcd118808d09c33044e27544561f5c9a7b397edb9c3b3fcf6d3d9"}, + {file = "pywry-0.5.14-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:713fe32afa2b61595057344b6c0b47772080dc05ee9b2f210448ba8cb2b8ac76"}, + {file = "pywry-0.5.14-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:d0479f3a52f27658eedb37128e230c3ea620eb113d1371326ae235006a29f3e0"}, + {file = "pywry-0.5.14-cp38-none-win_amd64.whl", hash = "sha256:3f42fd9e1fe6ae40be6f13195719e648fbbebda29fe9ba846c59797f71839add"}, + {file = "pywry-0.5.14-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b2690978499d63dfac3fe712ed3e3752866d7eb40ed7dcb21590b0ff109cecb7"}, + {file = "pywry-0.5.14-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2bcba7d64b9cdf2f1d65f4d468f87b00629157d233de251805b0816a43ba738b"}, + {file = "pywry-0.5.14-cp39-none-win_amd64.whl", hash = "sha256:c5b949f5d16a43aa2cc703159caa6de45b91e6008a4fa608d99909b7c89f45c3"}, + {file = "pywry-0.5.14.tar.gz", hash = "sha256:a2a03b18f0847366a4347d30429afd8a50c95cc35713371a3d6bbed077db9983"}, ] [package.dependencies] @@ -7843,8 +7843,7 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, @@ -8202,7 +8201,7 @@ files = [ [package.dependencies] packaging = ">=20.0" setuptools = [ - {version = "*"}, + {version = "*", optional = true, markers = "extra != \"toml\""}, {version = ">=42", optional = true, markers = "extra == \"toml\""}, ] tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} @@ -8535,7 +8534,7 @@ files = [ ] [package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} typing-extensions = ">=4.2.0" [package.extras] @@ -8677,52 +8676,6 @@ build = ["cython (>=0.29.26)"] develop = ["cython (>=0.29.26)"] docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] -[[package]] -name = "statsmodels" -version = "0.13.3" -description = "Statistical computations and models for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "statsmodels-0.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b71bb64c6d4087dd6192eadfad390fbeb4074f676ef34c7e56579cead8c478e7"}, - {file = "statsmodels-0.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:658b634c273c2f287a0086e56a5d6b95ec3ddac991cbb020b34f731e932de0bd"}, - {file = "statsmodels-0.13.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab9f63f432889b179967ab645aea7480e28731823a3b99850d7f7a561b624f93"}, - {file = "statsmodels-0.13.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f432fb7f54ce5edccc83aa36566653cd04ee35bbbefdf0a2b7bd9c97c5da443"}, - {file = "statsmodels-0.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:4cd64076c3ad366b10fd4e6f8ca6aeb1e398ec5480bddb65fba8889dd9eb550d"}, - {file = "statsmodels-0.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:33f9caff2dbdfef22505678407d2f549b32a4a2729eb8675b60eb2932fc0e883"}, - {file = "statsmodels-0.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:393f6a7ec85f65be9ac1a13be152dd14c65084436c48bcdf94cb21ef0b6cb79c"}, - {file = "statsmodels-0.13.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12b56d13d9a2af7a1aadc3fe9f3d3c18a5727a651323d94e7c2047177adfb9ce"}, - {file = "statsmodels-0.13.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a61e0652f62b01981d8e857aa77550b42cf316c9d8e569b559869c248e3de834"}, - {file = "statsmodels-0.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:5368bccd471bb8cef0a8957ba5f2a3e5b5ecc433b0783d9f602039df45c780d3"}, - {file = "statsmodels-0.13.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:1ecfb191958de187ba44b93316f4953b8b6588b5f68dcab218f76498a862dd7c"}, - {file = "statsmodels-0.13.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea2b481b15e9e501904a1c36efc5f9a202f87529e600a99c364fd7e4598ae88"}, - {file = "statsmodels-0.13.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d270a11aac6720a8024e1136ab44036d0878f62995617bb5b9fc5c77ea3d3b8"}, - {file = "statsmodels-0.13.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2185ed356823cd1c258c09b790f0c21d2fd49321e82c79f8f6dc546f1c671d7a"}, - {file = "statsmodels-0.13.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9da39a36d114abcdcf8ebd351ed69229e23cb12b8a607996cb6511fa88e78b4d"}, - {file = "statsmodels-0.13.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3b3a9942d0b462af4c68c3895095d304869cbec9d97f3c268f19a6ba7ba294dc"}, - {file = "statsmodels-0.13.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fff0316420bc4f6fbd80dd77eb74f3834fcd0e4ca98ba9611b8a6d41ebbb979"}, - {file = "statsmodels-0.13.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:352041bc04eaf90232e54a86861a460365ef45f34f58529578487e6f640dadf3"}, - {file = "statsmodels-0.13.3-cp38-cp38-win_amd64.whl", hash = "sha256:61a0f39848ebacf5560e1539ca0037b8fc25cc9d1d7444bbef5bdc0a3c56087b"}, - {file = "statsmodels-0.13.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:78cd12b0ee543fa955d2bace18518fc7d2b57f13c65929b54445bf3e54955b08"}, - {file = "statsmodels-0.13.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:afccb80e3ddc969bfb5285f846ac2622861ffe192423087214d60e4c6e40e384"}, - {file = "statsmodels-0.13.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3609824e1ced44722bd905564d8ce94df29d24e32a6dd67cc9255932aedcd7b"}, - {file = "statsmodels-0.13.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81f8e71963a7bd169338fbb1472e34ec85ae4447414ac37bdae5cf6d1ac223bb"}, - {file = "statsmodels-0.13.3-cp39-cp39-win_amd64.whl", hash = "sha256:000c7a1ce6780834f5fbb63f9ae07a00863a00f602c7c470c942153692f5bbc3"}, - {file = "statsmodels-0.13.3.tar.gz", hash = "sha256:ed71df887334b1d332e71d33215122bdd54494dcb2248606b30bcfa6112e860a"}, -] - -[package.dependencies] -numpy = {version = ">=1.17", markers = "python_version != \"3.10\" or platform_system != \"Windows\" or platform_python_implementation == \"PyPy\""} -packaging = ">=21.3" -pandas = ">=0.25" -patsy = ">=0.5.2" -scipy = {version = ">=1.3", markers = "(python_version > \"3.7\" or platform_system != \"Windows\" or platform_machine != \"x86\") and python_version < \"3.12\""} - -[package.extras] -build = ["cython (>=0.29.32)"] -develop = ["Jinja2", "colorama", "cython (>=0.29.32)", "cython (>=0.29.32,<3.0.0)", "flake8", "isort", "joblib", "matplotlib (>=3)", "oldest-supported-numpy (>=2022.4.18)", "pytest (>=7.0.1,<7.1.0)", "pytest-randomly", "pytest-xdist", "pywinpty", "setuptools-scm[toml] (>=7.0.0,<7.1.0)"] -docs = ["ipykernel", "jupyter-client", "matplotlib", "nbconvert", "nbformat", "numpydoc", "pandas-datareader", "sphinx"] - [[package]] name = "statsmodels" version = "0.13.5" @@ -8765,7 +8718,7 @@ numpy = [ packaging = ">=21.3" pandas = ">=0.25" patsy = ">=0.5.2" -scipy = {version = ">=1.3", markers = "(python_version > \"3.9\" or platform_system != \"Windows\" or platform_machine != \"x86\") and python_version < \"3.12\""} +scipy = {version = ">=1.3", markers = "python_version > \"3.9\" and python_version < \"3.12\" or platform_system != \"Windows\" and python_version < \"3.12\" or platform_machine != \"x86\" and python_version < \"3.12\""} [package.extras] build = ["cython (>=0.29.32)"] @@ -10558,4 +10511,4 @@ optimization = ["Riskfolio-Lib"] [metadata] lock-version = "2.0" python-versions = "^3.8.1,<3.11, !=3.9.7" -content-hash = "1852494c8df358b3c3631c50ee1d081b113b9b2f6c2c728f1570e8ecae8a3fea" +content-hash = "8347de5903ddbda7e77ce2bcfe4349702d41233891c9ea65a407611c96b57d87" diff --git a/pyproject.toml b/pyproject.toml index 0762644db5b..2a3bf4c979b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -101,7 +101,7 @@ jupyterlab-widgets = "^3.0.3" mstarpy = "^0.0.4" packaging = ">=22.0" streamlit = "^1.24.1" -pywry = "^0.5.13" +pywry = "^0.5.14" svglib = "^1.5.0" sparqlwrapper = "^2.0.0" y-py = "!=0.5.5" # Untraceable third level dependency that requires cargo to be built diff --git a/requirements-full.txt b/requirements-full.txt index 52f9fe31fec..9296a620c1f 100644 --- a/requirements-full.txt +++ b/requirements-full.txt @@ -122,7 +122,7 @@ google-auth-oauthlib==1.0.0 ; python_full_version >= "3.8.1" and python_full_ver google-auth==2.22.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" graphlib-backport==1.0.3 ; python_full_version >= "3.8.1" and python_version < "3.9" graphviz==0.20.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" -greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") +greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") grpcio==1.56.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" h11==0.14.0 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" hijri-converter==2.3.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -315,7 +315,7 @@ pytz==2023.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" pywin32-ctypes==0.2.2 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" and sys_platform == "win32" pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pywinpty==2.0.11 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and os_name == "nt" -pywry==0.5.13 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" +pywry==0.5.14 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyyaml==6.0.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyzmq==25.1.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" qdldl==0.1.7.post0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" diff --git a/requirements.txt b/requirements.txt index 67a6dff71eb..93c70ad0a27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -80,7 +80,7 @@ future==0.18.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9. gitdb==4.0.10 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" gitpython==3.1.32 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" graphlib-backport==1.0.3 ; python_full_version >= "3.8.1" and python_version < "3.9" -greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "win32" or platform_machine == "WIN32" or platform_machine == "AMD64" or platform_machine == "amd64" or platform_machine == "x86_64" or platform_machine == "ppc64le" or platform_machine == "aarch64") +greenlet==2.0.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") grpcio==1.56.2 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" h11==0.14.0 ; python_full_version >= "3.8.1" and python_version < "3.11" and python_full_version != "3.9.7" hijri-converter==2.3.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" @@ -217,7 +217,7 @@ pytz-deprecation-shim==0.1.0.post0 ; python_full_version >= "3.8.1" and python_f pytz==2023.3 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pywin32==306 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pywinpty==2.0.11 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" and os_name == "nt" -pywry==0.5.13 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" +pywry==0.5.14 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyyaml==6.0.1 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" pyzmq==25.1.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" quandl==3.7.0 ; python_full_version >= "3.8.1" and python_full_version != "3.9.7" and python_version < "3.11" diff --git a/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_controller.py b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_controller.py new file mode 100644 index 00000000000..0397aacd561 --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_controller.py @@ -0,0 +1,172 @@ +"""Test the companieshouse controller.""" +import os + +import pytest + +from openbb_terminal.alternative.companieshouse import companieshouse_controller +from openbb_terminal.core.session.current_user import PreferencesModel, copy_user + + +@pytest.mark.vcr(record_mode="none") +@pytest.mark.record_stdout +def test_print_help(): + controller = companieshouse_controller.CompaniesHouseController(queue=None) + controller.print_help() + + +@pytest.mark.vcr(record_mode="none") +def test_menu_without_queue_completion(mocker): + preferences = PreferencesModel(USE_PROMPT_TOOLKIT=True) + mock_current_user = copy_user(preferences=preferences) + mocker.patch( + target="openbb_terminal.core.session.current_user.__current_user", + new=mock_current_user, + ) + mocker.patch( + target="openbb_terminal.parent_classes.session", + ) + mocker.patch( + target="openbb_terminal.parent_classes.session.prompt", + return_value="quit", + ) + mocker.patch( + target="openbb_terminal.alternative.companieshouse.companieshouse_controller.session", + ) + mocker.patch( + target="openbb_terminal.alternative.companieshouse.companieshouse_controller.session.prompt", + return_value="quit", + ) + + result_menu = companieshouse_controller.CompaniesHouseController().menu() + + assert result_menu == ["help"] + + +@pytest.mark.parametrize( + "mock_input", + ["help", "homee help", "home help", "mock"], +) +@pytest.mark.vcr(record_mode="none") +def test_menu_without_queue_sys_exit(mock_input, mocker): + path_controller = ( + "openbb_terminal.alternative.companieshouse.companieshouse_controller" + ) + + # DISABLE AUTO-COMPLETION + preferences = PreferencesModel( + USE_PROMPT_TOOLKIT=False, + ) + mock_current_user = copy_user(preferences=preferences) + mocker.patch( + target="openbb_terminal.core.session.current_user.__current_user", + new=mock_current_user, + ) + mocker.patch( + target=f"{path_controller}.session", + return_value=None, + ) + + # MOCK USER INPUT + mocker.patch("builtins.input", return_value=mock_input) + + # MOCK SWITCH + mocker.patch( + target=f"{path_controller}.CompaniesHouseController.switch", + return_value=["quit"], + ) + + # MOCK SWITCH + class SystemExitSideEffect: + def __init__(self): + self.first_call = True + + def __call__(self, *args, **kwargs): + if self.first_call: + self.first_call = False + raise SystemExit() + return ["quit"] + + mock_switch = mocker.Mock(side_effect=SystemExitSideEffect()) + + mocker.patch( + target=f"{path_controller}.CompaniesHouseController.switch", + new=mock_switch, + ) + + result_menu = companieshouse_controller.CompaniesHouseController().menu() + + assert result_menu == ["help"] + + +@pytest.mark.parametrize( + "an_input, expected_queue", + [ + ("", []), + ("/help", ["home", "help"]), + ("help/help", ["help", "help"]), + ("q", ["quit"]), + ("h", []), + ("home", ["quit", "quit"]), + ( + "r", + ["quit", "quit", "reset", "alternative", "companieshouse"], + ), + ], +) +def test_switch(an_input, expected_queue): + controller = companieshouse_controller.CompaniesHouseController(queue=None) + queue = controller.switch(an_input=an_input) + + assert queue == expected_queue + + +@pytest.mark.vcr(record_mode="none") +def test_call_cls(mocker): + mocker.patch("os.system") + + controller = companieshouse_controller.CompaniesHouseController(queue=None) + controller.call_cls([]) + + assert controller.queue == [] + + os.system.assert_called_once_with("cls||clear") + + +@pytest.mark.parametrize( + "func, queue, expected_queue", + [ + ( + "call_exit", + [], + ["quit", "quit", "quit"], + ), + ("call_exit", ["help"], ["quit", "quit", "quit", "help"]), + ("call_home", [], ["quit", "quit"]), + ("call_help", [], []), + ("call_quit", [], ["quit"]), + ("call_quit", ["help"], ["quit", "help"]), + ( + "call_reset", + [], + ["quit", "quit", "reset", "alternative", "companieshouse"], + ), + ( + "call_reset", + ["help"], + ["quit", "quit", "reset", "alternative", "companieshouse", "help"], + ), + ], +) +def test_call_func_expect_queue(expected_queue, func, queue): + controller = companieshouse_controller.CompaniesHouseController(queue=queue) + result = getattr(controller, func)([]) + + assert result is None + assert controller.queue == expected_queue + + +@pytest.mark.vcr(record_mode="none") +def test_quit(): + controller = companieshouse_controller.CompaniesHouseController(queue=None) + controller.call_quit([]) + assert controller.queue == ["quit"] diff --git a/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_model.py b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_model.py new file mode 100644 index 00000000000..22ee7ee1ecc --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_model.py @@ -0,0 +1,299 @@ +import requests + +# IMPORTATION INTERNAL +from openbb_terminal.alternative.companieshouse import companieshouse_model +from openbb_terminal.alternative.companieshouse.company_doc import CompanyDocument + + +def test_get_search_results(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_results": 2369, + "items": [ + { + "kind": "searchresults#company", + "matches": {"title": [1, 5], "snippet": [13, 17]}, + "links": {"self": "/company/04366849"}, + "company_type": "plc", + "address": { + "premises": "Shell Centre", + "address_line_1": "London", + "postal_code": "SE1 7NA", + }, + "description": "04366849 - Incorporated on 5 February 2002", + "snippet": "ROYAL DUTCH SHELL ", + "title": "SHELL PLC", + "company_status": "active", + "date_of_creation": "2002-02-05", + "address_snippet": "Shell Centre, London, SE1 7NA", + "description_identifier": ["incorporated-on"], + "company_number": "04366849", + }, + { + "address_snippet": "Shell Centre, York Road, London, United Kingdom, SE1 7NA", + "description_identifier": ["incorporated-on"], + "company_number": "03323845", + "date_of_creation": "1997-02-25", + "links": {"self": "/company/03323845"}, + "matches": {"title": [1, 5], "snippet": [1, 5]}, + "company_type": "ltd", + "address": { + "address_line_1": "York Road", + "postal_code": "SE1 7NA", + "country": "United Kingdom", + "premises": "Shell Centre", + "locality": "London", + }, + "kind": "searchresults#company", + "snippet": "SHELL ", + "title": "SHELL GROUP LIMITED", + "company_status": "active", + "description": "03323845 - Incorporated on 25 February 1997", + }, + ], + "items_per_page": 2, + "kind": "search#companies", + "start_index": 0, + "page_number": 1, + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + result = companieshouse_model.get_search_results("shell", 2) + + assert len(result) == 2 + assert result["Name"].iloc[0] == "SHELL PLC" + assert result["Company Number"].iloc[0] == "04366849" + + +def test_get_persons_with_significant_control(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "ceased_count": 0, + "items_per_page": 25, + "total_results": 1, + "active_count": 1, + "start_index": 0, + "items": [ + { + "notified_on": "2020-12-18", + "links": { + "self": "/company/13090621/persons-with-significant-control/individual/vLLtcUU1xdVC4x3tXu2szkiDluE" + }, + "etag": "69ad137b49c648c6dd013761b82b52e6a7d474cb", + "kind": "individual-person-with-significant-control", + "country_of_residence": "England", + "name": "Mrs Shelley Ann Fray", + "natures_of_control": [ + "ownership-of-shares-75-to-100-percent", + "voting-rights-75-to-100-percent", + "right-to-appoint-and-remove-directors", + ], + "nationality": "British", + "address": { + "address_line_1": "Broadway", + "premises": "476-478", + "address_line_2": "Chadderton", + "country": "England", + "locality": "Oldham", + "postal_code": "OL9 9NS", + }, + "date_of_birth": {"month": 6, "year": 1985}, + "name_elements": { + "surname": "Fray", + "middle_name": "Ann", + "title": "Mrs", + "forename": "Shelley", + }, + } + ], + "links": {"self": "/company/13090621/persons-with-significant-control"}, + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + result = companieshouse_model.get_persons_with_significant_control("13090621") + + assert result["Name"].iloc[0] == "Mrs Shelley Ann Fray" + + +def test_get_officers(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_results": 1, + "links": {"self": "/company/13090621/officers"}, + "items_per_page": 35, + "items": [ + { + "links": { + "self": "/company/13090621/appointments/y2Xs68vEDqfz-zbmxzc4QucY8fQ", + "officer": { + "appointments": "/officers/MSVxvbR-XzoxCZazKccwdkkmCYE/appointments" + }, + }, + "date_of_birth": {"month": 6, "year": 1985}, + "address": { + "country": "England", + "address_line_2": "Chadderton", + "address_line_1": "Broadway", + "locality": "Oldham", + "premises": "476-478", + "postal_code": "OL9 9NS", + }, + "name": "FRAY, Shelley Ann", + "occupation": "Director", + "appointed_on": "2020-12-18", + "country_of_residence": "England", + "officer_role": "director", + "nationality": "British", + } + ], + "etag": "1138d965d225f6a0e5685c6d35e84e6a2dc0fc4f", + "resigned_count": 0, + "start_index": 0, + "inactive_count": 0, + "active_count": 1, + "kind": "officer-list", + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + result = companieshouse_model.get_officers("13090621") + + assert len(result) == 1 + assert result["Officer Role"].iloc[0] == "director" + + +def test_get_charges(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "etag": "0921370a2f5d8d191cc0c96de8de4ad7acdf68db", + "total_count": 1, + "unfiltered_count": 1, + "satisfied_count": 0, + "part_satisfied_count": 0, + "items": [ + { + "etag": "679e0c72b80543b2dc390b3d102163cf6cb89430", + "charge_code": "027235340001", + "classification": { + "type": "charge-description", + "description": "A registered charge", + }, + "charge_number": 1, + "status": "outstanding", + "delivered_on": "2014-12-04", + "created_on": "2014-11-26", + "particulars": { + "contains_fixed_charge": True, + "contains_negative_pledge": True, + }, + "persons_entitled": [{"name": "Astrazeneca Pensions Trustee Limited "}], + "transactions": [ + { + "filing_type": "create-charge-with-deed", + "delivered_on": "2014-12-04", + "links": { + "filing": "/company/02723534/filing-history/MzExMzExMzg3N2FkaXF6a2N4" + }, + } + ], + "links": { + "self": "/company/02723534/charges/ObJFuAILDHfp00ro3wjqXEonL7k" + }, + } + ], + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + result = companieshouse_model.get_charges("13090621") + + assert len(result) == 1 + + +def test_get_filings(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_count": 3, + "items_per_page": 25, + "items": [ + { + "action_date": "2022-12-17", + "category": "confirmation-statement", + "date": "2023-01-06", + "description": "confirmation-statement-with-no-updates", + "description_values": {"made_up_date": "2022-12-17"}, + "links": { + "self": "/company/13090621/filing-history/MzM2NDcxNTAzMWFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/ZIvX", + }, + "type": "CS01", + "pages": 3, + "barcode": "XBUK9D4X", + "transaction_id": "MzM2NDcxNTAzMWFkaXF6a2N4", + }, + { + "category": "accounts", + "date": "2022-09-14", + "description": "accounts-with-accounts-type-unaudited-abridged", + "description_values": {"made_up_date": "2021-12-31"}, + "links": { + "self": "/company/13090621/filing-history/MzM1MTY4NjU5NmFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/8_jg", + }, + "type": "AA", + "pages": 9, + "barcode": "XBCG6V3N", + "transaction_id": "MzM1MTY4NjU5NmFkaXF6a2N4", + }, + { + "action_date": "2022-09-09", + "category": "address", + "date": "2022-09-09", + "description": "change-registered-office-address-company-with-date-old-address-new-address", + "description_values": { + "change_date": "2022-09-09", + "old_address": "1J Shillington Old School Este Road London SW11 2TB", + "new_address": "476-478 Broadway Chadderton Oldham OL9 9NS", + }, + "links": { + "self": "/company/13090621/filing-history/MzM1MTIwMjE4NGFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/h1b5B84v", + }, + "type": "AD01", + "pages": 1, + "barcode": "XBC30YEG", + "transaction_id": "MzM1MTIwMjE4NGFkaXF6a2N4", + }, + ], + "start_index": 0, + "filing_history_status": "filing-history-available", + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + result = companieshouse_model.get_filings("13090621", 0) + + assert len(result.filings) == 3 + assert result.filings["Category"].iloc[0] == "confirmation-statement" + + +def test_get_filing_document(mocker): + result = CompanyDocument( + "confirmation-statement", + "2023-01-06", + "confirmation-statement-with-no-updates", + "paper_filed", + 3, + "MzM2NDcxNTAzMWFkaXF6a2N4", + "content", + ) + + assert result.description == "confirmation-statement-with-no-updates" + assert result.pages == 3 diff --git a/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_view.py b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_view.py new file mode 100644 index 00000000000..dede9e7512d --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/test_companieshouse_view.py @@ -0,0 +1,283 @@ +import pandas as pd +import pytest +import requests + +# IMPORTATION INTERNAL +from openbb_terminal.alternative.companieshouse import companieshouse_view +from openbb_terminal.helper_funcs import print_rich_table + + +@pytest.mark.vcr +@pytest.mark.record_stdout +def test_display_search(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_results": 2369, + "items": [ + { + "kind": "searchresults#company", + "matches": {"title": [1, 5], "snippet": [13, 17]}, + "links": {"self": "/company/04366849"}, + "company_type": "plc", + "address": { + "premises": "Shell Centre", + "address_line_1": "London", + "postal_code": "SE1 7NA", + }, + "description": "04366849 - Incorporated on 5 February 2002", + "snippet": "ROYAL DUTCH SHELL ", + "title": "SHELL PLC", + "company_status": "active", + "date_of_creation": "2002-02-05", + "address_snippet": "Shell Centre, London, SE1 7NA", + "description_identifier": ["incorporated-on"], + "company_number": "04366849", + }, + { + "address_snippet": "Shell Centre, York Road, London, United Kingdom, SE1 7NA", + "description_identifier": ["incorporated-on"], + "company_number": "03323845", + "date_of_creation": "1997-02-25", + "links": {"self": "/company/03323845"}, + "matches": {"title": [1, 5], "snippet": [1, 5]}, + "company_type": "ltd", + "address": { + "address_line_1": "York Road", + "postal_code": "SE1 7NA", + "country": "United Kingdom", + "premises": "Shell Centre", + "locality": "London", + }, + "kind": "searchresults#company", + "snippet": "SHELL ", + "title": "SHELL GROUP LIMITED", + "company_status": "active", + "description": "03323845 - Incorporated on 25 February 1997", + }, + ], + "items_per_page": 2, + "kind": "search#companies", + "start_index": 0, + "page_number": 1, + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + companieshouse_view.display_search("shell", 2) + + +@pytest.mark.vcr +@pytest.mark.record_stdout +def test_display_persons_with_significant_control(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "ceased_count": 0, + "items_per_page": 25, + "total_results": 1, + "active_count": 1, + "start_index": 0, + "items": [ + { + "notified_on": "2020-12-18", + "links": { + "self": "/company/13090621/persons-with-significant-control/individual/vLLtcUU1xdVC4x3tXu2szkiDluE" + }, + "etag": "69ad137b49c648c6dd013761b82b52e6a7d474cb", + "kind": "individual-person-with-significant-control", + "country_of_residence": "England", + "name": "Mrs Shelley Ann Fray", + "natures_of_control": [ + "ownership-of-shares-75-to-100-percent", + "voting-rights-75-to-100-percent", + "right-to-appoint-and-remove-directors", + ], + "nationality": "British", + "address": { + "address_line_1": "Broadway", + "premises": "476-478", + "address_line_2": "Chadderton", + "country": "England", + "locality": "Oldham", + "postal_code": "OL9 9NS", + }, + "date_of_birth": {"month": 6, "year": 1985}, + "name_elements": { + "surname": "Fray", + "middle_name": "Ann", + "title": "Mrs", + "forename": "Shelley", + }, + } + ], + "links": {"self": "/company/13090621/persons-with-significant-control"}, + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + companieshouse_view.display_persons_with_significant_control("13090621") + + +@pytest.mark.vcr +@pytest.mark.record_stdout +def test_display_officers(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_results": 1, + "links": {"self": "/company/13090621/officers"}, + "items_per_page": 35, + "items": [ + { + "links": { + "self": "/company/13090621/appointments/y2Xs68vEDqfz-zbmxzc4QucY8fQ", + "officer": { + "appointments": "/officers/MSVxvbR-XzoxCZazKccwdkkmCYE/appointments" + }, + }, + "date_of_birth": {"month": 6, "year": 1985}, + "address": { + "country": "England", + "address_line_2": "Chadderton", + "address_line_1": "Broadway", + "locality": "Oldham", + "premises": "476-478", + "postal_code": "OL9 9NS", + }, + "name": "FRAY, Shelley Ann", + "occupation": "Director", + "appointed_on": "2020-12-18", + "country_of_residence": "England", + "officer_role": "director", + "nationality": "British", + } + ], + "etag": "1138d965d225f6a0e5685c6d35e84e6a2dc0fc4f", + "resigned_count": 0, + "start_index": 0, + "inactive_count": 0, + "active_count": 1, + "kind": "officer-list", + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + companieshouse_view.display_officers("13090621") + + +@pytest.mark.vcr +@pytest.mark.record_stdout +def test_display_charges(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "etag": "0921370a2f5d8d191cc0c96de8de4ad7acdf68db", + "total_count": 1, + "unfiltered_count": 1, + "satisfied_count": 0, + "part_satisfied_count": 0, + "items": [ + { + "etag": "679e0c72b80543b2dc390b3d102163cf6cb89430", + "charge_code": "027235340001", + "classification": { + "type": "charge-description", + "description": "A registered charge", + }, + "charge_number": 1, + "status": "outstanding", + "delivered_on": "2014-12-04", + "created_on": "2014-11-26", + "particulars": { + "contains_fixed_charge": True, + "contains_negative_pledge": True, + }, + "persons_entitled": [{"name": "Astrazeneca Pensions Trustee Limited "}], + "transactions": [ + { + "filing_type": "create-charge-with-deed", + "delivered_on": "2014-12-04", + "links": { + "filing": "/company/02723534/filing-history/MzExMzExMzg3N2FkaXF6a2N4" + }, + } + ], + "links": { + "self": "/company/02723534/charges/ObJFuAILDHfp00ro3wjqXEonL7k" + }, + } + ], + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + df = pd.DataFrame.from_records(mock_response.json.return_value["items"]).iloc[0] + # Call the function that makes a request to the remote API + print_rich_table(df, show_index=True, title="Charges") + + +@pytest.mark.vcr +@pytest.mark.record_stdout +def test_display_filings(mocker): + mock_response = mocker.Mock() + mock_response.json.return_value = { + "total_count": 3, + "items_per_page": 25, + "items": [ + { + "action_date": "2022-12-17", + "category": "confirmation-statement", + "date": "2023-01-06", + "description": "confirmation-statement-with-no-updates", + "description_values": {"made_up_date": "2022-12-17"}, + "links": { + "self": "/company/13090621/filing-history/MzM2NDcxNTAzMWFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/ZIvX", + }, + "type": "CS01", + "pages": 3, + "barcode": "XBUK9D4X", + "transaction_id": "MzM2NDcxNTAzMWFkaXF6a2N4", + }, + { + "category": "accounts", + "date": "2022-09-14", + "description": "accounts-with-accounts-type-unaudited-abridged", + "description_values": {"made_up_date": "2021-12-31"}, + "links": { + "self": "/company/13090621/filing-history/MzM1MTY4NjU5NmFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/8_jg", + }, + "type": "AA", + "pages": 9, + "barcode": "XBCG6V3N", + "transaction_id": "MzM1MTY4NjU5NmFkaXF6a2N4", + }, + { + "action_date": "2022-09-09", + "category": "address", + "date": "2022-09-09", + "description": "change-registered-office-address-company-with-date-old-address-new-address", + "description_values": { + "change_date": "2022-09-09", + "old_address": "1J Shillington Old School Este Road London SW11 2TB", + "new_address": "476-478 Broadway Chadderton Oldham OL9 9NS", + }, + "links": { + "self": "/company/13090621/filing-history/MzM1MTIwMjE4NGFkaXF6a2N4", + "document_metadata": "https://frontend-doc-api.company-information.service.gov.uk/document/h1b5B84v", + }, + "type": "AD01", + "pages": 1, + "barcode": "XBC30YEG", + "transaction_id": "MzM1MTIwMjE4NGFkaXF6a2N4", + }, + ], + "start_index": 0, + "filing_history_status": "filing-history-available", + } + + mocker.patch.object(requests, "get", return_value=mock_response) + + # Call the function that makes a request to the remote API + companieshouse_view.display_filings("13090621", 0) diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_controller/test_print_help.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_controller/test_print_help.txt new file mode 100644 index 00000000000..ef2478d3414 --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_controller/test_print_help.txt @@ -0,0 +1,10 @@ +Current Company: + + search search for companies by name + load retrieve basic company details by company registration number + officers retrieve company officies + signifcontrol retrieve those with significant control over the company + filings retrieve list of documents filed with Companies House (Default 100) + filingdocument download filed document + charges registered charges against the company + diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_charges.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_charges.txt new file mode 100644 index 00000000000..45ea7729494 --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_charges.txt @@ -0,0 +1,11 @@ +etag 679e0c72b80543b2dc390b3d102163cf6cb89430 +charge_code 027235340001 +classification {'type': 'charge-description', 'description': ... +charge_number 1 +status outstanding +delivered_on 2014-12-04 +created_on 2014-11-26 +particulars {'contains_fixed_charge': True, 'contains_nega... +persons_entitled [{'name': 'Astrazeneca Pensions Trustee Limite... +transactions [{'filing_type': 'create-charge-with-deed', 'd... +links {'self': '/company/02723534/charges/ObJFuAILDH... diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_filings.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_filings.txt new file mode 100644 index 00000000000..02d7bf5b688 --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_filings.txt @@ -0,0 +1,5 @@ +Retrieved 3 filings + Category Date Description Type Pages Transaction ID Download +0 confirmation-statement 2023-01-06 confirmation-statement-with-no-updates CS01 3 MzM2NDcxNTAzMWFkaXF6a2N4 https://find-and-update.company-information.service.gov.uk/company/13090621/filing-history/MzM2NDcxNTAzMWFkaXF6a2N4/document?format=pdf&download=0 +1 accounts 2022-09-14 accounts-with-accounts-type-unaudited-abridged AA 9 MzM1MTY4NjU5NmFkaXF6a2N4 https://find-and-update.company-information.service.gov.uk/company/13090621/filing-history/MzM1MTY4NjU5NmFkaXF6a2N4/document?format=pdf&download=0 +2 address 2022-09-09 change-registered-office-address-company-with-date-old-address-new-address AD01 1 MzM1MTIwMjE4NGFkaXF6a2N4 https://find-and-update.company-information.service.gov.uk/company/13090621/filing-history/MzM1MTIwMjE4NGFkaXF6a2N4/document?format=pdf&download=0 diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_officers.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_officers.txt new file mode 100644 index 00000000000..8e52e5cfbcf --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_officers.txt @@ -0,0 +1,3 @@ +Retrieved 1 records + Officer Role Appointed On Resigned On Name +0 director 2020-12-18 - FRAY, Shelley Ann diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_persons_with_significant_control.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_persons_with_significant_control.txt new file mode 100644 index 00000000000..768bee61d87 --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_persons_with_significant_control.txt @@ -0,0 +1,3 @@ +Retrieved 1 records + Kind Name Natures of Control Notified On +0 individual-person-with-significant-control Mrs Shelley Ann Fray [ownership-of-shares-75-to-100-percent, voting-rights-75-to-100-percent, right-to-appoint-and-remove-directors] 2020-12-18 diff --git a/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_search.txt b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_search.txt new file mode 100644 index 00000000000..5e1e69257de --- /dev/null +++ b/tests/openbb_terminal/alternative/companieshouse/txt/test_companieshouse_view/test_display_search.txt @@ -0,0 +1,4 @@ +Retrieved 2 records + Name Company Number Status +0 SHELL PLC 04366849 active +1 SHELL GROUP LIMITED 03323845 active diff --git a/tests/openbb_terminal/alternative/txt/test_alt_controller/test_print_help.txt b/tests/openbb_terminal/alternative/txt/test_alt_controller/test_print_help.txt index 801cfd9834b..00374ecbce2 100644 --- a/tests/openbb_terminal/alternative/txt/test_alt_controller/test_print_help.txt +++ b/tests/openbb_terminal/alternative/txt/test_alt_controller/test_print_help.txt @@ -1,6 +1,7 @@ -> covid COVID menu cases, deaths, rates -> oss Open Source menu star history, repos information -> realestate Real Estate menu sold prices, HPIs +> covid COVID menu, cases, deaths, rates +> oss Open Source menu, star history, repos information +> realestate Real Estate menu, sold prices, HPIs +> companieshouse Companies House menu, UK company information hn Hacker News most popular stories [HackerNews] diff --git a/website/content/sdk/usage/guides/api-keys.md b/website/content/sdk/usage/guides/api-keys.md index 3d751db4843..288b26b1408 100644 --- a/website/content/sdk/usage/guides/api-keys.md +++ b/website/content/sdk/usage/guides/api-keys.md @@ -4,10 +4,9 @@ sidebar_position: 1 description: API (Application Programming Interface) keys are access credentials for accessing data from a particular source. Learn how to set, manage, and access data APIs for the OpenBB SDK. keywords: [api, keys, api keys, data provider, data, free, alpha vantage, fred, iex, twitter, degiro, binance, coinglass, polygon, intrinio, sdk, alphavantage, bitquery, coinbase, databento, finnhub, FRED, github, glassnode, iex cloud, news API, robinhood, santiment, shroomdk, token terminal, tradier, twitter, whale alert] --- - import HeadTitle from '@site/src/components/General/HeadTitle.tsx'; - +`` ## The Keys Module @@ -176,8 +175,6 @@ openbb.keys.biztoc(key = "REPLACE_WITH_KEY", persist=True) ### CoinMarketCap -### CoinMarketCap - > CoinMarketCap is the world's most-referenced price-tracking website for cryptoassets in the rapidly growing cryptocurrency space. Its mission is to make crypto discoverable and efficient globally by empowering retail users with unbiased, high quality and accurate information for drawing their own informed conclusions.
@@ -250,6 +247,29 @@ openbb.keys.coinglass(key = 'REPLACE_WITH_KEY', persist = True)
+### Companies House + +> The Companies House API lets you retrieve information about limited companies (and other companies that fall within the Companies Act 2006). The data returned is live and real-time, and is simple to use and understand. + +
+Instructions + +Setup an account by following the instructions [here](https://developer-specs.company-information.service.gov.uk/guides/gettingStarted#set-up-a-companies-house-account). + +![Companies House](https://user-images.githubusercontent.com/85772166/234980988-352e36f7-334b-4e4c-846f-2cea128f9464.png) + +After creating the account and logging in, click on, [Create an Application](https://developer.company-information.service.gov.uk/manage-applications/add). Fill out the form and then click the `Create` button at the bottom of the page. + +![Create an Application](https://user-images.githubusercontent.com/85772166/234981083-e78cf4f7-3be0-404e-b7cc-b452679bbb06.png) + +Once the application is created, an API key can be generated by clicking on `View all Applications`, and then the `Create new key` button at the bottom. Copy the API key value to the clipboard and then enter it into the OpenBB SDK with: + +```console +openbb.keys.companieshouse('REPLACE_WITH_KEY', persist = True) +``` + +
+ ### Crypto Panic > CryptoPanic is a news aggregator platform indicating impact on price and market for traders and cryptocurrency enthusiasts. diff --git a/website/content/terminal/usage/guides/api-keys.md b/website/content/terminal/usage/guides/api-keys.md index 75ff8caac82..46a3601b90a 100644 --- a/website/content/terminal/usage/guides/api-keys.md +++ b/website/content/terminal/usage/guides/api-keys.md @@ -223,6 +223,29 @@ With the account created, find the assigned API key within the account profile p +### Companies House + +> The Companies House API lets you retrieve information about limited companies (and other companies that fall within the Companies Act 2006). The data returned is live and real-time, and is simple to use and understand. + +
+Instructions + +Setup an account by following the instructions [here](https://developer-specs.company-information.service.gov.uk/guides/gettingStarted#set-up-a-companies-house-account). + +![Companies House](https://user-images.githubusercontent.com/85772166/234980988-352e36f7-334b-4e4c-846f-2cea128f9464.png) + +After creating the account and logging in, click on, [Create an Application](https://developer.company-information.service.gov.uk/manage-applications/add). Fill out the form and then click the `Create` button at the bottom of the page. + +![Create an Application](https://user-images.githubusercontent.com/85772166/234981083-e78cf4f7-3be0-404e-b7cc-b452679bbb06.png) + +Once the application is created, an API key can be generated by clicking on `View all Applications`, and then the `Create new key` button at the bottom. Copy the API key value to the clipboard and then enter it into the OpenBB Terminal with: + +```console +keys/companieshouse -k REPLACE_WITH_KEY +``` + +
+ ### Crypto Panic > CryptoPanic is a news aggregator platform indicating impact on price and market for traders and cryptocurrency enthusiasts.