Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scanning Yellowstone crashes with "AttributeError: 'list' object has no attribute 'items' #344

Closed
zhazell opened this issue May 1, 2024 · 5 comments · Fixed by #346
Closed
Assignees
Labels
bug Something isn't working released

Comments

@zhazell
Copy link

zhazell commented May 1, 2024

Describe the bug

When having a continuous scan run, it seems to error quite frequently with "list object has no attribute items" error. Requires me to start the command again. It has happened over the last 2 weeks a dozen times.

Original Camply Command (with --debug)

camply --provider Yellowstone campsites --campground YLYF:RV --campground YLYM:RV --start-date 2024-06-13 --end-date 2024-06-16 --nights 3 --search-forever --notifications pushover --polling-interval 5 --debug

Additional context

[2024-05-01 07:37:59] INFO     ⛰  Yellowstone National Park, USA (#1) - 🏕  Fishing Bridge RV Park (YLYF:RV)
[2024-05-01 07:37:59] INFO     ⛰  Yellowstone National Park, USA (#1) - 🏕  Madison Campground (YLYM:RV)
[2024-05-01 07:37:59] INFO     Searching for Yellowstone Lodging Availability: June, 2024
[2024-05-01 07:37:59] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 07:38:00] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/availability/hotels/yellowstonenationalparklodges?date=2024-06-01&limit=31&rate_code=INTERNET&nights=3
                               HTTP/1.1" 200 None
[2024-05-01 07:38:00] INFO     Exception encountered, emitting notification last gasp.
[2024-05-01 07:38:00] DEBUG    SilentNotification: camply encountered an error and exited 😟 [2024-05-01 07:38:00] - (AttributeError) 'list' object has no attribute 'items'
[2024-05-01 07:38:00] DEBUG    Starting new HTTPS connection (1): api.pushover.net:443
[2024-05-01 07:38:00] DEBUG    https://api.pushover.net:443 "POST
                               /1/messages.json?token=REMOVED&user=HIDDEN&message=camply+encountered+an+error+and+exited+%F0%9F%98%
                               9F+%5B2024-05-01+07%3A38%3A00%5D+-+%28AttributeError%29+%27list%27+object+has+no+attribute+%27items%27 HTTP/1.1" 200 None
[2024-05-01 07:38:00] CAMPLY   Exiting camply 👋



╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/base_search.py:57 │
│ 4 in get_matching_campsites                                                                      │
│                                                                                                  │
│    571 │   │   """                                                                               │
│    572 │   │   if continuous is True or search_once is True:                                     │
│    573 │   │   │   try:                                                                          │
│ ❱  574 │   │   │   │   self._search_campsites_continuous(                                        │
│    575 │   │   │   │   │   log=log,                                                              │
│    576 │   │   │   │   │   verbose=verbose,                                                      │
│    577 │   │   │   │   │   polling_interval=polling_interval,                                    │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │            continuous = True                                                                 │ │
│ │                   log = True                                                                 │ │
│ │ notification_provider = ['pushover']                                                         │ │
│ │      notify_first_try = False                                                                │ │
│ │      polling_interval = 5.0                                                                  │ │
│ │        search_forever = True                                                                 │ │
│ │           search_once = False                                                                │ │
│ │                  self = <camply.search.search_yellowstone.SearchYellowstone object at        │ │
│ │                         0x7f8451804a00>                                                      │ │
│ │               verbose = True                                                                 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/base_search.py:50 │
│ 8 in _search_campsites_continuous                                                                │
│                                                                                                  │
│    505 │   │   continuous_search_attempts = 1                                                    │
│    506 │   │   while continuous_search is True:                                                  │
│    507 │   │   │   starting_count = len(self.campsites_found)                                    │
│ ❱  508 │   │   │   self._continuous_search_retry(                                                │
│    509 │   │   │   │   log=log,                                                                  │
│    510 │   │   │   │   verbose=verbose,                                                          │
│    511 │   │   │   │   polling_interval=polling_interval,                                        │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │          continuous_search = True                                                            │ │
│ │ continuous_search_attempts = 1                                                               │ │
│ │                        log = True                                                            │ │
│ │      notification_provider = ['pushover']                                                    │ │
│ │           notify_first_try = False                                                           │ │
│ │           polling_interval = 5.0                                                             │ │
│ │   polling_interval_minutes = 5                                                               │ │
│ │             search_forever = True                                                            │ │
│ │                search_once = False                                                           │ │
│ │                       self = <camply.search.search_yellowstone.SearchYellowstone object at   │ │
│ │                              0x7f8451804a00>                                                 │ │
│ │             starting_count = 0                                                               │ │
│ │                    verbose = True                                                            │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/base_search.py:35 │
│ 4 in _continuous_search_retry                                                                    │
│                                                                                                  │
│    351 │   │   │   retry=tenacity.retry_if_exception_type(CampsiteNotFoundError),                │
│    352 │   │   │   wait=tenacity.wait.wait_fixed(int(polling_interval_minutes) * 60),            │
│    353 │   │   )                                                                                 │
│ ❱  354 │   │   matching_campsites = retryer.__call__(                                            │
│    355 │   │   │   fn=self._search_matching_campsites_available,                                 │
│    356 │   │   │   log=False,                                                                    │
│    357 │   │   │   verbose=False,                                                                │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ continuous_search_attempts = 1                                                               │ │
│ │                        log = True                                                            │ │
│ │      notification_provider = ['pushover']                                                    │ │
│ │           notify_first_try = False                                                           │ │
│ │           polling_interval = 5.0                                                             │ │
│ │   polling_interval_minutes = 5                                                               │ │
│ │                    retryer = <Retrying object at 0x7f8451805ff0                              │ │
│ │                              (stop=<tenacity.stop._stop_never object at 0x7f845a4f3850>,     │ │
│ │                              wait=<tenacity.wait.wait_fixed object at 0x7f8451805f90>,       │ │
│ │                              sleep=<function sleep at 0x7f845a50b640>,                       │ │
│ │                              retry=<tenacity.retry.retry_if_exception_type object at         │ │
│ │                              0x7f8451805b10>, before=<function before_nothing at             │ │
│ │                              0x7f845a52d1b0>, after=<function after_nothing at               │ │
│ │                              0x7f845a52d480>)>                                               │ │
│ │                search_once = False                                                           │ │
│ │                       self = <camply.search.search_yellowstone.SearchYellowstone object at   │ │
│ │                              0x7f8451804a00>                                                 │ │
│ │                    verbose = True                                                            │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/tenacity/__init__.py:379 in     │
│ __call__                                                                                         │
│                                                                                                  │
│   376 │   │                                                                                      │
│   377 │   │   retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)   │
│   378 │   │   while True:                                                                        │
│ ❱ 379 │   │   │   do = self.iter(retry_state=retry_state)                                        │
│   380 │   │   │   if isinstance(do, DoAttempt):                                                  │
│   381 │   │   │   │   try:                                                                       │
│   382 │   │   │   │   │   result = fn(*args, **kwargs)                                           │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │        args = ()                                                                             │ │
│ │          do = <tenacity.DoAttempt object at 0x7f84547965c0>                                  │ │
│ │          fn = <bound method BaseCampingSearch._search_matching_campsites_available of        │ │
│ │               <camply.search.search_yellowstone.SearchYellowstone object at 0x7f8451804a00>> │ │
│ │      kwargs = {'log': False, 'verbose': False, 'raise_error': True}                          │ │
│ │ retry_state = <RetryCallState 140206279776608: attempt #16; slept for 4500.0; last result:   │ │
│ │               failed (AttributeError 'list' object has no attribute 'items')>                │ │
│ │        self = <Retrying object at 0x7f8451805ff0 (stop=<tenacity.stop._stop_never object at  │ │
│ │               0x7f845a4f3850>, wait=<tenacity.wait.wait_fixed object at 0x7f8451805f90>,     │ │
│ │               sleep=<function sleep at 0x7f845a50b640>,                                      │ │
│ │               retry=<tenacity.retry.retry_if_exception_type object at 0x7f8451805b10>,       │ │
│ │               before=<function before_nothing at 0x7f845a52d1b0>, after=<function            │ │
│ │               after_nothing at 0x7f845a52d480>)>                                             │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/tenacity/__init__.py:314 in     │
│ iter                                                                                             │
│                                                                                                  │
│   311 │   │                                                                                      │
│   312 │   │   is_explicit_retry = fut.failed and isinstance(fut.exception(), TryAgain)           │
│   313 │   │   if not (is_explicit_retry or self.retry(retry_state)):                             │
│ ❱ 314 │   │   │   return fut.result()                                                            │
│   315 │   │                                                                                      │
│   316 │   │   if self.after is not None:                                                         │
│   317 │   │   │   self.after(retry_state)                                                        │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │               fut = <Future at 0x7f8452024d00 state=finished raised AttributeError>          │ │
│ │ is_explicit_retry = False                                                                    │ │
│ │       retry_state = <RetryCallState 140206279776608: attempt #16; slept for 4500.0; last     │ │
│ │                     result: failed (AttributeError 'list' object has no attribute 'items')>  │ │
│ │              self = <Retrying object at 0x7f8451805ff0 (stop=<tenacity.stop._stop_never      │ │
│ │                     object at 0x7f845a4f3850>, wait=<tenacity.wait.wait_fixed object at      │ │
│ │                     0x7f8451805f90>, sleep=<function sleep at 0x7f845a50b640>,               │ │
│ │                     retry=<tenacity.retry.retry_if_exception_type object at 0x7f8451805b10>, │ │
│ │                     before=<function before_nothing at 0x7f845a52d1b0>, after=<function      │ │
│ │                     after_nothing at 0x7f845a52d480>)>                                       │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /usr/lib/python3.10/concurrent/futures/_base.py:451 in result                                    │
│                                                                                                  │
│   448 │   │   │   │   if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:                     │
│   449 │   │   │   │   │   raise CancelledError()                                                 │
│   450 │   │   │   │   elif self._state == FINISHED:                                              │
│ ❱ 451 │   │   │   │   │   return self.__get_result()                                             │
│   452 │   │   │   │                                                                              │
│   453 │   │   │   │   self._condition.wait(timeout)                                              │
│   454                                                                                            │
│                                                                                                  │
│ ╭──── locals ────╮                                                                               │
│ │    self = None │                                                                               │
│ │ timeout = None │                                                                               │
│ ╰────────────────╯                                                                               │
│                                                                                                  │
│ /usr/lib/python3.10/concurrent/futures/_base.py:403 in __get_result                              │
│                                                                                                  │
│   400 │   def __get_result(self):                                                                │
│   401 │   │   if self._exception:                                                                │
│   402 │   │   │   try:                                                                           │
│ ❱ 403 │   │   │   │   raise self._exception                                                      │
│   404 │   │   │   finally:                                                                       │
│   405 │   │   │   │   # Break a reference cycle with the exception in self._exception            │
│   406 │   │   │   │   self = None                                                                │
│                                                                                                  │
│ ╭── locals ───╮                                                                                  │
│ │ self = None │                                                                                  │
│ ╰─────────────╯                                                                                  │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/tenacity/__init__.py:382 in     │
│ __call__                                                                                         │
│                                                                                                  │
│   379 │   │   │   do = self.iter(retry_state=retry_state)                                        │
│   380 │   │   │   if isinstance(do, DoAttempt):                                                  │
│   381 │   │   │   │   try:                                                                       │
│ ❱ 382 │   │   │   │   │   result = fn(*args, **kwargs)                                           │
│   383 │   │   │   │   except BaseException:  # noqa: B902                                        │
│   384 │   │   │   │   │   retry_state.set_exception(sys.exc_info())  # type: ignore[arg-type]    │
│   385 │   │   │   │   else:                                                                      │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │        args = ()                                                                             │ │
│ │          do = <tenacity.DoAttempt object at 0x7f84547965c0>                                  │ │
│ │          fn = <bound method BaseCampingSearch._search_matching_campsites_available of        │ │
│ │               <camply.search.search_yellowstone.SearchYellowstone object at 0x7f8451804a00>> │ │
│ │      kwargs = {'log': False, 'verbose': False, 'raise_error': True}                          │ │
│ │ retry_state = <RetryCallState 140206279776608: attempt #16; slept for 4500.0; last result:   │ │
│ │               failed (AttributeError 'list' object has no attribute 'items')>                │ │
│ │        self = <Retrying object at 0x7f8451805ff0 (stop=<tenacity.stop._stop_never object at  │ │
│ │               0x7f845a4f3850>, wait=<tenacity.wait.wait_fixed object at 0x7f8451805f90>,     │ │
│ │               sleep=<function sleep at 0x7f845a50b640>,                                      │ │
│ │               retry=<tenacity.retry.retry_if_exception_type object at 0x7f8451805b10>,       │ │
│ │               before=<function before_nothing at 0x7f845a52d1b0>, after=<function            │ │
│ │               after_nothing at 0x7f845a52d480>)>                                             │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/base_search.py:24 │
│ 6 in _search_matching_campsites_available                                                        │
│                                                                                                  │
│    243 │   │   List[AvailableCampsite]                                                           │
│    244 │   │   """                                                                               │
│    245 │   │   matching_campgrounds = []                                                         │
│ ❱  246 │   │   for camp in self.get_all_campsites():                                             │
│    247 │   │   │   if all(                                                                       │
│    248 │   │   │   │   [                                                                         │
│    249 │   │   │   │   │   self._compare_date_overlap(campsite=camp) is True,                    │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │                  log = False                                                                 │ │
│ │ matching_campgrounds = []                                                                    │ │
│ │          raise_error = True                                                                  │ │
│ │                 self = <camply.search.search_yellowstone.SearchYellowstone object at         │ │
│ │                        0x7f8451804a00>                                                       │ │
│ │              verbose = False                                                                 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/search_yellowston │
│ e.py:87 in get_all_campsites                                                                     │
│                                                                                                  │
│    84 │   │   this_month = datetime.now().date().replace(day=1)                                  │
│    85 │   │   for month in self.search_months:                                                   │
│    86 │   │   │   if month >= this_month:                                                        │
│ ❱  87 │   │   │   │   all_campsites += self.campsite_finder.get_monthly_campsites(               │
│    88 │   │   │   │   │   month=month, nights=None if self.nights == 1 else self.nights          │
│    89 │   │   │   │   )                                                                          │
│    90 │   │   matching_campsites = self._filter_campsites_to_campgrounds(                        │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │          all_campsites = []                                                                  │ │
│ │                  month = datetime.date(2024, 6, 1)                                           │ │
│ │ searchable_campgrounds = {'YLYF:RV', 'YLYM:RV'}                                              │ │
│ │                   self = <camply.search.search_yellowstone.SearchYellowstone object at       │ │
│ │                          0x7f8451804a00>                                                     │ │
│ │             this_month = datetime.date(2024, 5, 1)                                           │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/providers/xanterra/yello │
│ wstone_lodging.py:417 in get_monthly_campsites                                                   │
│                                                                                                  │
│   414 │   │   availability_found = self._get_monthly_availability(                               │
│   415 │   │   │   month=search_date, nights=nights                                               │
│   416 │   │   )                                                                                  │
│ ❱ 417 │   │   availability = XantResortData(**availability_found)                                │
│   418 │   │   monthly_campsites = self._compile_campground_availabilities(                       │
│   419 │   │   │   availability=availability                                                      │
│   420 │   │   )                                                                                  │
│                                                                                                  │
│ ╭──────────────────── locals ────────────────────╮                                               │
│ │ availability_found = {'availability': []}      │                                               │
│ │              month = datetime.date(2024, 6, 1) │                                               │
│ │             nights = 3                         │                                               │
│ │                now = datetime.date(2024, 5, 1) │                                               │
│ │        search_date = datetime.date(2024, 6, 1) │                                               │
│ │               self = <Yellowstone>             │                                               │
│ ╰────────────────────────────────────────────────╯                                               │
│                                                                                                  │
│ in pydantic.main.BaseModel.__init__:339                                                          │
│                                                                                                  │
│ in pydantic.main.validate_model:1074                                                             │
│                                                                                                  │
│ in pydantic.fields.ModelField.validate:864                                                       │
│                                                                                                  │
│ in pydantic.fields.ModelField._apply_validators:1154                                             │
│                                                                                                  │
│ in pydantic.class_validators._generic_validator_cls.lambda4:304                                  │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/containers/api_responses │
│ .py:440 in parse_datetime                                                                        │
│                                                                                                  │
│   437 │   │   """                                                                                │
│   438 │   │   return {                                                                           │
│   439 │   │   │   datetime.datetime.strptime(x, "%m/%d/%Y").date(): y                            │
│ ❱ 440 │   │   │   for x, y in value.items()                                                      │
│   441 │   │   }                                                                                  │
│   442                                                                                            │
│   443                                                                                            │
│                                                                                                  │
│ ╭───────────────────────────── locals ─────────────────────────────╮                             │
│ │   cls = <class 'camply.containers.api_responses.XantResortData'> │                             │
│ │ value = []                                                       │                             │
│ ╰──────────────────────────────────────────────────────────────────╯                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'list' object has no attribute 'items'

The above exception was the direct cause of the following exception:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/zach/.local/bin/camply:8 in <module>                                                       │
│                                                                                                  │
│   5 from camply.cli import cli                                                                   │
│   6 if __name__ == '__main__':                                                                   │
│   7 │   sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])                         │
│ ❱ 8 │   sys.exit(cli())                                                                          │
│   9                                                                                              │
│                                                                                                  │
│ ╭─────────────────────── locals ───────────────────────╮                                         │
│ │ cli = <function cli at 0x7f84517f9240>               │                                         │
│ │  re = <module 're' from '/usr/lib/python3.10/re.py'> │                                         │
│ │ sys = <module 'sys' (built-in)>                      │                                         │
│ ╰──────────────────────────────────────────────────────╯                                         │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/cli.py:883 in cli        │
│                                                                                                  │
│   880 │   Camply Command Line Utility Wrapper                                                    │
│   881 │   """                                                                                    │
│   882 │   try:                                                                                   │
│ ❱ 883 │   │   camply_command_line()                                                              │
│   884 │   except KeyboardInterrupt:                                                              │
│   885 │   │   logger.debug("Handling Exit Request")                                              │
│   886 │   finally:                                                                               │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/core.py:1157 in __call__  │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/rich_click/rich_group.py:21 in  │
│ main                                                                                             │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/core.py:1078 in main      │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/core.py:1688 in invoke    │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/core.py:1434 in invoke    │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/core.py:783 in invoke     │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/click/decorators.py:45 in       │
│ new_func                                                                                         │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/cli.py:775 in campsites  │
│                                                                                                  │
│   772 │   │   )                                                                                  │
│   773 │   provider_class: Type[BaseCampingSearch] = CAMPSITE_SEARCH_PROVIDER[provider]           │
│   774 │   camping_finder: BaseCampingSearch = provider_class(**provider_kwargs)                  │
│ ❱ 775 │   camping_finder.get_matching_campsites(**search_kwargs)                                 │
│   776                                                                                            │
│   777                                                                                            │
│   778 @camply_command_line.command(cls=RichCommand)                                              │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │          campground = ('YLYF:RV', 'YLYM:RV')                                                 │ │
│ │      camping_finder = <camply.search.search_yellowstone.SearchYellowstone object at          │ │
│ │                       0x7f8451804a00>                                                        │ │
│ │            campsite = ()                                                                     │ │
│ │             context = CamplyContext(debug=True, provider='Yellowstone')                      │ │
│ │          continuous = False                                                                  │ │
│ │                 day = ()                                                                     │ │
│ │               debug = True                                                                   │ │
│ │            end_date = ('2024-06-16',)                                                        │ │
│ │           equipment = ()                                                                     │ │
│ │        equipment_id = None                                                                   │ │
│ │              nights = 3                                                                      │ │
│ │       notifications = ('pushover',)                                                          │ │
│ │    notify_first_try = None                                                                   │ │
│ │      offline_search = False                                                                  │ │
│ │ offline_search_path = None                                                                   │ │
│ │    polling_interval = 5                                                                      │ │
│ │            provider = 'Yellowstone'                                                          │ │
│ │      provider_class = <class 'camply.search.search_yellowstone.SearchYellowstone'>           │ │
│ │     provider_kwargs = {                                                                      │ │
│ │                       │   'search_window': SearchWindow(                                     │ │
│ │                       │   │   start_date=datetime.date(2024, 6, 13),                         │ │
│ │                       │   │   end_date=datetime.date(2024, 6, 16)                            │ │
│ │                       │   ),                                                                 │ │
│ │                       │   'recreation_area': [],                                             │ │
│ │                       │   'campgrounds': ['YLYF:RV', 'YLYM:RV'],                             │ │
│ │                       │   'campsites': [],                                                   │ │
│ │                       │   'weekends_only': False,                                            │ │
│ │                       │   'nights': 3,                                                       │ │
│ │                       │   'offline_search': False,                                           │ │
│ │                       │   'offline_search_path': None,                                       │ │
│ │                       │   'equipment': (),                                                   │ │
│ │                       │   'equipment_id': None,                                              │ │
│ │                       │   ... +1                                                             │ │
│ │                       }                                                                      │ │
│ │            rec_area = ()                                                                     │ │
│ │      search_forever = 'FLAG-SET'                                                             │ │
│ │       search_kwargs = {                                                                      │ │
│ │                       │   'log': True,                                                       │ │
│ │                       │   'verbose': True,                                                   │ │
│ │                       │   'continuous': True,                                                │ │
│ │                       │   'polling_interval': 5.0,                                           │ │
│ │                       │   'notify_first_try': False,                                         │ │
│ │                       │   'notification_provider': ['pushover'],                             │ │
│ │                       │   'search_forever': True,                                            │ │
│ │                       │   'search_once': False                                               │ │
│ │                       }                                                                      │ │
│ │         search_once = False                                                                  │ │
│ │          start_date = ('2024-06-13',)                                                        │ │
│ │            weekends = False                                                                  │ │
│ │         yaml_config = None                                                                   │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/search/base_search.py:58 │
│ 4 in get_matching_campsites                                                                      │
│                                                                                                  │
│    581 │   │   │   │   │   search_once=search_once,                                              │
│    582 │   │   │   │   )                                                                         │
│    583 │   │   │   except Exception as e:                                                        │
│ ❱  584 │   │   │   │   self.notifier.last_gasp(error=e)                                          │
│    585 │   │   │   │   raise e                                                                   │
│    586 │   │   else:                                                                             │
│    587 │   │   │   starting_count = len(self.campsites_found)                                    │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │            continuous = True                                                                 │ │
│ │                   log = True                                                                 │ │
│ │ notification_provider = ['pushover']                                                         │ │
│ │      notify_first_try = False                                                                │ │
│ │      polling_interval = 5.0                                                                  │ │
│ │        search_forever = True                                                                 │ │
│ │           search_once = False                                                                │ │
│ │                  self = <camply.search.search_yellowstone.SearchYellowstone object at        │ │
│ │                         0x7f8451804a00>                                                      │ │
│ │               verbose = True                                                                 │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/notifications/multi_prov │
│ ider_notifications.py:130 in last_gasp                                                           │
│                                                                                                  │
│   127 │   │   for provider in self.providers:                                                    │
│   128 │   │   │   if provider.last_gasp is True:                                                 │
│   129 │   │   │   │   provider.send_message(error_message)                                       │
│ ❱ 130 │   │   raise RuntimeError(error_message) from error                                       │
│   131                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   date_string = '2024-05-01 07:38:00'                                                        │ │
│ │         error = AttributeError("'list' object has no attribute 'items'")                     │ │
│ │ error_message = 'camply encountered an error and exited 😟 [2024-05-01 07:38:00] -           │ │
│ │                 (AttributeError'+40                                                          │ │
│ │  error_string = "'list' object has no attribute 'items'"                                     │ │
│ │      provider = <PushoverNotifications>                                                      │ │
│ │          self = <MultiNotifierProvider>                                                      │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
RuntimeError: camply encountered an error and exited 😟 [2024-05-01 07:38:00] - (AttributeError) 'list' object has no attribute 'items'
@zhazell zhazell added the bug Something isn't working label May 1, 2024
@github-actions github-actions bot added the triage This will looked at label May 1, 2024
@juftin
Copy link
Owner

juftin commented May 1, 2024

Thanks for reporting this. It's been a while since I've worked with the Yellowstone provider, sounds like their API is returning inconsistent results. I'll dig into this and see if I can't get it fixed up soon.

@zhazell
Copy link
Author

zhazell commented May 1, 2024

May not be related but I was looking over the console logs as it was running and noticed that it seems to be searching 3 campgrounds and I only specified two. YLYM and YLYF, but it's also doing an API call for YLYB (Bridge Bay Campground).

[2024-05-01 08:45:41] INFO     2 Matching Campgrounds Found
[2024-05-01 08:45:41] INFO     ⛰  Yellowstone National Park, USA (#1) - 🏕  Madison Campground (YLYM:RV)
[2024-05-01 08:45:41] INFO     ⛰  Yellowstone National Park, USA (#1) - 🏕  Fishing Bridge RV Park (YLYF:RV)
[2024-05-01 08:45:41] INFO     Searching for Yellowstone Lodging Availability: June, 2024
[2024-05-01 08:45:41] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:46] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/availability/hotels/yellowstonenationalparklodges?date=2024-06-01&limit=31&rate_code=INTERNET&nights=3 HTTP/1.1" 200 None
[2024-05-01 08:45:47] INFO             ⛺️      4 sites found.
[2024-05-01 08:45:47] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:48] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/availability/rooms/yellowstonenationalparklodges/YLYB:RV?date=2024-06-01&limit=31&nights=3 HTTP/1.1" 200 None
[2024-05-01 08:45:48] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:49] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/availability/rooms/yellowstonenationalparklodges/YLYF:RV?date=2024-06-01&limit=31&nights=3 HTTP/1.1" 200 None
[2024-05-01 08:45:49] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:50] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/availability/rooms/yellowstonenationalparklodges/YLYM:RV?date=2024-06-01&limit=31&nights=3 HTTP/1.1" 200 None
[2024-05-01 08:45:51] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:51] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/property/rooms/yellowstonenationalparklodges/YLYB:RV HTTP/1.1" 200 None
[2024-05-01 08:45:51] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:52] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/property/rooms/yellowstonenationalparklodges/YLYF:RV HTTP/1.1" 200 None
[2024-05-01 08:45:52] DEBUG    Starting new HTTPS connection (1): webapi.xanterra.net:443
[2024-05-01 08:45:53] DEBUG    https://webapi.xanterra.net:443 "GET /v1/api/property/rooms/yellowstonenationalparklodges/YLYM:RV HTTP/1.1" 200 None
[2024-05-01 08:45:53] INFO     ❌ ❌ ❌ ❌ 0 Reservable Campsites Matching Search Preferences
[2024-05-01 08:45:53] INFO     No Campsites were found, we'll continue checking````

