threedi-modelchecker 2.6.2.dev0__tar.gz → 2.6.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/CHANGES.rst +10 -2
  2. {threedi-modelchecker-2.6.2.dev0/threedi_modelchecker.egg-info → threedi_modelchecker-2.6.3}/PKG-INFO +1 -1
  3. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/__init__.py +1 -1
  4. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/base.py +2 -3
  5. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/cross_section_definitions.py +0 -80
  6. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/other.py +22 -0
  7. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/config.py +39 -9
  8. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/conftest.py +5 -8
  9. threedi_modelchecker-2.6.3/threedi_modelchecker/tests/data/empty_v4.sqlite +3 -0
  10. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_cross_section_definitions.py +0 -115
  11. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_factories.py +1 -1
  12. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_other.py +41 -0
  13. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3/threedi_modelchecker.egg-info}/PKG-INFO +1 -1
  14. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker.egg-info/SOURCES.txt +1 -1
  15. threedi-modelchecker-2.6.2.dev0/threedi_modelchecker/tests/data/empty.gpkg +0 -0
  16. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/LICENSE +0 -0
  17. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/MANIFEST.in +0 -0
  18. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/README.rst +0 -0
  19. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/pyproject.toml +0 -0
  20. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/setup.cfg +0 -0
  21. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/__init__.py +0 -0
  22. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/factories.py +0 -0
  23. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/geo_query.py +0 -0
  24. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/raster.py +0 -0
  25. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/checks/timeseries.py +0 -0
  26. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/exporters.py +0 -0
  27. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/interfaces/__init__.py +0 -0
  28. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/interfaces/raster_interface.py +0 -0
  29. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/interfaces/raster_interface_gdal.py +0 -0
  30. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/interfaces/raster_interface_rasterio.py +0 -0
  31. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/model_checks.py +0 -0
  32. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/scripts.py +0 -0
  33. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/__init__.py +0 -0
  34. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/data/__init__.py +0 -0
  35. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/factories.py +0 -0
  36. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_base.py +0 -0
  37. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_raster.py +0 -0
  38. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_checks_timeseries.py +0 -0
  39. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_exporters.py +0 -0
  40. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker/tests/test_model_checks.py +0 -0
  41. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker.egg-info/dependency_links.txt +0 -0
  42. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker.egg-info/entry_points.txt +0 -0
  43. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker.egg-info/requires.txt +0 -0
  44. {threedi-modelchecker-2.6.2.dev0 → threedi_modelchecker-2.6.3}/threedi_modelchecker.egg-info/top_level.txt +0 -0
@@ -2,10 +2,18 @@ Changelog of threedi-modelchecker
2
2
  =================================
3
3
 
4
4
 
5
- 2.6.2 (unreleased)
5
+ 2.6.3 (2024-04-22)
6
6
  ------------------
7
7
 
8
- - Nothing changed yet.
8
+ - Fix bug with check 183
9
+
10
+
11
+ 2.6.2 (2024-02-29)
12
+ ------------------
13
+
14
+ - Add warning check (0616) for surfaces for which no inflow is generated because of the surface table not being referred to in global settings.
15
+ - Add warning check (0617) to warn if the surface table referred to in global settings is empty and no inflow will be generated for it.
16
+ - Remove warning check 0029.
9
17
 
10
18
 
11
19
  2.6.1 (2024-02-20)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: threedi-modelchecker
3
- Version: 2.6.2.dev0
3
+ Version: 2.6.3
4
4
  Summary: Checks validity of a 3Di schematisation
5
5
  Author-email: Nelen & Schuurmans <info@nelen-schuurmans.nl>
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  from .model_checks import * # NOQA
2
2
 
3
3
  # fmt: off
4
- __version__ = '2.6.2.dev0'
4
+ __version__ = '2.6.3'
5
5
  # fmt: on
@@ -221,8 +221,7 @@ class TypeCheck(BaseCheck):
221
221
  self.expected_types = _sqlalchemy_to_sqlite_types(self.column.type)
222
222
 
223
223
  def get_invalid(self, session):
224
- if ("sqlite" not in session.bind.dialect.dialect_description) and (
225
- "geopackage" not in session.bind.dialect.dialect_description):
224
+ if "sqlite" not in session.bind.dialect.dialect_description:
226
225
  return []
227
226
  q_invalid = self.to_check(session)
228
227
  invalid_type_query = q_invalid.filter(
@@ -312,7 +311,7 @@ class GeometryTypeCheck(BaseCheck):
312
311
  def _get_geometry_type(column, dialect):
313
312
  if column.type.geometry_type == "GEOMETRY":
314
313
  return # should skip the check
315
- if dialect in ["sqlite", "geopackage"]:
314
+ if dialect == "sqlite":
316
315
  return column.type.geometry_type
317
316
  elif dialect == "postgresql":
318
317
  geom_type = column.type.geometry_type.capitalize()
@@ -505,86 +505,6 @@ class OpenIncreasingCrossSectionConveyanceFrictionCheck(CrossSectionBaseCheck):
505
505
  )
506
506
 
507
507
 
508
- class CrossSectionConveyanceFrictionAdviceCheck(CrossSectionBaseCheck):
509
- """
510
- Check if cross sections:
511
- - Are of shape tabulated rectangle, tabulated trapezium, or tabulated YZ
512
- - Monotonically increase in width
513
- but do not use the new friction type with conveyance.
514
- If so, advise the user that they may wish to use a friction type with conveyance.
515
- """
516
-
517
- def __init__(self, *args, **kwargs):
518
- super().__init__(column=models.CrossSectionLocation.id, *args, **kwargs)
519
-
520
- def get_invalid(self, session):
521
- invalids = []
522
- for record in session.execute(
523
- select(
524
- models.CrossSectionLocation.id,
525
- models.CrossSectionLocation.friction_type,
526
- models.CrossSectionDefinition.shape,
527
- models.CrossSectionDefinition.width,
528
- models.CrossSectionDefinition.height,
529
- )
530
- .join(models.CrossSectionDefinition, isouter=True)
531
- .where(
532
- (models.CrossSectionDefinition.width != None)
533
- & (models.CrossSectionDefinition.width != "")
534
- )
535
- ):
536
- try:
537
- widths = [float(x) for x in record.width.split(" ")]
538
- heights = (
539
- [float(x) for x in record.height.split(" ")]
540
- if record.height not in [None, ""]
541
- else []
542
- )
543
- except ValueError:
544
- continue # other check catches this
545
-
546
- _, _, configuration = cross_section_configuration(
547
- shape=record.shape.value, heights=heights, widths=widths
548
- )
549
-
550
- if (
551
- configuration == "open"
552
- and (
553
- len(widths) > 1
554
- and all(
555
- next_width >= previous_width
556
- for (previous_width, next_width) in zip(widths[:-1], widths[1:])
557
- )
558
- )
559
- and (
560
- record.shape.value
561
- in [
562
- constants.CrossSectionShape.TABULATED_RECTANGLE.value,
563
- constants.CrossSectionShape.TABULATED_TRAPEZIUM.value,
564
- constants.CrossSectionShape.TABULATED_YZ.value,
565
- ]
566
- )
567
- and (
568
- record.friction_type.value
569
- not in [
570
- constants.FrictionType.CHEZY_CONVEYANCE.value,
571
- constants.FrictionType.MANNING_CONVEYANCE.value,
572
- ]
573
- )
574
- ):
575
- invalids.append(record)
576
-
577
- return invalids
578
-
579
- def description(self):
580
- return (
581
- "Friction for this cross-section will be calculated without conveyance. "
582
- "For open Tabulated or YZ cross-sections, using conveyance in the calculation "
583
- "of friction is recommended in case there is a significant variation "
584
- "of the bed level (for instance, in a scenario with overflowing floodplains)."
585
- )
586
-
587
-
588
508
  class CrossSectionVariableCorrectLengthCheck(CrossSectionBaseCheck):
589
509
  """Variable friction and vegetation properties should contain 1 value for each element; len(var_property) = len(width)-1"""
590
510
 
@@ -815,6 +815,28 @@ class PerviousNodeInflowAreaCheck(BaseCheck):
815
815
  return f"{self.column_name} has a an associated inflow area larger than 10000 m2; this might be an error."
816
816
 
817
817
 
818
+ class InflowNoFeaturesCheck(BaseCheck):
819
+ """Check that the surface table in the global use_0d_inflow setting contains at least 1 feature."""
820
+
821
+ def __init__(self, *args, surface_table, condition=True, **kwargs):
822
+ super().__init__(*args, column=models.GlobalSetting.id, **kwargs)
823
+ self.surface_table = surface_table
824
+ self.condition = condition
825
+
826
+ def get_invalid(self, session: Session):
827
+ surface_table_length = session.execute(
828
+ select(func.count(self.surface_table.id))
829
+ ).scalar()
830
+ return (
831
+ session.query(models.GlobalSetting)
832
+ .filter(self.condition, surface_table_length == 0)
833
+ .all()
834
+ )
835
+
836
+ def description(self) -> str:
837
+ return f"v2_global_settings.use_0d_inflow is set to use {self.surface_table.__tablename__}, but {self.surface_table.__tablename__} does not contain any features."
838
+
839
+
818
840
  class NodeSurfaceConnectionsCheck(BaseCheck):
819
841
  """Check that no more than 50 surfaces are mapped to a connection node"""
820
842
 
@@ -17,7 +17,6 @@ from .checks.base import (
17
17
  UniqueCheck,
18
18
  )
