many changes
This commit is contained in:
parent
126ede37a4
commit
661941a65c
7 changed files with 102 additions and 21 deletions
|
|
@ -66,12 +66,14 @@ def xe_healthcheck():
|
|||
"--currencies", default=",".join([]), show_default=True, type=click.STRING
|
||||
)
|
||||
@click.option("--dry-run", is_flag=True)
|
||||
@click.option("--ignore-warnings", is_flag=True)
|
||||
@click.option("--output", type=click.STRING, required=True)
|
||||
def get_rates(
|
||||
start_date: Union[str, datetime.datetime, datetime.date],
|
||||
end_date: Union[str, datetime.datetime, datetime.date],
|
||||
currencies: Union[None, str],
|
||||
dry_run: bool,
|
||||
ignore_warnings: bool,
|
||||
output: pathlib.Path,
|
||||
):
|
||||
get_rates_inputs = handle_get_rates_inputs(
|
||||
|
|
@ -79,6 +81,7 @@ def get_rates(
|
|||
end_date=end_date,
|
||||
currencies=currencies,
|
||||
dry_run=dry_run,
|
||||
ignore_warnings=ignore_warnings,
|
||||
output=output,
|
||||
)
|
||||
logger.info("Starting get-rates process.")
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ def handle_get_rates_inputs(
|
|||
end_date: Union[datetime.datetime, datetime.date],
|
||||
currencies: Union[None, str],
|
||||
dry_run: bool,
|
||||
ignore_warnings: bool,
|
||||
output: Union[str, pathlib.Path],
|
||||
):
|
||||
logger.info("Handling inputs.")
|
||||
|
|
@ -31,7 +32,8 @@ def handle_get_rates_inputs(
|
|||
tmp = {Currency(currency_code) for currency_code in currencies}
|
||||
currencies = tmp
|
||||
|
||||
if currencies is None:
|
||||
if currencies is None or currencies == "":
|
||||
logger.info("No currency list passed. Running for default currencies.")
|
||||
currencies = DEFAULT_CURRENCIES
|
||||
|
||||
# The Path constructor is idempotent, so this works equally fine if output
|
||||
|
|
@ -44,6 +46,7 @@ def handle_get_rates_inputs(
|
|||
"date_range": date_range,
|
||||
"currencies": currencies,
|
||||
"dry_run": dry_run,
|
||||
"ignore_warnings": ignore_warnings,
|
||||
"output": output,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,16 +56,23 @@ def run_get_rates(
|
|||
date_range: DateRange,
|
||||
currencies: List[Currency],
|
||||
dry_run: bool,
|
||||
ignore_warnings: bool,
|
||||
output: pathlib.Path,
|
||||
) -> None:
|
||||
logger.info("Getting rates")
|
||||
|
||||
process_state = GetRatesProcessState(output=output, dry_run=dry_run)
|
||||
process_state = GetRatesProcessState(
|
||||
output=output, dry_run=dry_run, ignore_warnings=ignore_warnings
|
||||
)
|
||||
|
||||
rates = obtain_rates_from_source(
|
||||
process_state, date_range=date_range, currencies=currencies
|
||||
process_state,
|
||||
date_range=date_range,
|
||||
currencies=currencies,
|
||||
)
|
||||
logger.info("Rates obtained.")
|
||||
write_rates_to_output(process_state, rates)
|
||||
logger.info("Rates written to output.")
|
||||
|
||||
|
||||
def obtain_rates_from_source(
|
||||
|
|
@ -77,6 +84,21 @@ def obtain_rates_from_source(
|
|||
date_range=date_range, currencies=currencies
|
||||
)
|
||||
|
||||
large_api_call_planned = (
|
||||
rates_fetcher.is_production_grade and len(currency_and_date_combinations) > 100
|
||||
)
|
||||
if large_api_call_planned and not process_state.ignore_warnings:
|
||||
user_confirmation_string = "i understand"
|
||||
user_response = input(
|
||||
f"WARNING: you are about to execute a large call {len(currency_and_date_combinations)} to a metered API. Type '{user_confirmation_string}' to move forward."
|
||||
)
|
||||
if user_response != user_confirmation_string:
|
||||
raise Exception("Execution aborted.")
|
||||
|
||||
logger.debug(
|
||||
f"We are looking for the following rate combinations: {currency_and_date_combinations}"
|
||||
)
|
||||
|
||||
rates = ExchangeRates()
|
||||
for combination in currency_and_date_combinations:
|
||||
try:
|
||||
|
|
@ -97,13 +119,15 @@ def obtain_rates_from_source(
|
|||
|
||||
def write_rates_to_output(process_state, rates):
|
||||
rates_writer = process_state.get_writer()
|
||||
logger.info("Attempting writing rates to output.")
|
||||
rates_writer.write_rates(rates)
|
||||
|
||||
|
||||
class GetRatesProcessState:
|
||||
def __init__(self, output: str, dry_run: bool) -> None:
|
||||
def __init__(self, output: str, dry_run: bool, ignore_warnings: bool) -> None:
|
||||
self.writer = self._select_writer(output)
|
||||
self.fetcher = self._select_fetcher(dry_run)
|
||||
self.ignore_warnings = ignore_warnings
|
||||
|
||||
@staticmethod
|
||||
def _select_writer(output: str) -> CSVRateWriter:
|
||||
|
|
@ -115,12 +139,14 @@ class GetRatesProcessState:
|
|||
raise ValueError(f"Don't know how to handle passed output: {output}")
|
||||
|
||||
@staticmethod
|
||||
def _select_fetcher(dry_run: bool) -> str:
|
||||
def _select_fetcher(dry_run: bool) -> RateFetcher:
|
||||
if dry_run:
|
||||
return MockRateFetcher
|
||||
logger.info("Dry-run activated. Running against MockRateFetcher.")
|
||||
return MockRateFetcher()
|
||||
|
||||
if not dry_run:
|
||||
return XERateFetcher
|
||||
logger.info("Real run active. Running against XE.com's API.")
|
||||
return XERateFetcher()
|
||||
|
||||
def get_fetcher(self) -> RateFetcher:
|
||||
return self.fetcher
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ from xexe.exchange_rates import ExchangeRate
|
|||
|
||||
|
||||
class RateFetcher(ABC):
|
||||
|
||||
is_production_grade = False
|
||||
|
||||
@abstractmethod
|
||||
def fetch_rate(
|
||||
self, from_currency: Currency, to_currency: Currency, rate_date: datetime.date
|
||||
|
|
@ -19,6 +22,8 @@ class RateFetcher(ABC):
|
|||
|
||||
class MockRateFetcher(RateFetcher):
|
||||
|
||||
is_production_grade = False
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
|
@ -36,6 +41,8 @@ class MockRateFetcher(RateFetcher):
|
|||
|
||||
class XERateFetcher(RateFetcher):
|
||||
|
||||
is_production_grade = True
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.xe_client = XecdClient(
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class CSVRateWriter(RateWriter):
|
|||
self.output_file_path = output_file_path
|
||||
|
||||
def write_rates(self, rates: ExchangeRates) -> None:
|
||||
with open(self.output_file_path, mode="w", newline="") as csvfile:
|
||||
csv_writer = csv.writer(csvfile)
|
||||
with open(self.output_file_path, mode="w") as csv_file:
|
||||
csv_writer = csv.writer(csv_file)
|
||||
csv_writer.writerow(["from_currency", "to_currency", "rate", "rate_date"])
|
||||
|
||||
# Write the exchange rate data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue