diff --git a/pyproject.toml b/pyproject.toml index 4a5517b..e105c0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ build-backend = "poetry.core.masonry.api" disable = [ "missing-module-docstring", ] -good-names = ["i", "j", "k", "x", "y", "z", "ds", "dt", "ax"] +good-names = ["i", "j", "k", "x", "y", "z", "u", "v", "w", "ds", "dt", "ax"] [tool.pylint.design] max-args = 10 # maximum number of arguments for function / method @@ -90,7 +90,16 @@ max-args = 10 "tests/*.py" = [ "D", # pydocstyle "PT009", # pytest-unittest-assertion + "PT027", # pytest-unittest-raises-assertion "INP001", # implicit-namespace-package + "ANN201", # missing-return-type-undocumented-public-function + "S311", # suspicious-non-cryptographic-random-usage +] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "if TYPE_CHECKING:", ] [tool.tox] diff --git a/src/arcade_collection/input/generate_setup_file.py b/src/arcade_collection/input/generate_setup_file.py index 68e5ed1..669196a 100644 --- a/src/arcade_collection/input/generate_setup_file.py +++ b/src/arcade_collection/input/generate_setup_file.py @@ -99,7 +99,7 @@ def make_setup_file( Contents of ARCADE setup file. """ - root = ET.fromstring("") + root = ET.fromstring("") # noqa: S314 series = ET.SubElement( root, "series", diff --git a/src/arcade_collection/output/convert_model_units.py b/src/arcade_collection/output/convert_model_units.py index 590ec28..e3eab5d 100644 --- a/src/arcade_collection/output/convert_model_units.py +++ b/src/arcade_collection/output/convert_model_units.py @@ -1,17 +1,20 @@ +from __future__ import annotations + import re -from typing import Optional, Union +from typing import TYPE_CHECKING -import pandas as pd +if TYPE_CHECKING: + import pandas as pd def convert_model_units( data: pd.DataFrame, - ds: Optional[float], - dt: Optional[float], - regions: Optional[Union[list[str], str]] = None, + ds: float | None, + dt: float | None, + regions: list[str] | str | None = None, ) -> None: """ - Converts data from simulation units to true units. + Convert data from simulation units to true units. Simulations use spatial unit of voxels and temporal unit of ticks. Spatial resolution (microns/voxel) and temporal resolution (hours/tick) are used to @@ -87,7 +90,7 @@ def convert_model_units( def convert_temporal_units(data: pd.DataFrame, dt: float) -> None: """ - Converts temporal data from simulation units to true units. + Convert temporal data from simulation units to true units. Simulations use temporal unit of ticks. Temporal resolution (hours/tick) is used to convert data to true units. @@ -112,9 +115,9 @@ def convert_temporal_units(data: pd.DataFrame, dt: float) -> None: data["time"] = round(dt * data["TICK"], 2) -def convert_spatial_units(data: pd.DataFrame, ds: float, region: Optional[str] = None) -> None: +def convert_spatial_units(data: pd.DataFrame, ds: float, region: str | None = None) -> None: """ - Converts spatial data from simulation units to true units. + Convert spatial data from simulation units to true units. Simulations use spatial unit of voxels. Spatial resolution (microns/voxel) is used to convert data to true units. @@ -183,7 +186,7 @@ def convert_spatial_units(data: pd.DataFrame, ds: float, region: Optional[str] = def estimate_temporal_resolution(key: str) -> float: """ - Estimates temporal resolution based on condition key. + Estimate temporal resolution based on condition key. If the key contains ``DT##``, where ``##`` denotes the temporal resolution in minutes/tick, temporal resolution is estimated from ``##``. Otherwise, @@ -206,7 +209,7 @@ def estimate_temporal_resolution(key: str) -> float: def estimate_spatial_resolution(key: str) -> float: """ - Estimates spatial resolution based on condition key. + Estimate spatial resolution based on condition key. If the key contains ``DS##``, where ``##`` denotes the spatial resolution in micron/voxel, spatial resolution is estimated from ``##``. Otherwise, diff --git a/src/arcade_collection/output/extract_tick_json.py b/src/arcade_collection/output/extract_tick_json.py index f44842c..8051c2a 100644 --- a/src/arcade_collection/output/extract_tick_json.py +++ b/src/arcade_collection/output/extract_tick_json.py @@ -1,16 +1,20 @@ +from __future__ import annotations + import json -import tarfile -from typing import Optional, Union +from typing import TYPE_CHECKING import numpy as np +if TYPE_CHECKING: + import tarfile + def extract_tick_json( tar: tarfile.TarFile, key: str, - tick: Union[int, float], - extension: Optional[str] = None, - field: Optional[str] = None, + tick: float, + extension: str | None = None, + field: str | None = None, ) -> list: """ Extract json for specified tick from tar archive. @@ -60,7 +64,10 @@ def extract_tick_json( else: member = tar.extractfile(f"{key}{formatted_tick}.{extension}.json") - assert member is not None + if member is None: + message = "File does not exist in archive." + raise RuntimeError(message) + tick_json = json.loads(member.read().decode("utf-8")) if isinstance(tick, float): diff --git a/src/arcade_collection/output/get_location_voxels.py b/src/arcade_collection/output/get_location_voxels.py index f9e2f0c..878d9a3 100644 --- a/src/arcade_collection/output/get_location_voxels.py +++ b/src/arcade_collection/output/get_location_voxels.py @@ -1,7 +1,7 @@ -from typing import Optional +from __future__ import annotations -def get_location_voxels(location: dict, region: Optional[str] = None) -> list[tuple[int, int, int]]: +def get_location_voxels(location: dict, region: str | None = None) -> list[tuple[int, int, int]]: """ Get list of voxels from location for specified region. @@ -22,11 +22,9 @@ def get_location_voxels(location: dict, region: Optional[str] = None) -> list[tu List of x, y, z voxels. """ - voxels = [ + return [ (x, y, z) for loc in location["location"] for x, y, z in loc["voxels"] if not region or loc["region"] == region ] - - return voxels diff --git a/src/arcade_collection/output/parse_growth_file.py b/src/arcade_collection/output/parse_growth_file.py index 8d329b9..1a70e42 100644 --- a/src/arcade_collection/output/parse_growth_file.py +++ b/src/arcade_collection/output/parse_growth_file.py @@ -61,9 +61,7 @@ def parse_growth_file(tar: tarfile.TarFile) -> pd.DataFrame: ] ) - timepoints_df = pd.DataFrame(all_timepoints, columns=GROWTH_COLUMNS) - - return timepoints_df + return pd.DataFrame(all_timepoints, columns=GROWTH_COLUMNS) def parse_growth_timepoint(data: dict, seed: int) -> list: @@ -110,8 +108,10 @@ def parse_growth_timepoint(data: dict, seed: int) -> list: Parameters ---------- - timepoint + data Original simulation data. + seed + Random seed. Returns ------- @@ -123,23 +123,14 @@ def parse_growth_timepoint(data: dict, seed: int) -> list: time = data["time"] for location, cells in data["cells"]: - u, v, w, z = location - for cell in cells: _, population, state, position, volume, cycles = cell - - if len(cycles) == 0: - cycle = None - else: - cycle = np.mean(cycles) + cycle = None if len(cycles) == 0 else np.mean(cycles) data_list = [ time, seed, - u, - v, - w, - z, + *location, position, population, CELL_STATES[state], diff --git a/src/arcade_collection/output/parse_locations_file.py b/src/arcade_collection/output/parse_locations_file.py index f5d3355..4457a2c 100644 --- a/src/arcade_collection/output/parse_locations_file.py +++ b/src/arcade_collection/output/parse_locations_file.py @@ -60,7 +60,7 @@ def parse_locations_file(tar: tarfile.TarFile, regions: list[str]) -> pd.DataFra return pd.DataFrame(all_locations, columns=columns) -def parse_location_tick(tick: int, locations: dict, regions: list[str]) -> list: +def parse_location_tick(tick: int, location: dict, regions: list[str]) -> list: """ Parse location data for a single simulation tick. @@ -105,7 +105,7 @@ def parse_location_tick(tick: int, locations: dict, regions: list[str]) -> list: ---------- tick Simulation tick. - loc + location Original location data. regions List of regions. @@ -116,31 +116,31 @@ def parse_location_tick(tick: int, locations: dict, regions: list[str]) -> list: Parsed location data. """ - if "center" in locations: - voxels = np.array([voxel for region in locations["location"] for voxel in region["voxels"]]) + if "center" in location: + voxels = np.array([voxel for region in location["location"] for voxel in region["voxels"]]) mins = np.min(voxels, axis=0) maxs = np.max(voxels, axis=0) - parsed = [locations["id"], tick, *locations["center"], *mins, *maxs] + parsed = [location["id"], tick, *location["center"], *mins, *maxs] else: - parsed = [locations["id"], tick, -1, -1, -1, -1, -1, -1, -1, -1, -1] + parsed = [location["id"], tick, -1, -1, -1, -1, -1, -1, -1, -1, -1] for reg in regions: region_voxels = np.array( [ voxel - for region in locations["location"] + for region in location["location"] for voxel in region["voxels"] if region["region"] == reg ] ) if len(region_voxels) == 0: - parsed = parsed + [-1, -1, -1, -1, -1, -1, -1, -1, -1] + parsed = [*parsed, -1, -1, -1, -1, -1, -1, -1, -1, -1] continue center = [int(value + 0.5) for value in region_voxels.mean(axis=0)] mins = np.min(region_voxels, axis=0) maxs = np.max(region_voxels, axis=0) - parsed = parsed + [*center, *mins, *maxs] + parsed = [*parsed, *center, *mins, *maxs] return parsed diff --git a/tests/arcade_collection/input/test_convert_to_cells_file.py b/tests/arcade_collection/input/test_convert_to_cells_file.py index f029d2a..3c31c5e 100644 --- a/tests/arcade_collection/input/test_convert_to_cells_file.py +++ b/tests/arcade_collection/input/test_convert_to_cells_file.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest import numpy as np @@ -16,7 +18,7 @@ DEFAULT_REGION_NAME = "DEFAULT" -def make_samples(cell_id, volume, height, region): +def make_samples(cell_id: int, volume: int, height: int, region: str | None): return pd.DataFrame( { "id": [cell_id] * volume, diff --git a/tests/arcade_collection/output/test_convert_model_units.py b/tests/arcade_collection/output/test_convert_model_units.py index ed1a266..17c00cc 100644 --- a/tests/arcade_collection/output/test_convert_model_units.py +++ b/tests/arcade_collection/output/test_convert_model_units.py @@ -14,18 +14,21 @@ class TestConvertModelUnits(unittest.TestCase): + def setUp(self): + self.rng = np.random.default_rng() + def test_convert_model_units_no_estimate_no_regions(self): dt = 1.0 / 3 ds = 1.0 / 7 regions = None - ticks = np.random.randint(100, size=10) - voxels = np.random.randint(100, size=10) - center = np.random.randint(100, size=(10, 3)) - z = np.random.randint(100, size=(10, 2)) + ticks = self.rng.integers(100, size=10) + voxels = self.rng.integers(100, size=10) + center = self.rng.integers(100, size=(10, 3)) + z = self.rng.integers(100, size=(10, 2)) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "TICK": ticks, "NUM_VOXELS": voxels, "CENTER_X": center[:, 0], @@ -52,20 +55,20 @@ def test_convert_model_units_with_estimate_no_regions(self): dt = None ds = None regions = None - ticks = np.random.randint(100, size=10) - voxels = np.random.randint(100, size=10) - center = np.random.randint(100, size=(10, 3)) - z = np.random.randint(100, size=(10, 2)) + ticks = self.rng.integers(100, size=10) + voxels = self.rng.integers(100, size=10) + center = self.rng.integers(100, size=(10, 3)) + z = self.rng.integers(100, size=(10, 2)) - all_dt = np.random.randint(1, 10, size=10) - all_ds = np.random.randint(1, 10, size=10) + all_dt = self.rng.integers(1, 10, size=10) + all_ds = self.rng.integers(1, 10, size=10) dt = all_dt / 60 ds = all_ds.astype("float") data = pd.DataFrame( { "KEY": [f"DT{dt:03d}_DS{ds:03d}" for dt, ds in zip(all_dt, all_ds)], - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "TICK": ticks, "NUM_VOXELS": voxels, "CENTER_X": center[:, 0], @@ -92,13 +95,13 @@ def test_convert_model_units_no_estimate_single_region(self): dt = 1.0 / 3 ds = 1.0 / 7 regions = "REGION" - ticks = np.random.randint(100, size=10) - voxels = np.random.randint(100, size=10) - region_voxels = np.random.randint(100, size=10) + ticks = self.rng.integers(100, size=10) + voxels = self.rng.integers(100, size=10) + region_voxels = self.rng.integers(100, size=10) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "TICK": ticks, "NUM_VOXELS": voxels, f"NUM_VOXELS.{regions}": region_voxels, @@ -118,13 +121,13 @@ def test_convert_model_units_no_estimate_multiple_regions(self): dt = 1.0 / 3 ds = 1.0 / 7 regions = ["DEFAULT", "REGION_A", "REGION_B"] - ticks = np.random.randint(100, size=10) - voxels = np.random.randint(100, size=10) - region_voxels = np.random.randint(100, size=(10, 2)) + ticks = self.rng.integers(100, size=10) + voxels = self.rng.integers(100, size=10) + region_voxels = self.rng.integers(100, size=(10, 2)) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "TICK": ticks, "NUM_VOXELS": voxels, f"NUM_VOXELS.{regions[1]}": region_voxels[:, 0], @@ -147,7 +150,7 @@ def test_convert_temporal_units_no_columns(self): data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), } ) @@ -159,11 +162,11 @@ def test_convert_temporal_units_no_columns(self): def test_convert_temporal_units_with_columns(self): dt = 1.0 / 3 - ticks = np.random.randint(100, size=10) + ticks = self.rng.integers(100, size=10) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "TICK": ticks, } ) @@ -181,7 +184,7 @@ def test_convert_spatial_units_no_columns(self): data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), } ) @@ -194,13 +197,13 @@ def test_convert_spatial_units_no_columns(self): def test_convert_spatial_units_with_columns_no_region_no_properties(self): ds = 1.0 / 3 region = None - voxels = np.random.randint(100, size=10) - center = np.random.randint(100, size=(10, 3)) - z = np.random.randint(100, size=(10, 2)) + voxels = self.rng.integers(100, size=10) + center = self.rng.integers(100, size=(10, 3)) + z = self.rng.integers(100, size=(10, 2)) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "NUM_VOXELS": voxels, "CENTER_X": center[:, 0], "CENTER_Y": center[:, 1], @@ -224,14 +227,14 @@ def test_convert_spatial_units_with_columns_no_region_no_properties(self): def test_convert_spatial_units_with_columns_no_region_with_properties(self): ds = 1.0 / 3 region = None - area = np.random.rand(10) - perimeter = np.random.rand(10) - axis_major_length = np.random.rand(10) - axis_minor_length = np.random.rand(10) + area = self.rng.random(10) + perimeter = self.rng.random(10) + axis_major_length = self.rng.random(10) + axis_minor_length = self.rng.random(10) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), + "PLACEHOLDER": self.rng.random(10), "area": area, "perimeter": perimeter, "axis_major_length": axis_major_length, @@ -252,19 +255,19 @@ def test_convert_spatial_units_with_columns_no_region_with_properties(self): def test_convert_spatial_units_with_columns_with_region_no_properties(self): ds = 1.0 / 3 region = "REGION" - voxels = np.random.randint(100, size=10) - z = np.random.randint(100, size=(10, 2)) + voxels = self.rng.integers(100, size=10) + z = self.rng.integers(100, size=(10, 2)) data = pd.DataFrame( { - "PLACEHOLDER": np.random.rand(10), - "NUM_VOXELS": np.random.randint(100, size=10), + "PLACEHOLDER": self.rng.random(10), + "NUM_VOXELS": self.rng.integers(100, size=10), f"NUM_VOXELS.{region}": voxels, - "CENTER_X": np.random.randint(100, size=10), - "CENTER_Y": np.random.randint(100, size=10), - "CENTER_Z": np.random.randint(100, size=10), - "MIN_Z": np.random.randint(100, size=10), - "MAX_Z": np.random.randint(100, size=10), + "CENTER_X": self.rng.integers(100, size=10), + "CENTER_Y": self.rng.integers(100, size=10), + "CENTER_Z": self.rng.integers(100, size=10), + "MIN_Z": self.rng.integers(100, size=10), + "MAX_Z": self.rng.integers(100, size=10), f"MIN_Z.{region}": z[:, 0], f"MAX_Z.{region}": z[:, 1], } @@ -281,11 +284,11 @@ def test_convert_spatial_units_with_columns_with_region_no_properties(self): def test_convert_spatial_units_with_columns_with_region_with_properties(self): ds = 1.0 / 3 region = "REGION" - placeholder = np.random.rand(10) - area = np.random.rand(10) - perimeter = np.random.rand(10) - axis_major_length = np.random.rand(10) - axis_minor_length = np.random.rand(10) + placeholder = self.rng.random(10) + area = self.rng.random(10) + perimeter = self.rng.random(10) + axis_major_length = self.rng.random(10) + axis_minor_length = self.rng.random(10) data = pd.DataFrame( { diff --git a/tests/arcade_collection/output/test_extract_tick_json.py b/tests/arcade_collection/output/test_extract_tick_json.py index 1f1b2fe..b094853 100644 --- a/tests/arcade_collection/output/test_extract_tick_json.py +++ b/tests/arcade_collection/output/test_extract_tick_json.py @@ -11,7 +11,7 @@ def test_extract_tick_json_file_does_not_exist(self): tar_mock = mock.Mock(spec=tarfile.TarFile) tar_mock.extractfile.return_value = None - with self.assertRaises(AssertionError): + with self.assertRaises(RuntimeError): extract_tick_json(tar_mock, "", 0) def test_extract_tick_json_integer_tick_without_extension(self): diff --git a/tests/arcade_collection/output/test_get_location_voxels.py b/tests/arcade_collection/output/test_get_location_voxels.py index 8d2afff..6e1119a 100644 --- a/tests/arcade_collection/output/test_get_location_voxels.py +++ b/tests/arcade_collection/output/test_get_location_voxels.py @@ -7,7 +7,8 @@ class TestGetLocationVoxels(unittest.TestCase): def test_get_location_voxels_no_region_single_region(self): - voxels1 = np.random.randint(100, size=(100, 3)).tolist() + rng = np.random.default_rng() + voxels1 = rng.integers(100, size=(100, 3)).tolist() location = {"location": [{"region": "UNDEFINED", "voxels": voxels1}]} @@ -18,8 +19,9 @@ def test_get_location_voxels_no_region_single_region(self): self.assertCountEqual(expected_voxels, voxels) def test_get_location_voxels_no_region_multiple_regions(self): - voxels1 = np.random.randint(100, size=(100, 3)).tolist() - voxels2 = np.random.randint(100, size=(100, 3)).tolist() + rng = np.random.default_rng() + voxels1 = rng.integers(100, size=(100, 3)).tolist() + voxels2 = rng.integers(100, size=(100, 3)).tolist() location = { "location": [ @@ -35,8 +37,9 @@ def test_get_location_voxels_no_region_multiple_regions(self): self.assertCountEqual(expected_voxels, voxels) def test_get_location_voxels_with_region(self): - voxels1 = np.random.randint(100, size=(100, 3)).tolist() - voxels2 = np.random.randint(100, size=(100, 3)).tolist() + rng = np.random.default_rng() + voxels1 = rng.integers(100, size=(100, 3)).tolist() + voxels2 = rng.integers(100, size=(100, 3)).tolist() location = { "location": [ diff --git a/tests/arcade_collection/output/test_parse_cells_file.py b/tests/arcade_collection/output/test_parse_cells_file.py index f262621..b4de772 100644 --- a/tests/arcade_collection/output/test_parse_cells_file.py +++ b/tests/arcade_collection/output/test_parse_cells_file.py @@ -2,9 +2,10 @@ import tarfile import unittest from unittest import mock + import pandas as pd -from arcade_collection.output.parse_cells_file import parse_cells_file, parse_cell_tick +from arcade_collection.output.parse_cells_file import parse_cell_tick, parse_cells_file class TestParseCellsFile(unittest.TestCase): @@ -213,8 +214,8 @@ def test_parse_cell_tick_with_regions(self): } expected = [1, tick, 2, 3, 4, 5, "STATE", "PHASE", 6] - expected = expected + [9] # REGION_A - expected = expected + [12] # REGION_B + expected = [*expected, 9] # REGION_A + expected = [*expected, 12] # REGION_B parsed = parse_cell_tick(tick, cell, regions) diff --git a/tests/arcade_collection/output/test_parse_locations_file.py b/tests/arcade_collection/output/test_parse_locations_file.py index 444f77e..6cf198d 100644 --- a/tests/arcade_collection/output/test_parse_locations_file.py +++ b/tests/arcade_collection/output/test_parse_locations_file.py @@ -2,9 +2,10 @@ import tarfile import unittest from unittest import mock + import pandas as pd -from arcade_collection.output.parse_locations_file import parse_locations_file, parse_location_tick +from arcade_collection.output.parse_locations_file import parse_location_tick, parse_locations_file class TestParseLocationsFile(unittest.TestCase): @@ -177,18 +178,18 @@ def test_parse_locations_file_with_regions(self): def test_parse_location_tick_without_regions_empty_list(self): tick = 15 regions = [] - locations = {"id": 1, "location": [{"region": "UNDEFINED", "voxels": []}]} + location = {"id": 1, "location": [{"region": "UNDEFINED", "voxels": []}]} expected = [1, tick, -1, -1, -1, -1, -1, -1, -1, -1, -1] - parsed = parse_location_tick(tick, locations, regions) + parsed = parse_location_tick(tick, location, regions) self.assertListEqual(expected, parsed) def test_parse_location_tick_without_regions(self): tick = 15 regions = [] - locations = { + location = { "id": 1, "center": [2, 3, 4], "location": [ @@ -201,14 +202,14 @@ def test_parse_location_tick_without_regions(self): expected = [1, tick, 2, 3, 4, 5, 6, 7, 14, 15, 16] - parsed = parse_location_tick(tick, locations, regions) + parsed = parse_location_tick(tick, location, regions) self.assertListEqual(expected, parsed) def test_parse_location_tick_with_regions_empty_list(self): tick = 15 regions = ["REGION_A", "REGION_B"] - locations = { + location = { "id": 1, "center": [2, 3, 4], "location": [ @@ -218,17 +219,17 @@ def test_parse_location_tick_with_regions_empty_list(self): } expected = [1, tick, 2, 3, 4, 5, 6, 7, 8, 9, 10] - expected = expected + [7, 8, 9, 5, 6, 7, 8, 9, 10] # REGION_A - expected = expected + [-1, -1, -1, -1, -1, -1, -1, -1, -1] # REGION_B + expected = [*expected, 7, 8, 9, 5, 6, 7, 8, 9, 10] # REGION_A + expected = [*expected, -1, -1, -1, -1, -1, -1, -1, -1, -1] # REGION_B - parsed = parse_location_tick(tick, locations, regions) + parsed = parse_location_tick(tick, location, regions) self.assertListEqual(expected, parsed) def test_parse_location_tick_with_regions(self): tick = 15 regions = ["REGION_A", "REGION_B"] - locations = { + location = { "id": 1, "center": [2, 3, 4], "location": [ @@ -238,10 +239,10 @@ def test_parse_location_tick_with_regions(self): } expected = [1, tick, 2, 3, 4, 5, 6, 7, 14, 15, 16] - expected = expected + [7, 8, 9, 5, 6, 7, 8, 9, 10] # REGION_A - expected = expected + [13, 14, 15, 11, 12, 13, 14, 15, 16] # REGION_B + expected = [*expected, 7, 8, 9, 5, 6, 7, 8, 9, 10] # REGION_A + expected = [*expected, 13, 14, 15, 11, 12, 13, 14, 15, 16] # REGION_B - parsed = parse_location_tick(tick, locations, regions) + parsed = parse_location_tick(tick, location, regions) self.assertListEqual(expected, parsed)