19
19
  from .checks.cross_section_definitions import (
20
- CrossSectionConveyanceFrictionAdviceCheck,
21
20
  CrossSectionEqualElementsCheck,
22
21
  CrossSectionExpectEmptyCheck,
23
22
  CrossSectionFirstElementNonZeroCheck,
@@ -61,6 +60,7 @@ from .checks.other import (
61
60
  DefinedAreaCheck,
62
61
  FeatureClosedCrossSectionCheck,
63
62
  ImperviousNodeInflowAreaCheck,
63
+ InflowNoFeaturesCheck,
64
64
  LinestringLocationCheck,
65
65
  NodeSurfaceConnectionsCheck,
66
66
  OpenChannelsWithNestedNewton,
@@ -326,12 +326,6 @@ CHECKS += [
326
326
  error_code=28,
327
327
  )
328
328
  ]
329
- CHECKS += [
330
- CrossSectionConveyanceFrictionAdviceCheck(
331
- error_code=29,
332
- level=CheckLevel.INFO,
333
- )
334
- ]
335
329
 
336
330
  ## 003x: CALCULATION TYPE
337
331
 
@@ -883,6 +877,16 @@ CHECKS += [
883
877
  LinestringLocationCheck(error_code=205, column=table.the_geom, max_distance=1)
884
878
  for table in [models.Channel, models.Culvert]
885
879
  ]
880
+ CHECKS += [
881
+ QueryCheck(
882
+ error_code=206,
883
+ column=models.ConnectionNode.the_geom_linestring,
884
+ invalid=Query(models.ConnectionNode).filter(
885
+ models.ConnectionNode.the_geom_linestring != None
886
+ ),
887
+ message=f"{models.ConnectionNode.the_geom_linestring} must be NULL",
888
+ )
889
+ ]
886
890
  CHECKS += [
887
891
  SpatialIndexCheck(
888
892
  error_code=207, column=models.ConnectionNode.the_geom, level=CheckLevel.WARNING
@@ -2060,7 +2064,33 @@ CHECKS += [
2060
2064
  (models.ImperviousSurfaceMap.connection_node_id, models.ConnectionNode),
2061
2065
  )
2062
2066
  ]
2067
+ CHECKS += [
2068
+ QueryCheck(
2069
+ error_code=616,
2070
+ level=CheckLevel.WARNING,
2071
+ column=table.id,
2072
+ filters=~CONDITIONS[condition].exists(),
2073
+ invalid=Query(table),
2074
+ message=f"No inflow will be generated for this feature, because v2_global_settings.use_0d_inflow is not set to use {table.__tablename__}.",
2075
+ )
2076
+ for table, condition in (
2077
+ (models.ImperviousSurface, "0d_imp"),
2078
+ (models.Surface, "0d_surf"),
2079
+ )
2080
+ ]
2063
2081
 
2082
+ CHECKS += [
2083
+ InflowNoFeaturesCheck(
2084
+ error_code=617,
2085
+ level=CheckLevel.WARNING,
2086
+ surface_table=table,
2087
+ condition=CONDITIONS[condition].exists(),
2088
+ )
2089
+ for table, condition in (
2090
+ (models.ImperviousSurface, "0d_imp"),
2091
+ (models.Surface, "0d_surf"),
2092
+ )
2093
+ ]
2064
2094
 
2065
2095
  CHECKS += [
2066
2096
  RangeCheck(
@@ -2890,9 +2920,9 @@ CHECKS += [
2890
2920
  error_code=183,
2891
2921
  level=CheckLevel.WARNING,
2892
2922
  column=col_cross_section_location,
2893
- invalid=Query(models.CrossSectionDefinition)
2923
+ invalid=Query(models.CrossSectionLocation)
2894
2924
  .join(
2895
- models.CrossSectionLocation,
2925
+ models.CrossSectionDefinition,
2896
2926
  models.CrossSectionLocation.definition_id
2897
2927
  == models.CrossSectionDefinition.id,
2898
2928
  )
@@ -20,8 +20,8 @@ def threedi_db(tmpdir_factory):
20
20
  https://factoryboy.readthedocs.io/en/latest/orms.html#managing-sessions
21
21
  """
22
22
  tmp_path = tmpdir_factory.mktemp("spatialite4")
23
- tmp_sqlite = tmp_path / "empty.gpkg"
24
- shutil.copyfile(data_dir / "empty.gpkg", tmp_sqlite)
23
+ tmp_sqlite = tmp_path / "empty_v4.sqlite"
24
+ shutil.copyfile(data_dir / "empty_v4.sqlite", tmp_sqlite)
25
25
  db = ThreediDatabase(tmp_sqlite)
26
26
  schema = ModelSchema(db)
27
27
  schema.upgrade(backup=False, upgrade_spatialite_version=False)
@@ -52,10 +52,7 @@ def session(threedi_db):
52
52
 
53
53
  @pytest.fixture
54
54
  def empty_sqlite_v4(tmp_path):
55
- """An function-scoped empty geopackage v4 in the latest migration state"""
56
- tmp_sqlite = tmp_path / "empty.gpkg"
57
- shutil.copyfile(data_dir / "empty.gpkg", tmp_sqlite)
55
+ """An function-scoped empty spatialite v4 in the latest migration state"""
56
+ tmp_sqlite = tmp_path / "empty_v4.sqlite"
57
+ shutil.copyfile(data_dir / "empty_v4.sqlite", tmp_sqlite)
58
58
  return ThreediDatabase(tmp_sqlite)
59
-
60
-
61
-
@@ -0,0 +1,3 @@
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1157e95b7271dbe14142f96bc46664be92f53d463726c4d0cb18be07f9cd7acb
3
+ size 6086656
@@ -2,7 +2,6 @@ import pytest
2
2
  from threedi_schema import constants, models
3
3
 
4
4
  from threedi_modelchecker.checks.cross_section_definitions import (
5
- CrossSectionConveyanceFrictionAdviceCheck,
6
5
  CrossSectionEqualElementsCheck,
7
6
  CrossSectionExpectEmptyCheck,
8
7
  CrossSectionFirstElementNonZeroCheck,
@@ -575,120 +574,6 @@ def test_check_cross_section_increasing_open_with_conveyance_friction(
575
574
  assert len(invalid_rows) == expected_result
576
575
 
577
576
 
578
- @pytest.mark.parametrize(
579
- "shape,width,height,expected_result",
580
- [
581
- (0, "0.1", "0.2", 0), # closed rectangle, pass
582
- (1, "0.1", None, 0), # open rectangle, pass because it isn't tabulated
583
- (
584
- 5,
585
- "0.04 0.1",
586
- "0.06 0.2",
587
- 1,
588
- ), # open tabulated rectangle, increasing width, fail
589
- (
590
- 5,
591
- "0.04 0.1 0.1",
592
- "0.06 0.2 0.3",
593
- 1,
594
- ), # open tabulated rectangle, equal width segments, fail
595
- (
596
- 5,
597
- "0.2 0.1",
598
- "0.06 0.2",
599
- 0,
600
- ), # open tabulated rectangle, decreasing width, pass
601
- (
602
- 5,
603
- "0.04 0.1 0",
604
- "0.06 0.2",
605
- 0,
606
- ), # closed tabulated rectangle, pass
607
- (
608
- 6,
609
- "0.04 0.1",
610
- "0.06 0.2",
611
- 1,
612
- ), # open tabulated trapezium, increasing width, fail
613
- (
614
- 6,
615
- "0.04 0.1 0.1",
616
- "0.06 0.2 0.3",
617
- 1,
618
- ), # open tabulated trapezium, equal width segments, fail
619
- (
620
- 6,
621
- "0.2 0.1",
622
- "0.06 0.3",
623
- 0,
624
- ), # open tabulated trapezium, decreasing width, pass
625
- (
626
- 6,
627
- "0.04 0.1 0",
628
- "0.06 0.2",
629
- 0,
630
- ), # closed tabulated trapezium, pass
631
- (
632
- 7,
633
- "0.01 0.11",
634
- "0.11 0.21",
635
- 1,
636
- ), # open tabulated yz, increasing width, fail
637
- (
638
- 7,
639
- "0.01 0.10 0.10",
640
- "0.11 0.21 0.31",
641
- 1,
642
- ), # open tabulated yz, equal width segments, fail
643
- (
644
- 7,
645
- "0.11 0.01",
646
- "0.11 0.20",
647
- 0,
648
- ), # open tabulated yz, decreasing width, pass
649
- (
650
- 7,
651
- "0.01 0.11 0.01",
652
- "0.11 0.21 0.11",
653
- 0,
654
- ), # closed tabulated yz, pass
655
- (0, "foo", "", 0), # bad data, pass
656
- ],
657
- )
658
- @pytest.mark.parametrize(
659
- "friction_type,conveyance",
660
- [
661
- (constants.FrictionType.CHEZY, False),
662
- (constants.FrictionType.MANNING, False),
663
- (constants.FrictionType.CHEZY_CONVEYANCE, True),
664
- (constants.FrictionType.MANNING_CONVEYANCE, True),
665
- ],
666
- )
667
- def test_check_cross_section_conveyance_friction_info_message(
668
- session, shape, width, height, expected_result, friction_type, conveyance
669
- ):
670
- """
671
- When a cross-section is expected to fail, that means
672
- it may use friction with conveyance, but isn't, so an
673
- info message will be given to inform the user of that.
674
- """
675
- definition = factories.CrossSectionDefinitionFactory(
676
- shape=shape,
677
- width=width,
678
- height=height,
679
- )
680
- factories.CrossSectionLocationFactory(
681
- definition=definition, friction_type=friction_type
682
- )
683
- check = CrossSectionConveyanceFrictionAdviceCheck()
684
- # this check should pass on cross-section locations which use conveyance,
685
- # regardless of their other parameters
686
- if conveyance:
687
- expected_result = 0
688
- invalid_rows = check.get_invalid(session)
689
- assert len(invalid_rows) == expected_result
690
-
691
-
692
577
  @pytest.mark.parametrize("data, result", [["1 2", True], ["1 2 3", False]])
693
578
  def test_check_correct_length(session, data, result):
694
579
  definition = factories.CrossSectionDefinitionFactory(
@@ -36,7 +36,7 @@ def test_gen_not_null_checks():
36
36
  def test_gen_geometry_check():
37
37
  geometry_checks = generate_geometry_checks(models.ConnectionNode.__table__)
38
38
 
39
- assert len(geometry_checks) == 1
39
+ assert len(geometry_checks) == 2
40
40
  geometry_check_columns = [check.column for check in geometry_checks]
41
41
  assert models.ConnectionNode.the_geom in geometry_check_columns
42
42
 
@@ -20,6 +20,7 @@ from threedi_modelchecker.checks.other import (
20
20
  DefinedAreaCheck,
21
21
  FeatureClosedCrossSectionCheck,
22
22
  ImperviousNodeInflowAreaCheck,
23
+ InflowNoFeaturesCheck,
23
24
  LinestringLocationCheck,
24
25
  NodeSurfaceConnectionsCheck,
25
26
  OpenChannelsWithNestedNewton,
@@ -549,6 +550,46 @@ def test_impervious_connection_node_inflow_area(session, value, expected_result)
549
550
  assert len(invalid) == expected_result
550
551
 
551
552
 
553
+ @pytest.mark.parametrize(
554
+ "surface_number,expected_result",
555
+ [
556
+ (0, 1),
557
+ (1, 0),
558
+ (10, 0),
559
+ ],
560
+ )
561
+ def test_inflow_no_features_impervious(session, surface_number, expected_result):
562
+ # add fields
563
+ factories.GlobalSettingsFactory()
564
+ if surface_number > 0:
565
+ factories.ImperviousSurfaceFactory.create_batch(size=surface_number)
566
+
567
+ # test
568
+ check = InflowNoFeaturesCheck(surface_table=models.ImperviousSurface)
569
+ invalid = check.get_invalid(session)
570
+ assert len(invalid) == expected_result
571
+
572
+
573
+ @pytest.mark.parametrize(
574
+ "surface_number,expected_result",
575
+ [
576
+ (0, 1),
577
+ (1, 0),
578
+ (10, 0),
579
+ ],
580
+ )
581
+ def test_inflow_no_features_pervious(session, surface_number, expected_result):
582
+ # add fields
583
+ factories.GlobalSettingsFactory()
584
+ if surface_number > 0:
585
+ factories.SurfaceFactory.create_batch(size=surface_number)
586
+
587
+ # test
588
+ check = InflowNoFeaturesCheck(surface_table=models.Surface)
589
+ invalid = check.get_invalid(session)
590
+ assert len(invalid) == expected_result
591
+
592
+
552
593
  @pytest.mark.parametrize(
553
594
  "value,expected_result",
554
595
  [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: threedi-modelchecker
3
- Version: 2.6.2.dev0
3
+ Version: 2.6.3
4
4
  Summary: Checks validity of a 3Di schematisation
5
5
  Author-email: Nelen & Schuurmans <info@nelen-schuurmans.nl>
6
6
  License: MIT
@@ -38,4 +38,4 @@ threedi_modelchecker/tests/test_checks_timeseries.py
38
38
  threedi_modelchecker/tests/test_exporters.py
39
39
  threedi_modelchecker/tests/test_model_checks.py
40
40
  threedi_modelchecker/tests/data/__init__.py
41
- threedi_modelchecker/tests/data/empty.gpkg
41
+ threedi_modelchecker/tests/data/empty_v4.sqlite