uk_bin_collection 0.78.0__tar.gz → 0.79.1__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 (183) hide show
  1. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/PKG-INFO +1 -1
  2. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/pyproject.toml +1 -1
  3. uk_bin_collection-0.79.1/uk_bin_collection/tests/council_feature_input_parity.py +109 -0
  4. uk_bin_collection-0.79.1/uk_bin_collection/tests/features/validate_council_outputs.feature +7 -0
  5. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/input.json +65 -2
  6. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/step_defs/test_validate_council.py +44 -16
  7. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/test_common_functions.py +4 -2
  8. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/common.py +4 -1
  9. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/ChichesterDistrictCouncil.py +110 -0
  10. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py +1 -1
  11. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/DartfordBoroughCouncil.py +44 -0
  12. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/DoverDistrictCouncil.py +11 -6
  13. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/EppingForestDistrictCouncil.py +51 -0
  14. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/FarehamBoroughCouncil.py +20 -21
  15. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/HounslowCouncil.py +122 -0
  16. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/KirkleesCouncil.py +3 -1
  17. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MoleValleyDistrictCouncil.py +13 -10
  18. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py +151 -0
  19. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/StroudDistrictCouncil.py +94 -0
  20. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/TendringDistrictCouncil.py +110 -0
  21. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WakefieldCityCouncil.py +3 -1
  22. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/councils/WalthamForest.py +127 -0
  23. uk_bin_collection-0.79.1/uk_bin_collection/uk_bin_collection/create_new_council.py +51 -0
  24. uk_bin_collection-0.78.0/uk_bin_collection/tests/council_feature_input_parity.py +0 -128
  25. uk_bin_collection-0.78.0/uk_bin_collection/tests/features/validate_council_outputs.feature +0 -777
  26. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/LICENSE +0 -0
  27. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/README.md +0 -0
  28. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/README.rst +0 -0
  29. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/features/environment.py +0 -0
  30. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/output.schema +0 -0
  31. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/step_defs/step_helpers/file_handler.py +0 -0
  32. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/tests/test_collect_data.py +0 -0
  33. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/collect_data.py +0 -0
  34. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/AdurAndWorthingCouncils.py +0 -0
  35. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ArunCouncil.py +0 -0
  36. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/AylesburyValeCouncil.py +0 -0
  37. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BCPCouncil.py +0 -0
  38. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BarnetCouncil.py +0 -0
  39. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BarnsleyMBCouncil.py +0 -0
  40. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BasingstokeCouncil.py +0 -0
  41. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BathAndNorthEastSomersetCouncil.py +0 -0
  42. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BedfordBoroughCouncil.py +0 -0
  43. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py +0 -0
  44. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BexleyCouncil.py +0 -0
  45. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py +0 -0
  46. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BlackburnCouncil.py +0 -0
  47. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BoltonCouncil.py +0 -0
  48. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BracknellForestCouncil.py +0 -0
  49. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BradfordMDC.py +0 -0
  50. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BrightonandHoveCityCouncil.py +0 -0
  51. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BristolCityCouncil.py +0 -0
  52. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py +0 -0
  53. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BroxtoweBoroughCouncil.py +0 -0
  54. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py +0 -0
  55. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/BuryCouncil.py +0 -0
  56. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CalderdaleCouncil.py +0 -0
  57. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CannockChaseDistrictCouncil.py +0 -0
  58. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CardiffCouncil.py +0 -0
  59. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CastlepointDistrictCouncil.py +0 -0
  60. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CharnwoodBoroughCouncil.py +0 -0
  61. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py +0 -0
  62. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CheshireEastCouncil.py +0 -0
  63. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py +0 -0
  64. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ChorleyCouncil.py +0 -0
  65. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ConwyCountyBorough.py +0 -0
  66. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/CroydonCouncil.py +0 -0
  67. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/DerbyshireDalesDistrictCouncil.py +0 -0
  68. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/DoncasterCouncil.py +0 -0
  69. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/DorsetCouncil.py +0 -0
  70. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/DurhamCouncil.py +0 -0
  71. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastCambridgeshireCouncil.py +0 -0
  72. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastDevonDC.py +0 -0
  73. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastLindseyDistrictCouncil.py +0 -0
  74. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastRidingCouncil.py +0 -0
  75. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastSuffolkCouncil.py +0 -0
  76. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EastleighBoroughCouncil.py +0 -0
  77. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/EnvironmentFirst.py +0 -0
  78. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ErewashBoroughCouncil.py +0 -0
  79. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/FenlandDistrictCouncil.py +0 -0
  80. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ForestOfDeanDistrictCouncil.py +0 -0
  81. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/GatesheadCouncil.py +0 -0
  82. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/GedlingBoroughCouncil.py +0 -0
  83. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py +0 -0
  84. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py +0 -0
  85. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py +0 -0
  86. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HaringeyCouncil.py +0 -0
  87. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HarrogateBoroughCouncil.py +0 -0
  88. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HighPeakCouncil.py +0 -0
  89. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HullCityCouncil.py +0 -0
  90. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/HuntingdonDistrictCouncil.py +0 -0
  91. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/KingstonUponThamesCouncil.py +0 -0
  92. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/KnowsleyMBCouncil.py +0 -0
  93. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py +0 -0
  94. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LeedsCityCouncil.py +0 -0
  95. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LisburnCastlereaghCityCouncil.py +0 -0
  96. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LiverpoolCityCouncil.py +0 -0
  97. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LondonBoroughHounslow.py +0 -0
  98. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/LondonBoroughRedbridge.py +0 -0
  99. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MaldonDistrictCouncil.py +0 -0
  100. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MalvernHillsDC.py +0 -0
  101. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py +0 -0
  102. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MansfieldDistrictCouncil.py +0 -0
  103. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MertonCouncil.py +0 -0
  104. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MidAndEastAntrimBoroughCouncil.py +0 -0
  105. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MidSussexDistrictCouncil.py +0 -0
  106. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/MiltonKeynesCityCouncil.py +0 -0
  107. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NeathPortTalbotCouncil.py +0 -0
  108. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NewarkAndSherwoodDC.py +0 -0
  109. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NewcastleCityCouncil.py +0 -0
  110. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NewhamCouncil.py +0 -0
  111. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NewportCityCouncil.py +0 -0
  112. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthEastDerbyshireDistrictCouncil.py +0 -0
  113. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthEastLincs.py +0 -0
  114. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthKestevenDistrictCouncil.py +0 -0
  115. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthLanarkshireCouncil.py +0 -0
  116. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthLincolnshireCouncil.py +0 -0
  117. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthNorfolkDistrictCouncil.py +0 -0
  118. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthNorthamptonshireCouncil.py +0 -0
  119. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthSomersetCouncil.py +0 -0
  120. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthTynesideCouncil.py +0 -0
  121. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthWestLeicestershire.py +0 -0
  122. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthYorkshire.py +0 -0
  123. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py +0 -0
  124. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/NottinghamCityCouncil.py +0 -0
  125. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/OldhamCouncil.py +0 -0
  126. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/PortsmouthCityCouncil.py +0 -0
  127. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/PrestonCityCouncil.py +0 -0
  128. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ReadingBoroughCouncil.py +0 -0
  129. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ReigateAndBansteadBoroughCouncil.py +0 -0
  130. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RenfrewshireCouncil.py +0 -0
  131. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RhonddaCynonTaffCouncil.py +0 -0
  132. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RochdaleCouncil.py +0 -0
  133. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RochfordCouncil.py +0 -0
  134. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RugbyBoroughCouncil.py +0 -0
  135. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RushcliffeBoroughCouncil.py +0 -0
  136. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/RushmoorCouncil.py +0 -0
  137. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SalfordCityCouncil.py +0 -0
  138. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SevenoaksDistrictCouncil.py +0 -0
  139. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SheffieldCityCouncil.py +0 -0
  140. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ShropshireCouncil.py +0 -0
  141. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SolihullCouncil.py +0 -0
  142. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py +0 -0
  143. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthAyrshireCouncil.py +0 -0
  144. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthCambridgeshireCouncil.py +0 -0
  145. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthGloucestershireCouncil.py +0 -0
  146. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthLanarkshireCouncil.py +0 -0
  147. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthNorfolkCouncil.py +0 -0
  148. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthOxfordshireCouncil.py +0 -0
  149. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py +0 -0
  150. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StAlbansCityAndDistrictCouncil.py +0 -0
  151. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StHelensBC.py +0 -0
  152. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StaffordshireMoorlandsDistrictCouncil.py +0 -0
  153. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StockportBoroughCouncil.py +0 -0
  154. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StokeOnTrentCityCouncil.py +0 -0
  155. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/StratfordUponAvonCouncil.py +0 -0
  156. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SunderlandCityCouncil.py +0 -0
  157. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/SwaleBoroughCouncil.py +0 -0
  158. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TamesideMBCouncil.py +0 -0
  159. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TandridgeDistrictCouncil.py +0 -0
  160. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TelfordAndWrekinCouncil.py +0 -0
  161. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TestValleyBoroughCouncil.py +0 -0
  162. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TonbridgeAndMallingBC.py +0 -0
  163. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TorbayCouncil.py +0 -0
  164. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/TorridgeDistrictCouncil.py +0 -0
  165. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py +0 -0
  166. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/ValeofWhiteHorseCouncil.py +0 -0
  167. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WarwickDistrictCouncil.py +0 -0
  168. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WaverleyBoroughCouncil.py +0 -0
  169. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WealdenDistrictCouncil.py +0 -0
  170. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WelhatCouncil.py +0 -0
  171. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WestBerkshireCouncil.py +0 -0
  172. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WestLindseyDistrictCouncil.py +0 -0
  173. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WestLothianCouncil.py +0 -0
  174. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WestNorthamptonshireCouncil.py +0 -0
  175. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WestSuffolkCouncil.py +0 -0
  176. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py +0 -0
  177. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WiltshireCouncil.py +0 -0
  178. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py +0 -0
  179. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py +0 -0
  180. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/WyreCouncil.py +0 -0
  181. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py +0 -0
  182. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py +0 -0
  183. {uk_bin_collection-0.78.0 → uk_bin_collection-0.79.1}/uk_bin_collection/uk_bin_collection/get_bin_data.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.78.0
3
+ Version: 0.79.1
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "uk_bin_collection"
3
- version = "0.78.0"
3
+ version = "0.79.1"
4
4
  description = "Python Lib to collect UK Bin Data"
5
5
  readme = "README.md"
6
6
  authors = ["Robert Bradley <robbrad182@gmail.com>"]
@@ -0,0 +1,109 @@
1
+ import json
2
+ import requests
3
+ import sys
4
+ from tabulate import tabulate
5
+ import base64
6
+
7
+
8
+ def get_councils_from_files(repo, branch):
9
+ url = f"https://api.github.com/repos/{repo}/contents/uk_bin_collection/uk_bin_collection/councils?ref={branch}"
10
+ print(f"Fetching councils from files at URL: {url}")
11
+ response = requests.get(url, headers={"Accept": "application/vnd.github.v3+json"})
12
+
13
+ if response.status_code == 200:
14
+ try:
15
+ data = response.json()
16
+ if isinstance(data, list):
17
+ return [
18
+ item["name"].replace(".py", "")
19
+ for item in data
20
+ if item["name"].endswith(".py")
21
+ ]
22
+ else:
23
+ print("Expected a list from the JSON response but got something else.")
24
+ raise ValueError(
25
+ "Expected a list from the JSON response but got something else."
26
+ )
27
+ except json.JSONDecodeError as e:
28
+ print(f"JSON decoding error: {e}")
29
+ raise
30
+ else:
31
+ print(f"Failed to fetch councils from files: {response.content}")
32
+ return []
33
+
34
+
35
+ def get_councils_from_json(repo, branch):
36
+ url = f"https://api.github.com/repos/{repo}/contents/uk_bin_collection/tests/input.json?ref={branch}"
37
+ print(f"Fetching councils from JSON at URL: {url}")
38
+ response = requests.get(url, headers={"Accept": "application/vnd.github.v3+json"})
39
+
40
+ if response.status_code == 200:
41
+ try:
42
+ content = response.json().get("content", "")
43
+ content_decoded = base64.b64decode(content).decode("utf-8")
44
+ data = json.loads(content_decoded)
45
+ return list(data.keys())
46
+ except json.JSONDecodeError as e:
47
+ print(f"JSON decoding error: {e}")
48
+ raise
49
+ else:
50
+ print(f"Failed to fetch councils from JSON: {response.content}")
51
+ return []
52
+
53
+
54
+ def compare_councils(councils1, councils2):
55
+ set1 = set(councils1)
56
+ set2 = set(councils2)
57
+ all_councils = set1 | set2
58
+ all_council_data = {}
59
+ discrepancies_found = False
60
+ for council in all_councils:
61
+ in_files = council in set1
62
+ in_json = council in set2
63
+ discrepancies_count = [in_files, in_json].count(False)
64
+ all_council_data[council] = {
65
+ "in_files": in_files,
66
+ "in_json": in_json,
67
+ "discrepancies_count": discrepancies_count,
68
+ }
69
+ if discrepancies_count > 0:
70
+ discrepancies_found = True
71
+ return all_council_data, discrepancies_found
72
+
73
+
74
+ def main(repo="robbrad/UKBinCollectionData", branch="master"):
75
+ # Execute and print the comparison
76
+ print(f"Starting comparison for repo: {repo}, branch: {branch}")
77
+ file_councils = get_councils_from_files(repo, branch)
78
+ json_councils = get_councils_from_json(repo, branch)
79
+
80
+ all_councils_data, discrepancies_found = compare_councils(
81
+ file_councils, json_councils
82
+ )
83
+
84
+ table_data = []
85
+ headers = ["Council Name", "In Files", "In JSON", "Discrepancies"]
86
+ for council, presence in sorted(
87
+ all_councils_data.items(), key=lambda x: (x[1]["discrepancies_count"], x[0])
88
+ ):
89
+ row = [
90
+ council,
91
+ "✔" if presence["in_files"] else "✘",
92
+ "✔" if presence["in_json"] else "✘",
93
+ presence["discrepancies_count"],
94
+ ]
95
+ table_data.append(row)
96
+
97
+ print(tabulate(table_data, headers=headers, tablefmt="grid"))
98
+
99
+ if discrepancies_found:
100
+ print("Discrepancies found! Failing the workflow.")
101
+ sys.exit(1)
102
+ else:
103
+ print("No discrepancies found. Workflow successful.")
104
+
105
+
106
+ if __name__ == "__main__":
107
+ repo = sys.argv[1] if len(sys.argv) > 1 else "robbrad/UKBinCollectionData"
108
+ branch = sys.argv[2] if len(sys.argv) > 2 else "master"
109
+ main(repo, branch)
@@ -0,0 +1,7 @@
1
+ Feature: Test each council output matches expected results
2
+
3
+ Scenario: Validate Council Output
4
+ Given the council
5
+ When we scrape the data from the council
6
+ Then the result is valid json
7
+ And the output should validate against the schema
@@ -222,6 +222,15 @@
222
222
  "web_driver": "http://selenium:4444",
