diff --git a/src/gsy_e/gsy_e_core/sim_results/endpoint_buffer.py b/src/gsy_e/gsy_e_core/sim_results/endpoint_buffer.py index 86e2d8174..7f2fc74b3 100644 --- a/src/gsy_e/gsy_e_core/sim_results/endpoint_buffer.py +++ b/src/gsy_e/gsy_e_core/sim_results/endpoint_buffer.py @@ -26,12 +26,11 @@ from pendulum import DateTime from gsy_e.gsy_e_core.sim_results.offer_bids_trades_hr_stats import OfferBidTradeGraphStats -from gsy_e.gsy_e_core.util import get_market_maker_rate_from_config +from gsy_e.gsy_e_core.util import ( + get_market_maker_rate_from_config, get_feed_in_tariff_rate_from_config) from gsy_e.models.strategy.commercial_producer import CommercialStrategy from gsy_e.models.strategy.finite_power_plant import FinitePowerPlant -from gsy_e.models.strategy.infinite_bus import InfiniteBusStrategy from gsy_e.models.strategy.load_hours import LoadHoursStrategy -from gsy_e.models.strategy.market_maker_strategy import MarketMakerStrategy from gsy_e.models.strategy.pv import PVStrategy from gsy_e.models.strategy.smart_meter import SmartMeterStrategy from gsy_e.models.strategy.storage import StorageStrategy @@ -48,6 +47,8 @@ } +# pylint: disable=too-many-instance-attributes +# pylint: disable=logging-too-many-args class SimulationEndpointBuffer: """Handles collecting and buffering of all results for all areas.""" @@ -84,16 +85,16 @@ def prepare_results_for_publish(self) -> Dict: message_size = get_json_dict_memory_allocation_size(result_report) if message_size > 64000: - logging.error(f"Do not publish message bigger than 64 MB, " - f"current message size {message_size / 1000.0} MB.") + logging.error("Do not publish message bigger than 64 MB, " + "current message size %s MB.", (message_size / 1000.0)) return {} - logging.debug(f"Publishing {message_size} KB of data via Redis.") + logging.debug("Publishing %s KB of data via Redis.", message_size) return result_report @staticmethod def _structure_results_from_area_object(target_area: "Area") -> Dict: """Add basic information about the area in the area_tree_dict.""" - area_dict = dict() + area_dict = {} area_dict["name"] = target_area.name area_dict["uuid"] = target_area.uuid area_dict["parent_uuid"] = (target_area.parent.uuid @@ -121,7 +122,6 @@ def update_results_area_uuids(self, area: "Area") -> None: def generate_result_report(self) -> Dict: """Create dict that contains all statistics that are sent to the gsy-web.""" - # TODO: In D3ASIM-2288, add unix_time=True to convert_pendulum_to_str_in_dict return { "job_id": self.job_id, "current_market": self.current_market_time_slot_str, @@ -182,7 +182,8 @@ def _read_future_markets_stats_to_dict(self, area: "Area") -> Dict[str, Dict]: "market_fee": area.future_markets.market_fee, "const_fee_rate": (area.future_markets.const_fee_rate if area.future_markets.const_fee_rate is not None else 0.), - "feed_in_tariff": GlobalConfig.FEED_IN_TARIFF, + "feed_in_tariff": get_feed_in_tariff_rate_from_config(area.future_markets, + time_slot=time_slot), "market_maker_rate": get_market_maker_rate_from_config( area.future_markets, time_slot=time_slot) } @@ -203,10 +204,11 @@ def _read_market_stats_to_dict(market: "MarketBase") -> Dict: stats_dict["market_fee"] = market.market_fee stats_dict["const_fee_rate"] = (market.const_fee_rate if market.const_fee_rate is not None else 0.) - stats_dict["feed_in_tariff"] = GlobalConfig.FEED_IN_TARIFF + stats_dict["feed_in_tariff"] = get_feed_in_tariff_rate_from_config(market) stats_dict["market_maker_rate"] = get_market_maker_rate_from_config(market) return stats_dict + # pylint: disable=too-many-branches def _populate_core_stats_and_sim_state(self, area: "Area") -> None: """Populate all area statistics and state into self.flattened_area_core_stats_dict and self.simulation_state.""" @@ -278,18 +280,18 @@ def _populate_core_stats_and_sim_state(self, area: "Area") -> None: for trade in area.strategy.trades[area.parent.current_market]: core_stats_dict["trades"].append(trade.serializable_dict()) - elif type(area.strategy) == FinitePowerPlant: - core_stats_dict["production_kWh"] = area.strategy.energy_per_slot_kWh - if area.parent.current_market is not None: - for trade in area.strategy.trades[area.parent.current_market]: - core_stats_dict["trades"].append(trade.serializable_dict()) - - elif type(area.strategy) in [InfiniteBusStrategy, MarketMakerStrategy, CommercialStrategy]: - if area.parent.current_market is not None: - core_stats_dict["energy_rate"] = ( - area.strategy.energy_rate.get(area.parent.current_market.time_slot, None)) - for trade in area.strategy.trades[area.parent.current_market]: - core_stats_dict["trades"].append(trade.serializable_dict()) + elif isinstance(area.strategy, CommercialStrategy): + if isinstance(area.strategy, FinitePowerPlant): + core_stats_dict["production_kWh"] = area.strategy.energy_per_slot_kWh + if area.parent.current_market is not None: + for trade in area.strategy.trades[area.parent.current_market]: + core_stats_dict["trades"].append(trade.serializable_dict()) + else: + if area.parent.current_market is not None: + core_stats_dict["energy_rate"] = ( + area.strategy.energy_rate.get(area.parent.current_market.time_slot, None)) + for trade in area.strategy.trades[area.parent.current_market]: + core_stats_dict["trades"].append(trade.serializable_dict()) self.flattened_area_core_stats_dict[area.uuid] = core_stats_dict diff --git a/src/gsy_e/gsy_e_core/util.py b/src/gsy_e/gsy_e_core/util.py index 6877f9c51..10c20c4c8 100644 --- a/src/gsy_e/gsy_e_core/util.py +++ b/src/gsy_e/gsy_e_core/util.py @@ -25,9 +25,10 @@ import tty from functools import wraps from logging import LoggerAdapter, getLogger, getLoggerClass, addLevelName, setLoggerClass, NOTSET +from typing import TYPE_CHECKING from click.types import ParamType -from gsy_framework.constants_limits import GlobalConfig, RangeLimit, ConstSettings +from gsy_framework.constants_limits import ConstSettings, GlobalConfig, RangeLimit from gsy_framework.enums import BidOfferMatchAlgoEnum from gsy_framework.exceptions import GSyException from gsy_framework.utils import ( @@ -40,6 +41,10 @@ import gsy_e.constants from gsy_e import setup as d3a_setup +if TYPE_CHECKING: + from gsy_e.models.market import MarketBase + + d3a_path = os.path.dirname(inspect.getsourcefile(gsy_e)) @@ -52,6 +57,7 @@ class TraceLogger(getLoggerClass()): + """TraceLogger""" def __init__(self, name, level=NOTSET): super().__init__(name, level) @@ -76,11 +82,10 @@ def trace(self, msg, *args, **kwargs): class TaggedLogWrapper(LoggerAdapter): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + """TaggedLogWrapper""" def process(self, msg, kwargs): - msg = "[{}] {}".format(self.extra, msg) + msg = f"[{self.extra}] {msg}" return msg, kwargs def trace(self, msg, *args, **kwargs): @@ -91,92 +96,100 @@ def trace(self, msg, *args, **kwargs): class DateType(ParamType): - name = 'date' + """DateType""" + name = "date" - def __init__(self, type): - if type == gsy_e.constants.DATE_FORMAT: + def __init__(self, date_type: gsy_e.constants.DATE_FORMAT): + if date_type == gsy_e.constants.DATE_FORMAT: self.allowed_formats = gsy_e.constants.DATE_FORMAT else: - raise ValueError(f"Invalid type. Choices: {gsy_e.constants.DATE_FORMAT} ") + raise ValueError(f"Invalid date_type. Choices: {gsy_e.constants.DATE_FORMAT} ") def convert(self, value, param, ctx): try: - return from_format(value, gsy_e.constants.DATE_FORMAT) + converted_format = from_format(value, gsy_e.constants.DATE_FORMAT) except ValueError: self.fail( - "'{}' is not a valid date. Allowed formats: {}".format( - value, - self.allowed_formats - ) - ) + f"'{value}' is not a valid date. Allowed formats: {self.allowed_formats}") + return converted_format class IntervalType(ParamType): - name = 'interval' + """IntervalType""" + name = "interval" - def __init__(self, type): - if type == 'H:M': + def __init__(self, interval_type): + if interval_type == "H:M": self.re = INTERVAL_HM_RE self.allowed_formats = "'XXh', 'XXm', 'XXhYYm', 'XX:YY'" - elif type == 'D:H': + elif interval_type == "D:H": self.re = INTERVAL_DH_RE self.allowed_formats = "'XXh', 'XXd', 'XXdYYh'" - elif type == 'M:S': + elif interval_type == "M:S": self.re = INTERVAL_MS_RE self.allowed_formats = "'XXm', 'XXs', 'XXmYYs', 'XX:YY'" else: - raise ValueError("Invalid type. Choices: 'H:M', 'M:S', 'D:H'") + raise ValueError("Invalid date_type. Choices: 'H:M', 'M:S', 'D:H'") def convert(self, value, param, ctx): + converted_duration = None match = self.re(value) if match: - return duration(**{ - k: int(v) if v else 0 - for k, v in match.items() - if isinstance(k, str) - }) - self.fail( - "'{}' is not a valid duration. Allowed formats: {}".format( - value, - self.allowed_formats - ) - ) - - + try: + converted_duration = duration(**{ + k: int(v) if v else 0 + for k, v in match.items() + if isinstance(k, str) + }) + except ValueError: + self.fail( + f"'{value}' is not a valid duration. Allowed formats: {self.allowed_formats}") + return converted_duration + + +# pylint: disable=attribute-defined-outside-init class NonBlockingConsole: + """NonBlockingConsole""" def __enter__(self): if os.isatty(sys.stdin.fileno()): self.old_settings = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin.fileno()) return self - def __exit__(self, type, value, traceback): + def __exit__(self, date_type, value, traceback): if os.isatty(sys.stdin.fileno()): termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings) - def get_char(self, timeout=0): + @classmethod + def get_char(cls, timeout=0): + """get char""" if select.select([sys.stdin], [], [], timeout) == ([sys.stdin], [], []): return sys.stdin.read(1) return False def make_ma_name(owner): + """Make market agent name.""" return f"MA {owner.name}" def make_ba_name(owner): + """Make balancing agent name.""" return f"BA {owner.name}" def make_sa_name(owner): + """Make settlement agent name.""" return f"SA {owner.name}" def make_fa_name(owner): + """Make future market agent name.""" return f"FA {owner.name}" def format_interval(interval, show_day=True): + """Format interval.""" if interval.days and show_day: template = "{i.days:02d}:{i.hours:02d}:{i.minutes:02d}:{i.remaining_seconds:02d}" else: @@ -191,14 +204,14 @@ def format_interval(interval, show_day=True): def parseboolstring(thestring): + """Parse bool string.""" if thestring == "None": return None - elif thestring[0].upper() == 'T': + if thestring[0].upper() == "T": return True - elif thestring[0].upper() == 'F': + if thestring[0].upper() == "F": return False - else: - return thestring + return thestring def read_settings_from_file(settings_file): @@ -252,6 +265,7 @@ def update_nested_settings(class_object, class_name, settings_dict): def get_market_slot_time_str(slot_number, config): + """Get market slot time string.""" return format_datetime( config.start_date.add( minutes=config.slot_length.minutes * slot_number @@ -260,6 +274,7 @@ def get_market_slot_time_str(slot_number, config): def constsettings_to_dict(): + """Constant settings to dict.""" def convert_nested_settings(class_object, class_name, settings_dict): for key, value in dict(class_object.__dict__).items(): @@ -284,12 +299,14 @@ def convert_nested_settings(class_object, class_name, settings_dict): continue convert_nested_settings(settings_class, settings_class_name, const_settings) return const_settings - except Exception: + except Exception as ex: raise SyntaxError("Error when serializing the const settings file. Incorrect " - "setting structure.") + "setting structure.") from ex def retry_function(max_retries=3): + """Decorator that retries the execution of the function until it returns without + raising an exception.""" def decorator_with_max_retries(f): @wraps(f) def wrapped(*args, **kwargs): @@ -299,16 +316,19 @@ def wrapped(*args, **kwargs): def recursive_retry(functor, retry_count, max_retries, *args, **kwargs): + """Recursive function that retries the execution of "functor" function if an exception is + raised from it.""" try: return functor(*args, **kwargs) except (AssertionError, GSyException) as e: - log.debug(f"Retrying action {functor.__name__} for the {retry_count+1} time.") + log.debug("Retrying action %s for the %s time.", functor.__name__, retry_count+1) if retry_count >= max_retries: raise e return recursive_retry(functor, retry_count+1, max_retries, *args, **kwargs) def change_global_config(**kwargs): + """Change global config.""" for arg, value in kwargs.items(): if hasattr(GlobalConfig, arg): setattr(GlobalConfig, arg, value) @@ -318,7 +338,7 @@ def change_global_config(**kwargs): def validate_const_settings_for_simulation(): - from gsy_framework.constants_limits import ConstSettings + """Validate constant settings for simulation.""" # If schemes are not compared and an individual scheme is selected # And the market type is not single sided market # This is a wrong configuration and an exception is raised @@ -335,34 +355,39 @@ def validate_const_settings_for_simulation(): def round_floats_for_ui(number): + """Round floats for UI.""" return round(number, 3) -def add_or_create_key(dict, key, value): - if key in dict: - dict[key] += value +def add_or_create_key(indict, key, value): + """Add value or create key.""" + if key in indict: + indict[key] += value else: - dict[key] = value - return dict + indict[key] = value + return indict -def subtract_or_create_key(dict, key, value): - if key in dict: - dict[key] -= value +def subtract_or_create_key(indict, key, value): + """Subtract value of create key.""" + if key in indict: + indict[key] -= value else: - dict[key] = 0 - value - return dict + indict[key] = 0 - value + return indict -def append_or_create_key(dict, key, obj): - if key in dict: - dict[key].append(obj) +def append_or_create_key(data_dict, key, obj): + """Append value or create key.""" + if key in data_dict: + data_dict[key].append(obj) else: - dict[key] = [obj] - return dict + data_dict[key] = [obj] + return data_dict def create_subdict_or_update(indict, key, subdict): + """Create subdict or update.""" if key in indict: indict[key].update(subdict) else: @@ -371,36 +396,45 @@ def create_subdict_or_update(indict, key, subdict): def write_default_to_dict(indict, key, default_value): + """Write default to dict.""" if key not in indict: indict[key] = default_value def convert_str_to_pause_after_interval(start_time, input_str): + """Convert string to pause after interval.""" pause_time = str_to_pendulum_datetime(input_str) return pause_time - start_time def convert_unit_to_mega(unit): + """Convert unit to mega.""" return unit * 1e-6 def convert_unit_to_kilo(unit): + """Connvert unit to kilo.""" return unit * 1e-3 def convert_kilo_to_mega(unit_k): + """Convert kilo to mega.""" return unit_k * 1e-3 def convert_percent_to_ratio(unit_percent): + """Convert percentage to ratio.""" return unit_percent / 100 def short_offer_bid_log_str(offer_or_bid): + """Offer bid log string.""" return f"({{{offer_or_bid.id!s:.6s}}}: {offer_or_bid.energy} kWh)" +# pylint: disable=unspecified-encoding def export_default_settings_to_json_file(): + """Export default settings to json file.""" base_settings = { "sim_duration": f"{GlobalConfig.DURATION_D*24}h", "slot_length": f"{GlobalConfig.SLOT_LENGTH_M}m", @@ -415,23 +449,27 @@ def export_default_settings_to_json_file(): def area_sells_to_child(trade, area_name, child_names): + """Area sells to child.""" return ( area_name_from_area_or_ma_name(trade.seller) == area_name and area_name_from_area_or_ma_name(trade.buyer) in child_names) def child_buys_from_area(trade, area_name, child_names): + """Child buys from area.""" return ( area_name_from_area_or_ma_name(trade.buyer) == area_name and area_name_from_area_or_ma_name(trade.seller) in child_names) def if_not_in_list_append(target_list, obj): + """Append object if not already in list.""" if obj not in target_list: target_list.append(obj) def get_market_maker_rate_from_config(next_market, default_value=None, time_slot=None): + """Get market maker rate from config.""" if next_market is None: return default_value if isinstance(GlobalConfig.market_maker_rate, dict): @@ -443,21 +481,37 @@ def get_market_maker_rate_from_config(next_market, default_value=None, time_slot raise e return find_object_of_same_weekday_and_time(GlobalConfig.market_maker_rate, time_slot) - else: - return GlobalConfig.market_maker_rate + return GlobalConfig.market_maker_rate + + +def get_feed_in_tariff_rate_from_config(next_market: "MarketBase", time_slot=None): + """Get feed in tariff rate from config.""" + if next_market is None: + return 0. + if isinstance(GlobalConfig.FEED_IN_TARIFF, dict): + if time_slot is None: + time_slot = next_market.time_slot + assert time_slot, "time_slot parameter is missing to get feed-in tariff" + + return find_object_of_same_weekday_and_time(GlobalConfig.FEED_IN_TARIFF, + time_slot) or 0. + return GlobalConfig.FEED_IN_TARIFF def convert_area_throughput_kVA_to_kWh(transfer_capacity_kWA, slot_length): + """Convert area throughput frm kVA to kWh.""" return transfer_capacity_kWA * slot_length.total_minutes() / 60.0 \ if transfer_capacity_kWA is not None else 0. def get_simulation_queue_name(): + """Get simulation queue name.""" listen_to_cn = os.environ.get("LISTEN_TO_CANARY_NETWORK_REDIS_QUEUE", "no") == "yes" return "canary_network" if listen_to_cn else "exchange" class ExternalTickCounter: + """External tick counter.""" def __init__(self, ticks_per_slot: int, dispatch_frequency_percent: int): self._dispatch_tick_frequency = int( @@ -466,10 +520,12 @@ def __init__(self, ticks_per_slot: int, dispatch_frequency_percent: int): ) def is_it_time_for_external_tick(self, current_tick_in_slot: int) -> bool: + """Boolean return if time for external tick.""" return current_tick_in_slot % self._dispatch_tick_frequency == 0 def should_read_profile_from_db(profile_uuid): + """Boolean return if profile to be read from DB.""" return profile_uuid is not None and gsy_e.constants.CONNECT_TO_PROFILES_DB @@ -483,7 +539,6 @@ def is_external_matching_enabled(): class StrategyProfileConfigurationException(Exception): """Exception raised when neither a profile nor a profile_uuid are provided for a strategy.""" - pass def is_time_slot_in_past_markets(time_slot: DateTime, current_time_slot: DateTime): @@ -491,8 +546,7 @@ def is_time_slot_in_past_markets(time_slot: DateTime, current_time_slot: DateTim if ConstSettings.SettlementMarketSettings.ENABLE_SETTLEMENT_MARKETS: return (time_slot < current_time_slot.subtract( hours=ConstSettings.SettlementMarketSettings.MAX_AGE_SETTLEMENT_MARKET_HOURS)) - else: - return time_slot < current_time_slot + return time_slot < current_time_slot class FutureMarketCounter: diff --git a/src/gsy_e/models/strategy/infinite_bus.py b/src/gsy_e/models/strategy/infinite_bus.py index 8cac892f4..77207253e 100644 --- a/src/gsy_e/models/strategy/infinite_bus.py +++ b/src/gsy_e/models/strategy/infinite_bus.py @@ -30,7 +30,9 @@ from gsy_e.models.strategy.commercial_producer import CommercialStrategy +# pylint: disable=missing-class-docstring, too-many-instance-attributes, too-many-arguments class InfiniteBusStrategy(CommercialStrategy, BidEnabledStrategy): + """Implementation for infinite bus to participate in GSy Exchange.""" parameters = ("energy_sell_rate", "energy_rate_profile", "energy_buy_rate", "buying_rate_profile", "buying_rate_profile_uuid", "energy_rate_profile_uuid") @@ -71,6 +73,9 @@ def _set_global_market_maker_rate(self): elif self.energy_rate is not None: GlobalConfig.market_maker_rate = self.energy_rate + def _set_global_feed_in_tariff_rate(self): + GlobalConfig.FEED_IN_TARIFF = self.energy_buy_rate + def _read_or_rotate_profiles(self, reconfigure=False): if (self.energy_buy_rate_input is None and self.buying_rate_profile is None and @@ -104,12 +109,12 @@ def _read_or_rotate_profiles(self, reconfigure=False): profile_uuid=self.energy_rate_profile_uuid))) self._set_global_market_maker_rate() + self._set_global_feed_in_tariff_rate() def _populate_selling_rate(self): if self.energy_rate_profile is not None: self.energy_rate = read_arbitrary_profile(InputProfileTypes.IDENTITY, self.energy_rate_profile) - # TODO: to be checked via deleting in case increased memory is observed during runtime del self.energy_rate_profile elif self.energy_rate is not None: self.energy_rate = read_arbitrary_profile(InputProfileTypes.IDENTITY, @@ -121,7 +126,6 @@ def _populate_buying_rate(self): if self.buying_rate_profile is not None: self.energy_buy_rate = read_arbitrary_profile( InputProfileTypes.IDENTITY, self.buying_rate_profile) - # TODO: to be checked via deleting in case increased memory is observed during runtime del self.buying_rate_profile elif self.energy_buy_rate is not None: self.energy_buy_rate = read_arbitrary_profile( @@ -130,10 +134,12 @@ def _populate_buying_rate(self): self.energy_buy_rate = self.simulation_config.market_maker_rate def event_activate(self, **kwargs): + """Event activate.""" self._populate_selling_rate() self._populate_buying_rate() def buy_energy(self, market): + """Buy energy.""" for offer in market.sorted_offers: if offer.seller == self.owner.name: # Don't buy our own offer diff --git a/tests/strategies/test_strategy_infinite_bus.py b/tests/strategies/test_strategy_infinite_bus.py index 79ba529c5..a3f17c5cd 100644 --- a/tests/strategies/test_strategy_infinite_bus.py +++ b/tests/strategies/test_strategy_infinite_bus.py @@ -23,13 +23,13 @@ import pendulum import pytest from gsy_framework.constants_limits import ConstSettings, GlobalConfig +from gsy_framework.data_classes import Offer, Trade, BalancingOffer, Bid from gsy_e import constants from gsy_e.constants import TIME_ZONE from gsy_e.gsy_e_core.device_registry import DeviceRegistry from gsy_e.gsy_e_core.util import d3a_path from gsy_e.models.area import DEFAULT_CONFIG -from gsy_framework.data_classes import Offer, Trade, BalancingOffer, Bid from gsy_e.models.strategy.infinite_bus import InfiniteBusStrategy TIME = pendulum.today(tz=TIME_ZONE).at(hour=10, minute=45, second=0) @@ -46,11 +46,12 @@ def auto_fixture(): DeviceRegistry.REGISTRY = {} +# pylint: disable=too-many-instance-attributes class FakeArea: - def __init__(self, count): + def __init__(self): self.current_tick = 2 self.appliance = None - self.name = 'FakeArea' + self.name = "FakeArea" self.uuid = str(uuid4()) self.test_market = FakeMarket(0) self.test_balancing_market = FakeMarket(1) @@ -95,8 +96,8 @@ def __init__(self, count): self.count = count self.created_offers = [] self.created_balancing_offers = [] - self.sorted_offers = [Offer('id', pendulum.now(), 25., 1., 'other'), - Offer('id', pendulum.now(), 26., 1., 'other')] + self.sorted_offers = [Offer("id", pendulum.now(), 25., 1., "other"), + Offer("id", pendulum.now(), 26., 1., "other")] self.traded_offers = [] self._bids = {TIME: []} @@ -115,16 +116,16 @@ def offer(self, price, energy, seller, original_price=None, return offer def balancing_offer(self, price, energy, seller): - offer = BalancingOffer('id', pendulum.now(), price, energy, seller) + offer = BalancingOffer("id", pendulum.now(), price, energy, seller) self.created_balancing_offers.append(offer) - offer.id = 'id' + offer.id = "id" return offer def accept_offer(self, offer_or_id, buyer, *, energy=None, time=None, already_tracked=False, trade_rate: float = None, trade_bid_info=None, buyer_origin=None, buyer_origin_id=None, buyer_id=None): offer = offer_or_id - trade = Trade('trade_id', time, offer, offer.seller, buyer, + trade = Trade("trade_id", time, offer, offer.seller, buyer, seller_origin=offer.seller_origin, buyer_origin=buyer_origin, buyer_origin_id=buyer_origin_id, buyer_id=buyer_id) self.traded_offers.append(trade) @@ -139,13 +140,9 @@ def bid(self, price, energy, buyer, original_price=None, return bid -"""COPY of CEP tests below""" -"""TEST1""" - - @pytest.fixture() def area_test1(): - return FakeArea(0) + return FakeArea() @pytest.fixture() @@ -187,7 +184,7 @@ def test_balancing_offers_are_not_sent_to_all_markets_if_device_not_in_registry( def test_balancing_offers_are_sent_to_all_markets_if_device_in_registry(bus_test1, area_test1): ConstSettings.BalancingSettings.ENABLE_BALANCING_MARKET = True - DeviceRegistry.REGISTRY = {'FakeArea': (30, 40)} + DeviceRegistry.REGISTRY = {"FakeArea": (30, 40)} bus_test1.event_activate() bus_test1.event_market_cycle() assert len(area_test1.test_balancing_market.created_balancing_offers) == 1 @@ -223,12 +220,9 @@ def test_event_market_cycle_creates_balancing_offer_on_last_market_if_in_registr sys.maxsize * 50 -"""TEST2""" - - @pytest.fixture() def area_test2(): - return FakeArea(0) + return FakeArea() @pytest.fixture() @@ -259,11 +253,11 @@ def test_event_trade(area_test2, bus_test2): def test_on_offer_changed(area_test2, bus_test2): bus_test2.event_activate() original_offer = Offer( - id='id', creation_time=pendulum.now(), price=20, energy=1, seller='FakeArea') + id="id", creation_time=pendulum.now(), price=20, energy=1, seller="FakeArea") accepted_offer = Offer( - id='new', creation_time=pendulum.now(), price=15, energy=0.75, seller='FakeArea') - residual_offer = Offer(id='new_id', creation_time=pendulum.now(), price=5, - energy=0.25, seller='FakeArea') + id="new", creation_time=pendulum.now(), price=15, energy=0.75, seller="FakeArea") + residual_offer = Offer(id="new_id", creation_time=pendulum.now(), price=5, + energy=0.25, seller="FakeArea") bus_test2.event_offer_split(market_id=area_test2.test_market.id, original_offer=original_offer, accepted_offer=accepted_offer, @@ -309,15 +303,9 @@ def test_validate_posted_offers_get_updated_on_offer_energy_method(area_test2, b assert list(bus_test2.offers.posted.values())[0] == area_test2.test_market.id -"""COPY of CEP tests above""" - - -"""TEST3""" - - @pytest.fixture() def area_test3(): - return FakeArea(0) + return FakeArea() @pytest.fixture() @@ -336,9 +324,6 @@ def testing_event_market_cycle_post_offers(bus_test3, area_test3): assert area_test3.test_market.created_offers[-1].price == float(30 * sys.maxsize) -"""TEST4""" - - @pytest.fixture() def bus_test4(area_test1): c = InfiniteBusStrategy(energy_sell_rate=30, energy_buy_rate=25) @@ -370,9 +355,6 @@ def test_global_market_maker_rate_single_value(bus_test4): for v in GlobalConfig.market_maker_rate.values()) -"""TEST5""" - - @pytest.fixture() def bus_test5(area_test1): c = InfiniteBusStrategy( @@ -392,9 +374,6 @@ def test_global_market_maker_rate_profile_and_infinite_bus_selling_rate_profile( assert list(bus_test5.energy_rate.values())[-1] == 595.0 -"""TEST6""" - - @pytest.fixture() def bus_test6(area_test1): c = InfiniteBusStrategy( @@ -410,3 +389,8 @@ def test_infinite_bus_buying_rate_set_as_profile(bus_test6): assert len(bus_test6.energy_buy_rate) == 96 assert list(bus_test6.energy_buy_rate.values())[0] == 10 assert list(bus_test6.energy_buy_rate.values())[15] == 15 + + +def test_feed_in_tariff_set_as_infinite_bus_buying_rate(bus_test6): + bus_test6.event_activate() + assert GlobalConfig.FEED_IN_TARIFF == bus_test6.energy_buy_rate