From a7d44f69fdef47ba92521df83c500bd5155bf28b Mon Sep 17 00:00:00 2001 From: 1kastner Date: Sat, 9 Sep 2023 13:11:56 +0200 Subject: [PATCH] Fix time chaching of container (#190) * Drop fixed Sphinx version * explain why some variables are good names * elaborate on excluded patterns in documentation * drop cache_rsult from container.get_arrival_time and container.get_departure_time, add typehints for fields * Fix pylint issues * get_factor -> get_teu_factor --- .pylintrc | 27 ++++++------- conflowgen/domain_models/container.py | 40 ++++++++++--------- .../data_types/container_length.py | 8 +++- ...iner_dwell_time_distribution_repository.py | 6 ++- ...ontainer_length_distribution_repository.py | 3 +- .../factories/container_factory.py | 2 +- .../large_scheduled_vehicle_repository.py | 14 +++---- .../repositories/schedule_repository.py | 2 +- .../abstract_truck_for_containers_manager.py | 12 +++++- ...r_containers_delivered_by_truck_service.py | 4 +- ...hicle_for_onward_transportation_manager.py | 2 +- .../truck_for_export_containers_manager.py | 7 ++-- .../truck_for_import_containers_manager.py | 7 ++-- ...hicle_for_onward_transportation_manager.py | 18 ++++----- docs/conf.py | 7 +++- setup.py | 2 +- 16 files changed, 95 insertions(+), 66 deletions(-) diff --git a/.pylintrc b/.pylintrc index d8a9d089..2ec4e2d6 100644 --- a/.pylintrc +++ b/.pylintrc @@ -185,18 +185,17 @@ function-naming-style=snake_case #function-rgx= # Good variable names which should always be accepted, separated by a comma. -good-names=i, - j, - k, - ex, - Run, - _, - df, - ax, - x, - xs, - mu, - gs +good-names=i, # typical counter variable + j, # typical counter variable + k, # typical counter variable + _, # typical discard result indicator + df, # pandas DataFrame + ax, # matplotlib axis + gs, # matplotlib gridspec + x, # one element on the x axis + xs, # collection of elements on the x axis + mu, # mu of, e.g., a normal distribution + sd, # standard deviation of, e.g., a normal distribution # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted @@ -547,5 +546,5 @@ preferred-modules= # Exceptions that will emit a warning when being caught. Defaults to # "BaseException, Exception". -overgeneral-exceptions=BaseException, - Exception +overgeneral-exceptions=builtins.BaseException, + builtins.Exception diff --git a/conflowgen/domain_models/container.py b/conflowgen/domain_models/container.py index f5e6514b..043c9ad4 100644 --- a/conflowgen/domain_models/container.py +++ b/conflowgen/domain_models/container.py @@ -4,16 +4,16 @@ from peewee import ForeignKeyField from peewee import IntegerField -from conflowgen.data_summaries.data_summaries_cache import DataSummariesCache from .arrival_information import TruckArrivalInformationForDelivery, TruckArrivalInformationForPickup from .base_model import BaseModel -from .data_types.container_length import CONTAINER_LENGTH_TO_OCCUPIED_TEU +from .data_types.container_length import CONTAINER_LENGTH_TO_OCCUPIED_TEU, ContainerLength from .field_types.container_length import ContainerLengthField from .field_types.mode_of_transport import ModeOfTransportField from .field_types.storage_requirement import StorageRequirementField from .large_vehicle_schedule import Destination from .vehicle import LargeScheduledVehicle from .vehicle import Truck +from .data_types.storage_requirement import StorageRequirement from ..domain_models.data_types.mode_of_transport import ModeOfTransport @@ -35,78 +35,78 @@ def __init__(self, container, vehicle_type): class Container(BaseModel): """A representation of the physical container that is moved through the yard.""" id = AutoField() - weight = IntegerField( + weight: int = IntegerField( null=False, help_text="The weight of the container (approximated). This value should suit to the container weight " "distribution." ) - length = ContainerLengthField( + length: ContainerLength = ContainerLengthField( null=False, help_text="The length of the container in feet, typically 20' or 40' are used in international trade." ) - storage_requirement = StorageRequirementField( + storage_requirement: StorageRequirement = StorageRequirementField( null=False, help_text="Some containers must be stored separately, e.g. if they are reefers or dangerous goods containers." ) - delivered_by = ModeOfTransportField( + delivered_by: ModeOfTransport = ModeOfTransportField( null=False, help_text="This vehicle type delivers this container to the terminal. This helps to quickly pick the correct " "foreign key in the next step and is thus just additional information." ) - picked_up_by_initial = ModeOfTransportField( + picked_up_by_initial: ModeOfTransport = ModeOfTransportField( null=False, help_text="This vehicle type is first drawn randomly for picking up the container. It might be overwritten " "later because no vehicle satisfies the constraints, e.g. because all vehicles of that type arrive " "too early or too late or they are already full. Large deviations between `picked_up_by_initial` " "and `picked_up_by` might indicate calibration issues with the random distributions or schedules." ) - picked_up_by = ModeOfTransportField( + picked_up_by: ModeOfTransport = ModeOfTransportField( null=False, help_text="This vehicle type is later actually used for picking up the container. This helps to quickly pick " "the correct foreign key in the next step and is thus just additional information." ) - delivered_by_large_scheduled_vehicle = ForeignKeyField( + delivered_by_large_scheduled_vehicle: LargeScheduledVehicle = ForeignKeyField( LargeScheduledVehicle, null=True, help_text="Points at the large scheduled vehicle it is delivered by (null if truck). " "Any arrival information of the container is attached to that vehicle." ) - delivered_by_truck = ForeignKeyField( + delivered_by_truck: Truck = ForeignKeyField( Truck, null=True, help_text="Points at the truck it is delivered by (null if large scheduled vehicle). " "Any arrival information of the container is attached to that vehicle)." ) - picked_up_by_large_scheduled_vehicle = ForeignKeyField( + picked_up_by_large_scheduled_vehicle: LargeScheduledVehicle = ForeignKeyField( LargeScheduledVehicle, null=True, help_text="Points at the large scheduled vehicle it is picked up by (null if truck). " "Any departure information of the container is attached to that vehicle." ) - picked_up_by_truck = ForeignKeyField( + picked_up_by_truck: Truck = ForeignKeyField( Truck, null=True, help_text="Points at the truck it is picked up by (null if large scheduled vehicle). " "Any departure information of the container is attached to that vehicle." ) - destination = ForeignKeyField( + destination: Destination = ForeignKeyField( Destination, null=True, help_text="Points at the next destination of the container. Only applicable if picked up by a large scheduled " "vehicle. This information is sometimes used for better container stacking in the yard. For vessels, " "this can be regarded as a simplified stowage plan, likewise for trains and barges." ) - emergency_pickup = BooleanField( + emergency_pickup: bool = BooleanField( default=False, help_text="This indicates that no regular means of transport was available so that a vehicle had to be called " "explicitly to pick up the container so that the maximum dwell time is not exceeded." ) - cached_arrival_time = DateTimeField( + cached_arrival_time: datetime.datetime = DateTimeField( default=None, null=True, help_text="This field is used to cache the arrival time for faster evaluation of analyses." ) - cached_departure_time = DateTimeField( + cached_departure_time: datetime.datetime = DateTimeField( default=None, null=True, help_text="This field is used to cache the departure time for faster evaluation of analyses." @@ -116,9 +116,11 @@ class Container(BaseModel): def occupied_teu(self) -> float: return CONTAINER_LENGTH_TO_OCCUPIED_TEU[self.length] - @DataSummariesCache.cache_result def get_arrival_time(self) -> datetime.datetime: + if self.cached_arrival_time is not None: + return self.cached_arrival_time + container_arrival_time: datetime.datetime if self.delivered_by == ModeOfTransport.truck: # noinspection PyTypeChecker @@ -136,9 +138,11 @@ def get_arrival_time(self) -> datetime.datetime: self.save() return container_arrival_time - @DataSummariesCache.cache_result def get_departure_time(self) -> datetime.datetime: + if self.cached_departure_time is not None: + return self.cached_departure_time + container_departure_time: datetime.datetime if self.picked_up_by_truck is not None: # noinspection PyTypeChecker diff --git a/conflowgen/domain_models/data_types/container_length.py b/conflowgen/domain_models/data_types/container_length.py index 54106894..a90bbc94 100644 --- a/conflowgen/domain_models/data_types/container_length.py +++ b/conflowgen/domain_models/data_types/container_length.py @@ -20,7 +20,7 @@ class ContainerLength(enum.Enum): other = -1 # doc: Any other length usually does not fit into the standardized slots and handling processes. @classmethod - def get_factor(cls, container_length: ContainerLength) -> float: + def get_teu_factor(cls, container_length: ContainerLength) -> float: """ Each container occupies a certain amount of space when stored. This required space is measured in TEU. @@ -36,6 +36,10 @@ def get_factor(cls, container_length: ContainerLength) -> float: """ return CONTAINER_LENGTH_TO_OCCUPIED_TEU[container_length] + @classmethod + def get_maximum_teu_factor(cls) -> float: + return MAXIMUM_OCCUPIED_TEU + def __str__(self) -> str: """ The textual representation is, e.g., '20 feet' instead of '' so it is easier to @@ -79,3 +83,5 @@ def cast_element_type(cls, text: str) -> ContainerLength | None: The TEU factor for the value 'other' is chosen to be rather large because it is assumed to be difficult to find a proper storage position. """ + +MAXIMUM_OCCUPIED_TEU = max(list(CONTAINER_LENGTH_TO_OCCUPIED_TEU.values())) diff --git a/conflowgen/domain_models/distribution_repositories/container_dwell_time_distribution_repository.py b/conflowgen/domain_models/distribution_repositories/container_dwell_time_distribution_repository.py index 113b5688..485abfef 100644 --- a/conflowgen/domain_models/distribution_repositories/container_dwell_time_distribution_repository.py +++ b/conflowgen/domain_models/distribution_repositories/container_dwell_time_distribution_repository.py @@ -10,6 +10,10 @@ from conflowgen.tools.continuous_distribution import ContinuousDistribution +class ContainerDwellTimeCouldNotBeCastedException(Exception): + pass + + class ContainerDwellTimeDistributionRepository: @staticmethod @@ -68,7 +72,7 @@ def set_distributions( elif isinstance(container_dwell_time_distribution, dict): distribution_properties = container_dwell_time_distribution else: - raise Exception( + raise ContainerDwellTimeCouldNotBeCastedException( f"The container dwell time distribution representation " f"'{container_dwell_time_distribution}' could not be casted." ) diff --git a/conflowgen/domain_models/distribution_repositories/container_length_distribution_repository.py b/conflowgen/domain_models/distribution_repositories/container_length_distribution_repository.py index b70d26ec..3bcd1f9f 100644 --- a/conflowgen/domain_models/distribution_repositories/container_length_distribution_repository.py +++ b/conflowgen/domain_models/distribution_repositories/container_length_distribution_repository.py @@ -63,5 +63,6 @@ def get_teu_factor(cls) -> float: container_length_weighted_average = 0.0 container_length_distribution = cls.get_distribution() for container_length, fraction in container_length_distribution.items(): - container_length_weighted_average += ContainerLength.get_factor(container_length) * fraction + container_length_weighted_average += ContainerLength.get_teu_factor(container_length) * fraction + assert 0 < container_length_weighted_average < ContainerLength.get_maximum_teu_factor() return container_length_weighted_average diff --git a/conflowgen/domain_models/factories/container_factory.py b/conflowgen/domain_models/factories/container_factory.py index 8e01e954..4b35cff2 100644 --- a/conflowgen/domain_models/factories/container_factory.py +++ b/conflowgen/domain_models/factories/container_factory.py @@ -26,7 +26,7 @@ class ContainerFactory: Creates containers according to the distributions which are either hard-coded or stored in the database. """ - ignored_capacity = ContainerLength.get_factor(ContainerLength.other) + ignored_capacity = ContainerLength.get_teu_factor(ContainerLength.other) random_seed = 1 diff --git a/conflowgen/domain_models/repositories/large_scheduled_vehicle_repository.py b/conflowgen/domain_models/repositories/large_scheduled_vehicle_repository.py index 933c1fec..05563689 100644 --- a/conflowgen/domain_models/repositories/large_scheduled_vehicle_repository.py +++ b/conflowgen/domain_models/repositories/large_scheduled_vehicle_repository.py @@ -9,7 +9,7 @@ class LargeScheduledVehicleRepository: - ignored_capacity = ContainerLength.get_factor(ContainerLength.other) + ignored_capacity = ContainerLength.get_teu_factor(ContainerLength.other) def __init__(self): self.transportation_buffer = None @@ -44,7 +44,7 @@ def block_capacity_for_inbound_journey( # calculate new free capacity free_capacity_in_teu = self.free_capacity_for_inbound_journey_buffer[vehicle] - used_capacity_in_teu = ContainerLength.get_factor(container_length=container.length) + used_capacity_in_teu = ContainerLength.get_teu_factor(container_length=container.length) new_free_capacity_in_teu = free_capacity_in_teu - used_capacity_in_teu assert new_free_capacity_in_teu >= 0, f"vehicle {vehicle} is overloaded, " \ f"free_capacity_in_teu: {free_capacity_in_teu}, " \ @@ -65,7 +65,7 @@ def block_capacity_for_outbound_journey( # calculate new free capacity free_capacity_in_teu = self.free_capacity_for_outbound_journey_buffer[vehicle] - used_capacity_in_teu = ContainerLength.get_factor(container_length=container.length) + used_capacity_in_teu = ContainerLength.get_teu_factor(container_length=container.length) new_free_capacity_in_teu = free_capacity_in_teu - used_capacity_in_teu assert new_free_capacity_in_teu >= 0, f"vehicle {vehicle} is overloaded, " \ f"free_capacity_in_teu: {free_capacity_in_teu}, " \ @@ -133,10 +133,10 @@ def _get_free_capacity_in_teu( loaded_other_containers = container_counter(vehicle, ContainerLength.other) free_capacity_in_teu = ( maximum_capacity - - loaded_20_foot_containers * ContainerLength.get_factor(ContainerLength.twenty_feet) - - loaded_40_foot_containers * ContainerLength.get_factor(ContainerLength.forty_feet) - - loaded_45_foot_containers * ContainerLength.get_factor(ContainerLength.forty_five_feet) - - loaded_other_containers * ContainerLength.get_factor(ContainerLength.other) + - loaded_20_foot_containers * ContainerLength.get_teu_factor(ContainerLength.twenty_feet) + - loaded_40_foot_containers * ContainerLength.get_teu_factor(ContainerLength.forty_feet) + - loaded_45_foot_containers * ContainerLength.get_teu_factor(ContainerLength.forty_five_feet) + - loaded_other_containers * ContainerLength.get_teu_factor(ContainerLength.other) ) vehicle_name = vehicle.large_scheduled_vehicle.vehicle_name assert free_capacity_in_teu >= 0, f"vehicle {vehicle} of type {vehicle.get_mode_of_transport()} with the " \ diff --git a/conflowgen/domain_models/repositories/schedule_repository.py b/conflowgen/domain_models/repositories/schedule_repository.py index 53b93b4e..b45382a3 100644 --- a/conflowgen/domain_models/repositories/schedule_repository.py +++ b/conflowgen/domain_models/repositories/schedule_repository.py @@ -41,7 +41,7 @@ def get_departing_vehicles( ) # Check for each of the vehicles how much it has already loaded - required_capacity_in_teu = ContainerLength.get_factor(required_capacity) + required_capacity_in_teu = ContainerLength.get_teu_factor(required_capacity) vehicles_with_sufficient_capacity = [] vehicle: Type[AbstractLargeScheduledVehicle] for vehicle in vehicles: diff --git a/conflowgen/flow_generator/abstract_truck_for_containers_manager.py b/conflowgen/flow_generator/abstract_truck_for_containers_manager.py index 84052a97..1d2483e1 100644 --- a/conflowgen/flow_generator/abstract_truck_for_containers_manager.py +++ b/conflowgen/flow_generator/abstract_truck_for_containers_manager.py @@ -17,6 +17,14 @@ from ..tools.continuous_distribution import ContinuousDistribution, multiply_discretized_probability_densities +class SumOfProbabilitiesDoesNotEqualOneException(Exception): + pass + + +class UnknownDistributionPropertyException(Exception): + pass + + class AbstractTruckForContainersManager(abc.ABC): def __init__(self): self.logger = logging.getLogger("conflowgen") @@ -128,7 +136,7 @@ def _get_time_window_of_truck_arrival( ) if sum(total_probabilities) == 0: # bad circumstances, no slot available - raise Exception( + raise SumOfProbabilitiesDoesNotEqualOneException( f"No truck slots available! {truck_arrival_probabilities} and {total_probabilities} just do not match." ) @@ -142,7 +150,7 @@ def _get_time_window_of_truck_arrival( elif _debug_check_distribution_property == "average": selected_time_window = int(round(container_dwell_time_distribution.average)) else: - raise Exception(f"Unknown: {_debug_check_distribution_property}") + raise UnknownDistributionPropertyException(_debug_check_distribution_property) else: selected_time_window = random.choices( population=time_windows_for_truck_arrival, diff --git a/conflowgen/flow_generator/allocate_space_for_containers_delivered_by_truck_service.py b/conflowgen/flow_generator/allocate_space_for_containers_delivered_by_truck_service.py index 8c4b064d..322e4dc7 100644 --- a/conflowgen/flow_generator/allocate_space_for_containers_delivered_by_truck_service.py +++ b/conflowgen/flow_generator/allocate_space_for_containers_delivered_by_truck_service.py @@ -15,7 +15,7 @@ class AllocateSpaceForContainersDeliveredByTruckService: - ignored_capacity = ContainerLength.get_factor(ContainerLength.other) + ignored_capacity = ContainerLength.get_teu_factor(ContainerLength.other) def __init__(self): self.logger = logging.getLogger("conflowgen") @@ -131,7 +131,7 @@ def allocate(self) -> None: continue # try again (possibly new vehicle type, definitely not same vehicle again) container = self.container_factory.create_container_for_delivering_truck(vehicle) - teu_total += ContainerLength.get_factor(container.length) + teu_total += ContainerLength.get_teu_factor(container.length) self.large_scheduled_vehicle_repository.block_capacity_for_outbound_journey(vehicle, container) successful_assignment += 1 break # success, no further looping to search for a suitable vehicle diff --git a/conflowgen/flow_generator/large_scheduled_vehicle_for_onward_transportation_manager.py b/conflowgen/flow_generator/large_scheduled_vehicle_for_onward_transportation_manager.py index 8a5e6888..b18b995c 100644 --- a/conflowgen/flow_generator/large_scheduled_vehicle_for_onward_transportation_manager.py +++ b/conflowgen/flow_generator/large_scheduled_vehicle_for_onward_transportation_manager.py @@ -195,7 +195,7 @@ def _draw_vehicle( vehicles_and_their_respective_free_capacity = {} for vehicle in available_vehicles: free_capacity = self.large_scheduled_vehicle_repository.get_free_capacity_for_outbound_journey(vehicle) - if free_capacity >= ContainerLength.get_factor(ContainerLength.other): + if free_capacity >= ContainerLength.get_teu_factor(ContainerLength.other): vehicles_and_their_respective_free_capacity[vehicle] = free_capacity if len(available_vehicles) == 0: diff --git a/conflowgen/flow_generator/truck_for_export_containers_manager.py b/conflowgen/flow_generator/truck_for_export_containers_manager.py index 140a3188..2d89aab6 100644 --- a/conflowgen/flow_generator/truck_for_export_containers_manager.py +++ b/conflowgen/flow_generator/truck_for_export_containers_manager.py @@ -3,7 +3,8 @@ import random from typing import Dict, Optional -from .abstract_truck_for_containers_manager import AbstractTruckForContainersManager +from .abstract_truck_for_containers_manager import AbstractTruckForContainersManager, \ + UnknownDistributionPropertyException from ..domain_models.data_types.container_length import ContainerLength from ..domain_models.data_types.storage_requirement import StorageRequirement from ..domain_models.arrival_information import TruckArrivalInformationForDelivery @@ -85,7 +86,7 @@ def _get_container_delivery_time( elif _debug_check_distribution_property == "average": random_time_component = 0 else: - raise Exception(f"Unknown: {_debug_check_distribution_property}") + raise UnknownDistributionPropertyException(f"Unknown: {_debug_check_distribution_property}") truck_arrival_time = ( # go back to the earliest time window @@ -143,6 +144,6 @@ def generate_trucks_for_delivering(self) -> None: ) container.delivered_by_truck = truck container.save() - teu_total += ContainerLength.get_factor(container.length) + teu_total += ContainerLength.get_teu_factor(container.length) self.logger.info(f"All {number_containers} trucks that deliver a container are created now, moving " f"{teu_total} TEU.") diff --git a/conflowgen/flow_generator/truck_for_import_containers_manager.py b/conflowgen/flow_generator/truck_for_import_containers_manager.py index 13bdaa0c..94d2b0ca 100644 --- a/conflowgen/flow_generator/truck_for_import_containers_manager.py +++ b/conflowgen/flow_generator/truck_for_import_containers_manager.py @@ -2,7 +2,8 @@ import random from typing import Dict, Optional -from .abstract_truck_for_containers_manager import AbstractTruckForContainersManager +from .abstract_truck_for_containers_manager import AbstractTruckForContainersManager, \ + UnknownDistributionPropertyException from ..domain_models.data_types.container_length import ContainerLength from ..domain_models.data_types.storage_requirement import StorageRequirement from ..domain_models.arrival_information import TruckArrivalInformationForPickup @@ -67,7 +68,7 @@ def _get_container_pickup_time( elif _debug_check_distribution_property == "average": random_time_component = 1 else: - raise Exception(f"Unknown: {_debug_check_distribution_property}") + raise UnknownDistributionPropertyException(f"Unknown: {_debug_check_distribution_property}") truck_arrival_time = ( container_arrival_time.replace(minute=0, second=0, microsecond=0) @@ -121,6 +122,6 @@ def generate_trucks_for_picking_up(self): ) container.picked_up_by_truck = truck container.save() - teu_total += ContainerLength.get_factor(container.length) + teu_total += ContainerLength.get_teu_factor(container.length) self.logger.info(f"All {number_containers} trucks that pick up a container have been generated, moving " f"{teu_total} TEU.") diff --git a/conflowgen/tests/flow_generator/test_large_scheduled_vehicle_for_onward_transportation_manager.py b/conflowgen/tests/flow_generator/test_large_scheduled_vehicle_for_onward_transportation_manager.py index dd02630a..05bdadb4 100644 --- a/conflowgen/tests/flow_generator/test_large_scheduled_vehicle_for_onward_transportation_manager.py +++ b/conflowgen/tests/flow_generator/test_large_scheduled_vehicle_for_onward_transportation_manager.py @@ -171,7 +171,7 @@ def test_do_not_overload_feeder_with_truck_traffic(self): feeder.large_scheduled_vehicle.moved_capacity = 10 # in TEU containers = [self._create_container_for_truck(truck) for _ in range(10)] self.assertEqual(Container.select().count(), 10) - teu_generated = sum((ContainerLength.get_factor(container.length) for container in containers)) + teu_generated = sum((ContainerLength.get_teu_factor(container.length) for container in containers)) self.assertGreaterEqual(teu_generated, 10, "Generating 10 containers with each at least 1 TEU must result in a " "total TEU of more than 10 TEU") @@ -185,7 +185,7 @@ def test_do_not_overload_feeder_with_truck_traffic(self): teu_loaded = 0 for container in containers_reloaded: # pylint: disable=E1133 self.assertEqual(container.picked_up_by_large_scheduled_vehicle, feeder.large_scheduled_vehicle) - teu_loaded += ContainerLength.get_factor(container.length) + teu_loaded += ContainerLength.get_teu_factor(container.length) self.assertLessEqual(teu_loaded, 10, "Feeder must not be loaded with more than 10 TEU") def test_do_not_overload_feeder_with_train_traffic(self): @@ -200,7 +200,7 @@ def test_do_not_overload_feeder_with_train_traffic(self): feeder.save() self.assertEqual(Container.select().count(), 90) - teu_generated = sum((ContainerLength.get_factor(container.length) for container in containers)) + teu_generated = sum((ContainerLength.get_teu_factor(container.length) for container in containers)) self.assertEqual(teu_generated, 90) self.manager.choose_departing_vehicle_for_containers() @@ -213,7 +213,7 @@ def test_do_not_overload_feeder_with_train_traffic(self): teu_loaded = 0 for container in containers_reloaded: # pylint: disable=not-an-iterable self.assertEqual(container.picked_up_by_large_scheduled_vehicle, feeder.large_scheduled_vehicle) - teu_loaded += ContainerLength.get_factor(container.length) + teu_loaded += ContainerLength.get_teu_factor(container.length) self.assertLessEqual(teu_loaded, 80, "Feeder must not be loaded with more than what it can carry") def test_do_not_load_if_the_time_span_is_too_long(self): @@ -228,7 +228,7 @@ def test_do_not_load_if_the_time_span_is_too_long(self): feeder.save() self.assertEqual(Container.select().count(), 90) - teu_generated = sum((ContainerLength.get_factor(container.length) for container in containers)) + teu_generated = sum((ContainerLength.get_teu_factor(container.length) for container in containers)) self.assertEqual(teu_generated, 90) self.manager.choose_departing_vehicle_for_containers() @@ -256,7 +256,7 @@ def test_do_not_overload_feeder_with_train_traffic_of_two_vehicles(self): feeder.save() self.assertEqual(Container.select().count(), 180) - teu_generated = sum((ContainerLength.get_factor(container.length) for container in containers)) + teu_generated = sum((ContainerLength.get_teu_factor(container.length) for container in containers)) self.assertEqual(teu_generated, 180) self.manager.choose_departing_vehicle_for_containers() @@ -269,7 +269,7 @@ def test_do_not_overload_feeder_with_train_traffic_of_two_vehicles(self): teu_loaded = 0 for container in containers_reloaded: # pylint: disable=not-an-iterable self.assertEqual(container.picked_up_by_large_scheduled_vehicle, feeder.large_scheduled_vehicle) - teu_loaded += ContainerLength.get_factor(container.length) + teu_loaded += ContainerLength.get_teu_factor(container.length) self.assertLessEqual(teu_loaded, 80, "Feeder must not be loaded with more than what it can carry") def test_do_not_overload_feeder_with_train_traffic_of_two_vehicles_and_changing_container_lengths(self): @@ -293,7 +293,7 @@ def test_do_not_overload_feeder_with_train_traffic_of_two_vehicles_and_changing_ feeder.save() self.assertEqual(Container.select().count(), 180) - teu_generated = sum((ContainerLength.get_factor(container.length) for container in containers)) + teu_generated = sum((ContainerLength.get_teu_factor(container.length) for container in containers)) self.assertEqual(teu_generated, 270) self.manager.choose_departing_vehicle_for_containers() @@ -306,7 +306,7 @@ def test_do_not_overload_feeder_with_train_traffic_of_two_vehicles_and_changing_ teu_loaded = 0 for container in containers_reloaded: # pylint: disable=not-an-iterable self.assertEqual(container.picked_up_by_large_scheduled_vehicle, feeder.large_scheduled_vehicle) - teu_loaded += ContainerLength.get_factor(container.length) + teu_loaded += ContainerLength.get_teu_factor(container.length) self.assertLessEqual(teu_loaded, 80, "Feeder must not be loaded with more than what it can carry") def test_nothing_to_do(self): diff --git a/docs/conf.py b/docs/conf.py index ba2ab937..acf44758 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -67,7 +67,12 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.tools'] +exclude_patterns = [ + 'Thumbs.db', '.DS_Store', # OS-specific + '_build', # Sphinx-specific + '.tools', # project-specific + '.ipynb_checkpoints', '.virtual_documents' # specific for Jupyter Notebooks +] add_module_names = False diff --git a/setup.py b/setup.py index 07ef852a..3d70c443 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ 'nbconvert', # build documentation - 'sphinx==7.1.2', # build the documentation + 'sphinx', # build the documentation 'sphinx-rtd-theme', # adding the nice sphinx theme 'sphinx-toolbox', # dependency of enum_tools, we got this as a present 'myst-parser', # for Contributing.md