@juftin
Copy link
Owner

juftin commented May 1, 2024

Looks like the API for Yellowstone had some kind of behavior change. Rather than returning {"availability": {}} when no availabilities are found it started returning {"availability": []}

I was only able to replicate this once, but I can see it in your debug logging:

│ /home/zach/.local/pipx/venvs/camply/lib/python3.10/site-packages/camply/providers/xanterra/yello │
│ wstone_lodging.py:417 in get_monthly_campsites                                                   │
│                                                                                                  │
│   414 │   │   availability_found = self._get_monthly_availability(                               │
│   415 │   │   │   month=search_date, nights=nights                                               │
│   416 │   │   )                                                                                  │
│ ❱ 417 │   │   availability = XantResortData(**availability_found)                                │
│   418 │   │   monthly_campsites = self._compile_campground_availabilities(                       │
│   419 │   │   │   availability=availability                                                      │
│   420 │   │   )                                                                                  │
│                                                                                                  │
│ ╭──────────────────── locals ────────────────────╮                                               │
│ │ availability_found = {'availability': []}      │                                               │
│ │              month = datetime.date(2024, 6, 1) │                                               │
│ │             nights = 3                         │                                               │
│ │                now = datetime.date(2024, 5, 1) │                                               │
│ │        search_date = datetime.date(2024, 6, 1) │                                               │
│ │               self = <Yellowstone>             │                                               │
│ ╰────────────────────────────────────────────────╯                                               │

#346 will resolve this

@juftin
Copy link
Owner

juftin commented May 1, 2024

The PR will auto-close this issue when it's merged momentarily and you can resolve this on your end by upgrading camply to the newest version. Please let me know if you encounter any other issues 🤝

juftin added a commit that referenced this issue May 1, 2024
@juftin juftin removed the triage This will looked at label May 1, 2024
github-actions bot added a commit that referenced this issue May 1, 2024
# [v0.32.6](v0.32.5...v0.32.6) (2024-05-01)

## 🐛 Bug Fixes
- [`f4d1b47`](f4d1b47)  yellowstone availability response empty (Issues: [`#344`](#344))

[skip ci]
@juftin
Copy link
Owner

juftin commented May 1, 2024

🎉 This issue has been resolved in version 0.32.6 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

@juftin juftin added the released label May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants