Skip to content

Commit f378f84

Browse files
authored
refactor(PackageContainer): compose not inherit, deprecate methods (#2324)
First steps toward shrinking the inheritance hierarchy. Components (simulation/model/package) now have a PackageContainer instead of being one. APIs which are clearly public remain the same. Visibility is tweaked for a few methods which were previously "private" (leading underscore) but seem user-facing. A number of methods which seem internal-only and/or are redundant with other APIs are deprecated.
1 parent 82ec160 commit f378f84

File tree

9 files changed

+476
-182
lines changed

9 files changed

+476
-182
lines changed

autotest/regression/test_mf6.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4497,22 +4497,21 @@ def test006_2models_mvr(function_tmpdir, example_data_path):
44974497
exg_pkg.exchangedata.set_data(exg_data)
44984498

44994499
# test getting packages
4500-
pkg_dict = parent_model.package_dict
4501-
assert len(pkg_dict) == 6
4502-
pkg_names = parent_model.package_names
4503-
assert len(pkg_names) == 6
4500+
pkg_list = parent_model.get_package()
4501+
assert len(pkg_list) == 6
45044502
# confirm that this is a copy of the original dictionary with references
45054503
# to the packages
4506-
del pkg_dict[pkg_names[0]]
4507-
assert len(pkg_dict) == 5
4508-
pkg_dict = parent_model.package_dict
4509-
assert len(pkg_dict) == 6
4510-
4511-
old_val = pkg_dict["dis"].nlay.get_data()
4512-
pkg_dict["dis"].nlay = 22
4513-
pkg_dict = parent_model.package_dict
4514-
assert pkg_dict["dis"].nlay.get_data() == 22
4515-
pkg_dict["dis"].nlay = old_val
4504+
del pkg_list[0]
4505+
assert len(pkg_list) == 5
4506+
pkg_list = parent_model.get_package()
4507+
assert len(pkg_list) == 6
4508+
4509+
dis_pkg = parent_model.get_package("dis")
4510+
old_val = dis_pkg.nlay.get_data()
4511+
dis_pkg.nlay = 22
4512+
pkg_list = parent_model.get_package()
4513+
assert dis_pkg.nlay.get_data() == 22
4514+
dis_pkg.nlay = old_val
45164515

45174516
# write simulation again
45184517
save_folder = function_tmpdir / "save"
@@ -4560,8 +4559,8 @@ def test006_2models_mvr(function_tmpdir, example_data_path):
45604559
model = sim.get_model(model_name)
45614560
for package in model_package_check:
45624561
assert (
4563-
package in model.package_type_dict
4564-
or package in sim.package_type_dict
4562+
model.get_package(package, type_only=True) is not None
4563+
or sim.get_package(package, type_only=True) is not None
45654564
) == (package in load_only or f"{package}6" in load_only)
45664565
assert (len(sim._exchange_files) > 0) == (
45674566
"gwf6-gwf6" in load_only or "gwf-gwf" in load_only
@@ -4577,10 +4576,10 @@ def test006_2models_mvr(function_tmpdir, example_data_path):
45774576
)
45784577
model_parent = sim.get_model("parent")
45794578
model_child = sim.get_model("child")
4580-
assert "oc" not in model_parent.package_type_dict
4581-
assert "oc" in model_child.package_type_dict
4582-
assert "npf" in model_parent.package_type_dict
4583-
assert "npf" not in model_child.package_type_dict
4579+
assert model_parent.get_package("oc") is None
4580+
assert model_child.get_package("oc") is not None
4581+
assert model_parent.get_package("npf") is not None
4582+
assert model_child.get_package("npf") is None
45844583

45854584
# test running a runnable load_only case
45864585
sim = MFSimulation.load(
@@ -4652,9 +4651,9 @@ def test001e_uzf_3lay(function_tmpdir, example_data_path):
46524651
sim.set_sim_path(function_tmpdir)
46534652
model = sim.get_model()
46544653
for package in model_package_check:
4655-
assert (package in model.package_type_dict) == (
4656-
package in load_only or f"{package}6" in load_only
4657-
)
4654+
assert (
4655+
model.get_package(package, type_only=True) is not None
4656+
) == (package in load_only or f"{package}6" in load_only)
46584657
# test running a runnable load_only case
46594658
sim = MFSimulation.load(
46604659
model_name, "mf6", "mf6", pth, load_only=load_only_lists[0]

autotest/test_copy.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ def model_is_copy(m1, m2):
5454
if k in [
5555
"_packagelist",
5656
"_package_paths",
57-
"package_key_dict",
58-
"package_type_dict",
59-
"package_name_dict",
60-
"package_filename_dict",
6157
"_ftype_num_dict",
6258
]:
6359
continue
@@ -97,17 +93,13 @@ def package_is_copy(pk1, pk2):
9793
if k in [
9894
"_child_package_groups",
9995
"_data_list",
100-
"_packagelist",
101-
"_simulation_data",
96+
"simulation_data",
10297
"blocks",
10398
"dimensions",
104-
"package_key_dict",
105-
"package_name_dict",
106-
"package_filename_dict",
107-
"package_type_dict",
10899
"post_block_comments",
109100
"simulation_data",
110101
"structure",
102+
"_package_container",
111103
]:
112104
continue
113105
elif isinstance(v, MFPackage):

autotest/test_model_splitter.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -467,19 +467,19 @@ def test_empty_packages(function_tmpdir):
467467
m0 = new_sim.get_model(f"{base_name}_0")
468468
m1 = new_sim.get_model(f"{base_name}_1")
469469

470-
if "chd_0" in m0.package_dict:
471-
raise AssertionError(f"Empty CHD file written to {base_name}_0 model")
472-
473-
if "wel_0" in m1.package_dict:
474-
raise AssertionError(f"Empty WEL file written to {base_name}_1 model")
470+
assert not m0.get_package(
471+
name="chd_0"
472+
), f"Empty CHD file written to {base_name}_0 model"
473+
assert not m1.get_package(
474+
name="wel_0"
475+
), f"Empty WEL file written to {base_name}_1 model"
475476

476477
mvr_status0 = m0.sfr.mover.array
477478
mvr_status1 = m0.sfr.mover.array
478479

479-
if not mvr_status0 or not mvr_status1:
480-
raise AssertionError(
481-
"Mover status being overwritten in options splitting"
482-
)
480+
assert (
481+
mvr_status0 and mvr_status1
482+
), "Mover status being overwritten in options splitting"
483483

484484

485485
@requires_exe("mf6")

flopy/mf6/mfbase.py

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from pathlib import Path
1212
from shutil import copyfile
1313
from typing import Union
14-
from warnings import warn
1514

1615

1716
# internal handled exceptions
@@ -454,24 +453,13 @@ class PackageContainer:
454453
modflow_models = []
455454
models_by_type = {}
456455

457-
def __init__(self, simulation_data, name):
458-
self.type = "PackageContainer"
459-
self.simulation_data = simulation_data
460-
self.name = name
461-
self._packagelist = []
456+
def __init__(self, simulation_data):
457+
self._simulation_data = simulation_data
458+
self.packagelist = []
462459
self.package_type_dict = {}
463460
self.package_name_dict = {}
464461
self.package_filename_dict = {}
465462

466-
@property
467-
def package_key_dict(self):
468-
warnings.warn(
469-
"package_key_dict has been deprecated, use "
470-
"package_type_dict instead",
471-
category=DeprecationWarning,
472-
)
473-
return self.package_type_dict
474-
475463
@staticmethod
476464
def package_list():
477465
"""Static method that returns the list of available packages.
@@ -554,9 +542,9 @@ def package_names(self):
554542
"""Returns a list of package names."""
555543
return list(self.package_name_dict.keys())
556544

557-
def _add_package(self, package, path):
545+
def add_package(self, package):
558546
# put in packages list and update lookup dictionaries
559-
self._packagelist.append(package)
547+
self.packagelist.append(package)
560548
if package.package_name is not None:
561549
self.package_name_dict[package.package_name.lower()] = package
562550
if package.filename is not None:
@@ -565,9 +553,9 @@ def _add_package(self, package, path):
565553
self.package_type_dict[package.package_type.lower()] = []
566554
self.package_type_dict[package.package_type.lower()].append(package)
567555

568-
def _remove_package(self, package):
569-
if package in self._packagelist:
570-
self._packagelist.remove(package)
556+
def remove_package(self, package):
557+
if package in self.packagelist:
558+
self.packagelist.remove(package)
571559
if (
572560
package.package_name is not None
573561
and package.package_name.lower() in self.package_name_dict
@@ -587,7 +575,7 @@ def _remove_package(self, package):
587575

588576
# collect keys of items to be removed from main dictionary
589577
items_to_remove = []
590-
for key in self.simulation_data.mfdata:
578+
for key in self._simulation_data.mfdata:
591579
is_subkey = True
592580
for pitem, ditem in zip(package.path, key):
593581
if pitem != ditem:
@@ -598,7 +586,7 @@ def _remove_package(self, package):
598586

599587
# remove items from main dictionary
600588
for key in items_to_remove:
601-
del self.simulation_data.mfdata[key]
589+
del self._simulation_data.mfdata[key]
602590

603591
def _rename_package(self, package, new_name):
604592
# fix package_name_dict key
@@ -609,7 +597,7 @@ def _rename_package(self, package, new_name):
609597
del self.package_name_dict[package.package_name.lower()]
610598
self.package_name_dict[new_name.lower()] = package
611599
# get keys to fix in main dictionary
612-
main_dict = self.simulation_data.mfdata
600+
main_dict = self._simulation_data.mfdata
613601
items_to_fix = []
614602
for key in main_dict:
615603
is_subkey = True
@@ -648,7 +636,7 @@ def get_package(self, name=None, type_only=False, name_only=False):
648636
649637
"""
650638
if name is None:
651-
return self._packagelist[:]
639+
return self.packagelist[:]
652640

653641
# search for full package name
654642
if name.lower() in self.package_name_dict and not type_only:
@@ -669,7 +657,7 @@ def get_package(self, name=None, type_only=False, name_only=False):
669657

670658
# search for partial and case-insensitive package name
671659
if not type_only:
672-
for pp in self._packagelist:
660+
for pp in self.packagelist:
673661
if pp.package_name is not None:
674662
# get first package of the type requested
675663
package_name = pp.package_name.lower()
@@ -680,11 +668,6 @@ def get_package(self, name=None, type_only=False, name_only=False):
680668

681669
return None
682670

683-
def register_package(self, package):
684-
"""Base method for registering a package. Should be overridden."""
685-
path = (package.package_name,)
686-
return (path, None)
687-
688671
@staticmethod
689672
def _load_only_dict(load_only):
690673
if load_only is None:

0 commit comments

Comments
 (0)