223
223
  "wiki_name": "Cheshire West and Chester Council"
224
224
  },
225
+ "ChichesterDistrictCouncil": {
226
+ "house_number": "7, Plaistow Road, Kirdford, Billingshurst, West Sussex",
227
+ "postcode": "RH14 0JT",
228
+ "skip_get_url": true,
229
+ "url": "https://www.chichester.gov.uk/checkyourbinday",
230
+ "web_driver": "http://selenium:4444",
231
+ "wiki_name": "ChichesterDistrictCouncil",
232
+ "wiki_note": "Needs the full address and postcode as appears on page https://www.chichester.gov.uk/checkyourbinday"
233
+ },
225
234
  "ChorleyCouncil": {
226
235
  "postcode": "PR6 7PG",
227
236
  "skip_get_url": true,
@@ -253,6 +262,12 @@
253
262
  "url": "https://service.croydon.gov.uk/wasteservices/w/webpage/bin-day-enter-address",
254
263
  "wiki_name": "Croydon Council"
255
264
  },
265
+ "DartfordBoroughCouncil": {
266
+ "url": "https://windmz.dartford.gov.uk/ufs/WS_CHECK_COLLECTIONS.eb?UPRN=010094157511",
267
+ "wiki_name": "DartfordBoroughCouncil",
268
+ "uprn": "010094157511",
269
+ "wiki_note": "Use https://uprn.uk/ to find your UPRN "
270
+ },
256
271
  "DerbyshireDalesDistrictCouncil": {
257
272
  "postcode": "DE4 3AS",
258
273
  "skip_get_url": true,
@@ -336,6 +351,11 @@
336
351
  "wiki_name": "Environment First",
337
352
  "wiki_note": "For properties with collections managed by Environment First, such as Lewes and Eastbourne.\nReplace the XXXXXXXXXXX with the UPRN of your property - you can use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find this."
338
353
  },
354
+ "EppingForestDistrictCouncil": {
355
+ "postcode": "IG9 6EP",
356
+ "url": "https://eppingforestdc.maps.arcgis.com/apps/instant/lookup/index.html?appid=bfca32b46e2a47cd9c0a84f2d8cdde17&find=IG9%206EP",
357
+ "wiki_name": "Epping Forest District Council"
358
+ },
339
359
  "ErewashBoroughCouncil": {
340
360
  "skip_get_url": true,
341
361
  "uprn": "10003582028",
@@ -343,7 +363,7 @@
343
363
  "wiki_name": "Erewash Borough Council"
344
364
  },
345
365
  "FarehamBoroughCouncil": {
346
- "postcode": "PO14 4NR",
366
+ "postcode": "PO14 4NR",
347
367
  "skip_get_url": true,
348
368
  "url": "https://www.fareham.gov.uk/internetlookups/search_data.aspx?type=JSON&list=DomesticBinCollections&Road=&Postcode=PO14%204NR",
349
369
  "wiki_name": "Fareham Borough Council"
@@ -427,6 +447,15 @@
427
447
  "wiki_name": "High Peak Council",
428
448
  "wiki_note": "Pass the name of the street with the house number parameter, wrapped in double quotes"
429
449
  },
450
+ "HounslowCouncil": {
451
+ "house_number": "17A LAMPTON PARK ROAD, HOUNSLOW",
452
+ "postcode": "TW3 4HS",
453
+ "skip_get_url": true,
454
+ "uprn": "10091596698",
455
+ "url": "https://www.hounslow.gov.uk/info/20272/recycling_and_waste_collection_day_finder",
456
+ "web_driver": "http://selenium:4444",
457
+ "wiki_name": "HounslowCouncil"
458
+ },
430
459
  "HullCityCouncil": {
431
460
  "skip_get_url": true,
432
461
  "uprn": "21033995",
@@ -561,7 +590,7 @@
561
590
  "postcode": "RH4 1SJ",
562
591
  "skip_get_url": true,
563
592
  "uprn": "200000171235",
564
- "url": "https://molevalley.cloudmappin.com/mmv/",
593
+ "url": "https://myproperty.molevalley.gov.uk/molevalley/",
565
594
  "wiki_name": "Mole Valley District Council",
566
595
  "wiki_note": "UPRN can only be parsed with a valid postcode."
567
596
  },
@@ -834,6 +863,15 @@
834
863
  "url": "https://beta.southglos.gov.uk/waste-and-recycling-collection-date",
835
864
  "wiki_name": "South Gloucestershire Council"
836
865
  },
866
+ "SouthKestevenDistrictCouncil": {
867
+ "house_number": "2 Althorpe Close, Market Deeping, PE6 8BL",
868
+ "postcode": "PE68BL",
869
+ "skip_get_url": true,
870
+ "url": "https://pre.southkesteven.gov.uk/BinSearch.aspx",
871
+ "web_driver": "http://selenium:4444",
872
+ "wiki_name": "SouthKestevenDistrictCouncil",
873
+ "wiki_note": ""
874
+ },
837
875
  "SouthLanarkshireCouncil": {
838
876
  "url": "https://www.southlanarkshire.gov.uk/directory_record/579973/abbeyhill_crescent_lesmahagow",
839
877
  "wiki_command_url_override": "https://www.southlanarkshire.gov.uk/directory_record/XXXXX/XXXXX",
@@ -898,6 +936,13 @@
898
936
  "url": "https://www.stratford.gov.uk/waste-recycling/when-we-collect.cfm/part/calendar",
899
937
  "wiki_name": "Stratford Upon Avon Council"
900
938
  },
939
+ "StroudDistrictCouncil": {
940
+ "postcode": "GL10 3BH",
941
+ "uprn": "100120512183",
942
+ "url": "https://www.stroud.gov.uk/my-house?uprn=100120512183&postcode=GL10+3BH",
943
+ "wiki_name": "Stroud District Council",
944
+ "wiki_note": "Find your uprn and replace it in the url do the same for the postcode."
945
+ },
901
946
  "SunderlandCityCouncil": {
902
947
  "house_number": "13",
903
948
  "postcode": "SR4 6BJ",
@@ -932,6 +977,14 @@
932
977
  "url": "https://dac.telford.gov.uk/bindayfinder/",
933
978
  "wiki_name": "Telford and Wrekin Co-operative Council"
934
979
  },
980
+ "TendringDistrictCouncil": {
981
+ "postcode": "CO15 4EU",
982
+ "skip_get_url": true,
983
+ "uprn": "100090604247",
984
+ "url": "https://tendring-self.achieveservice.com/en/service/Rubbish_and_recycling_collection_days",
985
+ "web_driver": "http://selenium:4444",
986
+ "wiki_name": "Tendring District Council"
987
+ },
935
988
  "TestValleyBoroughCouncil": {
936
989
  "postcode": "SO51 9ZD",
937
990
  "skip_get_url": true,
@@ -980,6 +1033,16 @@
980
1033
  "wiki_name": "Wakefield City Council",
981
1034
  "wiki_note": "Follow the instructions [here](https://www.wakefield.gov.uk/where-i-live/) until you get the page that includes a \"Bin Collections\" section then copy the URL and replace the URL in the command."
982
1035
  },
1036
+ "WalthamForest": {
1037
+ "house_number": "17 Chingford Road, Walthamstow",
1038
+ "postcode": "E17 4PW",
1039
+ "skip_get_url": true,
1040
+ "uprn": "200001415697",
1041
+ "url": "https://portal.walthamforest.gov.uk/AchieveForms/?mode=fill&consentMessage=yes&form_uri=sandbox-publish://AF-Process-d62ccdd2-3de9-48eb-a229-8e20cbdd6393/AF-Stage-8bf39bf9-5391-4c24-857f-0dc2025c67f4/definition.json&process=1&process_uri=sandbox-processes://AF-Process-d62ccdd2-3de9-48eb-a229-8e20cbdd6393&process_id=AF-Process-d62ccdd2-3de9-48eb-a229-8e20cbdd6393",
1042
+ "web_driver": "http://selenium:4444",
1043
+ "wiki_name": "Waltham Forest",
1044
+ "wiki_note": "Use to find your UPRN https://uprn.uk/"
1045
+ },
983
1046
  "WarwickDistrictCouncil": {
984
1047
  "url": "https://estates7.warwickdc.gov.uk/PropertyPortal/Property/Recycling/100070263793",
985
1048
  "wiki_command_url_override": "https://estates7.warwickdc.gov.uk/PropertyPortal/Property/Recycling/XXXXXXXX",
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  import traceback
3
3
  from typing import Any, Generator, Callable
4
+ import json
4
5
 
5
6
  import pytest
6
7
  from pytest_bdd import scenario, given, when, then, parsers
@@ -11,10 +12,26 @@ from uk_bin_collection.uk_bin_collection import collect_data
11
12
 
12
13
  logging.basicConfig(level=logging.INFO, format="%(levelname)s - %(message)s")
13
14
 
15
+
16
+ def get_council_list():
17
+ json_file_path = "uk_bin_collection/tests/input.json" # Specify the correct path to the JSON file
18
+ with open(json_file_path, "r") as file:
19
+ data = json.load(file)
20
+ logging.info(f"Council List: {list(data.keys())}")
21
+ return list(data.keys())
22
+
23
+
24
+ @pytest.fixture(params=get_council_list())
25
+ def council(request):
26
+ print(f"Running test for council: {request.param}")
27
+ return request.param
28
+
29
+
14
30
  @scenario("../features/validate_council_outputs.feature", "Validate Council Output")
15
- def test_scenario_outline() -> None:
31
+ def test_scenario_outline(council) -> None:
16
32
  pass
17
33
 
34
+
18
35
  def handle_test_errors(func: Callable[..., Any]) -> Callable[..., Any]:
19
36
  @wraps(func)
20
37
  def wrapper(*args: Any, **kwargs: Any) -> Any:
@@ -24,30 +41,37 @@ def handle_test_errors(func: Callable[..., Any]) -> Callable[..., Any]:
24
41
  logging.error(f"Error in test '{func.__name__}': {e}")
25
42
  logging.error(traceback.format_exc())
26
43
  raise e
44
+
27
45
  return wrapper
28
46
 
29
- @pytest.fixture
30
- @handle_test_errors
31
- def context() -> Generator[Any, None, None]:
32
- class Context:
33
- metadata: dict[str, Any]
34
- council: str
35
- parse_result: Any
36
47
 
48
+ class Context:
49
+ def __init__(self):
50
+ self.metadata: dict[str, Any] = {}
51
+ self.council: str = ""
52
+ self.parse_result: Any = None
53
+
54
+
55
+ @pytest.fixture(scope="module")
56
+ def context():
37
57
  return Context()
38
58
 
59
+
39
60
  @handle_test_errors
40
- @given(parsers.parse("the council: {council_name}"))
41
- def get_council_step(context: Any, council_name: str) -> None:
61
+ @given(parsers.parse("the council"))
62
+ def get_council_step(context, council) -> None:
42
63
  council_input_data = file_handler.load_json_file("input.json")
43
- context.metadata = council_input_data[council_name]
64
+ context.metadata = council_input_data[council]
65
+ context.council = council
66
+
44
67
 
45
68
  @handle_test_errors
46
- @when(parsers.parse("we scrape the data from {council}"))
47
- def scrape_step(context: Any, council: str, headless_mode: str, local_browser: str, selenium_url: str) -> None:
48
- context.council = council
69
+ @when(parsers.parse("we scrape the data from the council"))
70
+ def scrape_step(
71
+ context: Any, headless_mode: str, local_browser: str, selenium_url: str
72
+ ) -> None:
49
73
 
50
- args = [council, context.metadata["url"]]
74
+ args = [context.council, context.metadata["url"]]
51
75
 
52
76
  if "uprn" in context.metadata:
53
77
  uprn = context.metadata["uprn"]
@@ -75,13 +99,17 @@ def scrape_step(context: Any, council: str, headless_mode: str, local_browser: s
75
99
  CollectData.set_args(args)
76
100
  context.parse_result = CollectData.run()
77
101
 
102
+
78
103
  @handle_test_errors
79
104
  @then("the result is valid json")
80
105
  def validate_json_step(context: Any) -> None:
81
106
  assert file_handler.validate_json(context.parse_result), "Invalid JSON output"
82
107
 
108
+
83
109
  @handle_test_errors
84
110
  @then("the output should validate against the schema")
85
111
  def validate_output_step(context: Any) -> None:
86
112
  council_schema = file_handler.load_json_file("output.schema")
87
- assert file_handler.validate_json_schema(context.parse_result, council_schema), "Schema validation failed"
113
+ assert file_handler.validate_json_schema(
114
+ context.parse_result, council_schema
115
+ ), "Schema validation failed"
@@ -332,8 +332,10 @@ def test_contains_date_with_mixed_content():
332
332
 
333
333
 
334
334
  def test_create_webdriver_local():
335
- result = create_webdriver(None, headless=True, user_agent="FireFox", session_name="test-session")
336
- assert result.name in ["chrome","chrome-headless-shell"]
335
+ result = create_webdriver(
336
+ None, headless=True, user_agent="FireFox", session_name="test-session"
337
+ )
338
+ assert result.name in ["chrome", "chrome-headless-shell"]
337
339
 
338
340
 
339
341
  def test_create_webdriver_remote_failure():
@@ -258,7 +258,10 @@ def contains_date(string, fuzzy=False) -> bool:
258
258
 
259
259
 
260
260
  def create_webdriver(
261
- web_driver: str = None, headless: bool = True, user_agent: str = None, session_name: str = None
261
+ web_driver: str = None,
262
+ headless: bool = True,
263
+ user_agent: str = None,
264
+ session_name: str = None,
262
265
  ) -> webdriver.Chrome:
263
266
  """
264
267
  Create and return a Chrome WebDriver configured for optional headless operation.
@@ -0,0 +1,110 @@
1
+ import time
2
+ from datetime import datetime
3
+
4
+ from selenium.webdriver.support.ui import Select
5
+ from bs4 import BeautifulSoup
6
+ from selenium.webdriver.common.by import By
7
+ from selenium.webdriver.support import expected_conditions as EC
8
+ from selenium.webdriver.support.ui import Select
9
+ from selenium.webdriver.support.wait import WebDriverWait
10
+ from selenium.webdriver.common.keys import Keys
11
+
12
+ from uk_bin_collection.uk_bin_collection.common import *
13
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
14
+
15
+
16
+ # import the wonderful Beautiful Soup and the URL grabber
17
+ class CouncilClass(AbstractGetBinDataClass):
18
+ """
19
+ Concrete classes have to implement all abstract operations of the
20
+ base class. They can also override some operations with a default
21
+ implementation.
22
+ """
23
+
24
+ def parse_data(self, page: str, **kwargs) -> dict:
25
+ driver = None
26
+ try:
27
+ # Make a BS4 object
28
+
29
+ page = "https://www.chichester.gov.uk/checkyourbinday"
30
+
31
+ user_postcode = kwargs.get("postcode")
32
+ user_uprn = kwargs.get("uprn")
33
+ web_driver = kwargs.get("web_driver")
34
+ headless = kwargs.get("headless")
35
+ house_number = kwargs.get("paon")
36
+
37
+ driver = create_webdriver(web_driver, headless, None, __name__)
38
+ driver.get(page)
39
+
40
+ wait = WebDriverWait(driver, 60)
41
+
42
+ inputElement_postcodesearch = wait.until(
43
+ EC.visibility_of_element_located(
44
+ (By.ID, "WASTECOLLECTIONCALENDARV5_CALENDAR_ADDRESSLOOKUPPOSTCODE")
45
+ )
46
+ )
47
+
48
+ inputElement_postcodesearch.send_keys(user_postcode)
49
+
50
+ inputElement_postcodesearch_btn = wait.until(
51
+ EC.visibility_of_element_located(
52
+ (By.ID, "WASTECOLLECTIONCALENDARV5_CALENDAR_ADDRESSLOOKUPSEARCH")
53
+ )
54
+ )
55
+ inputElement_postcodesearch_btn.send_keys(Keys.ENTER)
56
+
57
+ inputElement_select_address = wait.until(
58
+ EC.element_to_be_clickable(
59
+ (By.ID, "WASTECOLLECTIONCALENDARV5_CALENDAR_ADDRESSLOOKUPADDRESS")
60
+ )
61
+ )
62
+ dropdown_element = driver.find_element(
63
+ By.ID, "WASTECOLLECTIONCALENDARV5_CALENDAR_ADDRESSLOOKUPADDRESS"
64
+ )
65
+
66
+ # Now create a Select object based on the found element
67
+ dropdown = Select(dropdown_element)
68
+
69
+ # Select the option by visible text
70
+ dropdown.select_by_visible_text(house_number)
71
+
72
+ results = wait.until(
73
+ EC.element_to_be_clickable(
74
+ (By.CLASS_NAME, "bin-collection-dates-container")
75
+ )
76
+ )
77
+
78
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
79
+ soup.prettify()
80
+
81
+ # Extract data from the table
82
+ bin_collection_data = []
83
+ rows = soup.find(
84
+ "table", class_="defaultgeneral bin-collection-dates"
85
+ ).find_all("tr")
86
+ for row in rows:
87
+ cells = row.find_all("td")
88
+ if cells:
89
+ date_str = cells[0].text.strip()
90
+ bin_type = cells[1].text.strip()
91
+ # Convert date string to the required format DD/MM/YYYY
92
+ date_obj = datetime.strptime(date_str, "%d %B %Y")
93
+ date_formatted = date_obj.strftime(date_format)
94
+ bin_collection_data.append(
95
+ {"collectionDate": date_formatted, "type": bin_type}
96
+ )
97
+
98
+ # Convert to JSON
99
+ json_data = {"bins": bin_collection_data}
100
+
101
+ except Exception as e:
102
+ # Here you can log the exception if needed
103
+ print(f"An error occurred: {e}")
104
+ # Optionally, re-raise the exception if you want it to propagate
105
+ raise
106
+ finally:
107
+ # This block ensures that the driver is closed regardless of an exception
108
+ if driver:
109
+ driver.quit()
110
+ return json_data
@@ -35,7 +35,7 @@ class CouncilClass(AbstractGetBinDataClass):
35
35
 
36
36
  data = {"bins": []}
37
37
 
38
- titles = [title.text for title in soup.select(".title")]
38
+ titles = [title.text for title in soup.select(".block-title")]
39
39
  collection_tag = soup.body.find_all(
40
40
  "div", {"class": "col-md-6 col-sm-6 col-xs-6"}, string="Next collection"
41
41
  )
@@ -0,0 +1,44 @@
1
+ from bs4 import BeautifulSoup
2
+ from uk_bin_collection.uk_bin_collection.common import *
3
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
+
5
+
6
+ # import the wonderful Beautiful Soup and the URL grabber
7
+ class CouncilClass(AbstractGetBinDataClass):
8
+ """
9
+ Concrete classes have to implement all abstract operations of the
10
+ base class. They can also override some operations with a default
11
+ implementation.
12
+ """
13
+
14
+ def parse_data(self, page: str, **kwargs) -> dict:
15
+ # Make a BS4 object
16
+ soup = BeautifulSoup(page.text, features="html.parser")
17
+ soup.prettify()
18
+
19
+ # Extract data
20
+ bin_data = {
21
+ "bins": []
22
+ }
23
+
24
+ # Find the table containing the bin collection data
25
+ table = soup.find('table', {'class': 'eb-EVDNdR1G-tableContent'})
26
+
27
+ if table:
28
+ rows = table.find_all('tr', class_='eb-EVDNdR1G-tableRow')
29
+
30
+ for row in rows:
31
+ columns = row.find_all('td')
32
+ if len(columns) >= 4:
33
+ collection_type = columns[1].get_text(strip=True)
34
+ collection_date = columns[3].get_text(strip=True)
35
+
36
+ # Validate collection_date format
37
+ if re.match(r"\d{2}/\d{2}/\d{4}", collection_date):
38
+ bin_entry = {
39
+ "type": collection_type,
40
+ "collectionDate": collection_date
41
+ }
42
+ bin_data["bins"].append(bin_entry)
43
+
44
+ return bin_data
@@ -4,9 +4,10 @@ import re
4
4
  from uk_bin_collection.uk_bin_collection.common import * # Consider specific imports
5
5
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
6
6
 
7
+
7
8
  class CouncilClass(AbstractGetBinDataClass):
8
9
  def parse_data(self, page: str, **kwargs) -> dict:
9
- soup = BeautifulSoup(page.text, 'html.parser')
10
+ soup = BeautifulSoup(page.text, "html.parser")
10
11
 
11
12
  bins_data = {"bins": []}
12
13
  bin_collections = []
@@ -23,7 +24,9 @@ class CouncilClass(AbstractGetBinDataClass):
23
24
  if service_name and next_service:
24
25
  bin_type = service_name.get_text().replace("Collection", "bin").strip()
25
26
  date_span = next_service.find("span", {"class": "table-label"})
26
- date_text = date_span.next_sibling.get_text().strip() if date_span else None
27
+ date_text = (
28
+ date_span.next_sibling.get_text().strip() if date_span else None
29
+ )
27
30
 
28
31
  if date_text and re.match(r"\d{2}/\d{2}/\d{4}", date_text):
29
32
  try:
@@ -33,9 +36,11 @@ class CouncilClass(AbstractGetBinDataClass):
33
36
  continue
34
37
 
35
38
  for bin_type, bin_date in sorted(bin_collections, key=lambda x: x[1]):
36
- bins_data["bins"].append({
37
- "type": bin_type.capitalize(),
38
- "collectionDate": bin_date.strftime("%d/%m/%Y"),
39
- })
39
+ bins_data["bins"].append(
40
+ {
41
+ "type": bin_type.capitalize(),
42
+ "collectionDate": bin_date.strftime("%d/%m/%Y"),
43
+ }
44
+ )
40
45
 
41
46
  return bins_data
@@ -0,0 +1,51 @@
1
+ from bs4 import BeautifulSoup
2
+ from uk_bin_collection.uk_bin_collection.common import *
3
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
4
+ from selenium import webdriver
5
+ from selenium.webdriver.common.keys import Keys
6
+ from selenium.webdriver.common.by import By
7
+ from selenium.webdriver.support.ui import WebDriverWait
8
+ from selenium.webdriver.support import expected_conditions as EC
9
+ from datetime import datetime
10
+ from uk_bin_collection.uk_bin_collection.common import date_format
11
+
12
+
13
+ class CouncilClass(AbstractGetBinDataClass):
14
+ def parse_data(self, page: str, **kwargs) -> dict:
15
+ postcode = kwargs.get("postcode", "")
16
+ web_driver = kwargs.get("web_driver")
17
+ headless = kwargs.get("headless")
18
+
19
+ options = webdriver.ChromeOptions()
20
+ if headless:
21
+ options.add_argument("--headless")
22
+ driver = create_webdriver(web_driver, headless)
23
+
24
+ try:
25
+ driver.get(
26
+ f"https://eppingforestdc.maps.arcgis.com/apps/instant/lookup/index.html?appid=bfca32b46e2a47cd9c0a84f2d8cdde17&find={postcode}"
27
+ )
28
+ wait = WebDriverWait(driver, 10)
29
+ WebDriverWait(driver, 10).until(
30
+ EC.visibility_of_element_located(
31
+ (By.CSS_SELECTOR, ".esri-feature-content")
32
+ )
33
+ )
34
+ html_content = driver.page_source
35
+
36
+ soup = BeautifulSoup(html_content, "html.parser")
37
+ bin_info_divs = soup.select(".esri-feature-content p")
38
+ data = {"bins": []}
39
+ for div in bin_info_divs:
40
+ if "collection day is" in div.text:
41
+ bin_type, date_str = div.text.split(" collection day is ")
42
+ bin_dates = datetime.strptime(
43
+ date_str.strip(), "%d/%m/%Y"
44
+ ).strftime(date_format)
45
+ data["bins"].append(
46
+ {"type": bin_type.strip(), "collectionDate": bin_dates}
47
+ )
48
+
49
+ return data
50
+ finally:
51
+ driver.quit()