coveralls: 
[![Coverage Status](https://coveralls.io/builds/31694688/badge)](https://coveralls.io/builds/31694688)

Coverage remained the same at 100.0% when pulling **1a991f2f13db4e887a647d789ef067f389ce17c9 on jessemcbride:issue/370-whitespaces-in-base-url** into **e85c5552b8bd611ab87fbf84ba9d752a86567be8 on ucfopen:develop**.

diff --git a/canvasapi/canvas.py b/canvasapi/canvas.py
index 13b7aad..3321e06 100644
--- a/canvasapi/canvas.py
+++ b/canvasapi/canvas.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
 import warnings
 
 from canvasapi.account import Account
+from canvasapi.comm_message import CommMessage
 from canvasapi.course import Course
 from canvasapi.course_epub_export import CourseEpubExport
 from canvasapi.current_user import CurrentUser
@@ -14,7 +15,6 @@ from canvasapi.paginated_list import PaginatedList
 from canvasapi.requester import Requester
 from canvasapi.section import Section
 from canvasapi.user import User
-from canvasapi.comm_message import CommMessage
 from canvasapi.util import combine_kwargs, get_institution_url, obj_or_id
 
 
@@ -59,10 +59,10 @@ class Canvas(object):
                 UserWarning,
             )
 
-        # Ensure that the user-supplied access token contains no leading or
-        # trailing spaces that may cause issues when communicating with
-        # the API.
+        # Ensure that the user-supplied access token and base_url contain no leading or
+        # trailing spaces that might cause issues when communicating with the API.
         access_token = access_token.strip()
+        base_url = base_url.strip()
 
         self.__requester = Requester(base_url, access_token)
 

try to loop through a PaginatedList of type Course but triggered AttributeError: 'NoneType' object has no attribute 'group'
# Describe the bug
It seems when I try to loop through the `PaginatedList of type Course` and print it out, a traceback error will show up. Like this, see below

Traceback (most recent call last):
  File"C:\Users\qchen\Documents\ITS\Canvas_script\lti_report\generate_term.py", line 51, in <module>
    for i in courses:
File"C:\Users\qchen\AppData\Local\Programs\Python\Python37-32\lib\site packages\canvasapi\paginated_list.py", line 49, in __iter__
    new_elements = self._grow()
File"C:\Users\qchen\AppData\Local\Programs\Python\Python37-32\lib\site-packages\canvasapi\paginated_list.py", line 93, in _grow            
new_elements = self._get_next_page()
File"C:\Users\qchen\AppData\Local\Programs\Python\Python37-32\lib\site-packages\canvasapi\paginated_list.py", line 67, in _get_next_page
re.search(regex,next_link["url"]).group(1) if next_link else None
AttributeError: 'NoneType' object has no attribute 'group'

# To Reproduce

Steps to reproduce the behavior:

1. Go to 'command line'
2. Click on 'run my python script'
my code is like this:
`canvas = Canvas(API_URL, API_KEY)
account=canvas.get_account(147)
courses=account.get_courses(include=['term'])
for i in courses: 
    print(i.term)`

3. See error

# Expected behavior
I want to loop through my list of course and get term information.

# Environment information

<!--(please complete the following information)-->

- Python version (`python --version`): Python 3.7.2
- CanvasAPI version (`pip show canvasapi`): Version: 0.15.0

# Additional context
I can print out the account list but it doesn't work for the course list. After I changed my file for api link nd token, it worked. Then I compare the api link with my previous one, I found there is an extra whitespace at the beginning of my api url. It seems that's the reason why my code doesn't work. 


diff --git a/tests/settings.py b/tests/settings.py
index f5dd44f..679cc11 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -6,6 +6,7 @@ BASE_URL_WITH_VERSION = "https://example.com/api/v1/"
 BASE_URL_AS_HTTP = "http://example.com"
 BASE_URL_AS_BLANK = ""
 BASE_URL_AS_INVALID = "example.com"
+BASE_URL_WITH_EXTRA_SPACES = " https://example.com "
 API_KEY = "123"
 
 INVALID_ID = 9001
diff --git a/tests/test_canvas.py b/tests/test_canvas.py
index 77e56be..4256dce 100644
--- a/tests/test_canvas.py
+++ b/tests/test_canvas.py
@@ -12,20 +12,19 @@ from canvasapi import Canvas
 from canvasapi.account import Account
 from canvasapi.appointment_group import AppointmentGroup
 from canvasapi.calendar_event import CalendarEvent
+from canvasapi.comm_message import CommMessage
 from canvasapi.conversation import Conversation
 from canvasapi.course import Course, CourseNickname
 from canvasapi.course_epub_export import CourseEpubExport
 from canvasapi.discussion_topic import DiscussionTopic
-from canvasapi.exceptions import RequiredFieldMissing
+from canvasapi.exceptions import RequiredFieldMissing, ResourceDoesNotExist
 from canvasapi.file import File
 from canvasapi.group import Group, GroupCategory
-from canvasapi.exceptions import ResourceDoesNotExist
 from canvasapi.outcome import Outcome, OutcomeGroup
 from canvasapi.paginated_list import PaginatedList
 from canvasapi.progress import Progress
 from canvasapi.section import Section
 from canvasapi.user import User
-from canvasapi.comm_message import CommMessage
 from tests import settings
 from tests.util import register_uris
 
@@ -75,6 +74,12 @@ class TestCanvas(unittest.TestCase):
         client = Canvas(settings.BASE_URL, " 12345 ")
         self.assertEqual(client._Canvas__requester.access_token, "12345")
 
+    def test_init_strips_extra_spaces_in_base_url(self, m):
+        client = Canvas(settings.BASE_URL_WITH_EXTRA_SPACES, "12345")
+        self.assertEqual(
+            client._Canvas__requester.base_url, settings.BASE_URL_WITH_VERSION
+        )
+
     # create_account()
     def test_create_account(self, m):
         register_uris({"account": ["create"]}, m)

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov requests_mock
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/ucfopen/canvasapi.git@e85c5552b8bd611ab87fbf84ba9d752a86567be8#egg=canvasapi
certifi==2025.1.31
charset-normalizer==3.4.1
coverage==7.8.0
exceptiongroup==1.2.2
idna==3.10
iniconfig==2.1.0
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
pytest-cov==6.0.0
pytz==2025.2
requests==2.32.3
requests-mock==1.12.1
six==1.17.0
tomli==2.2.1
urllib3==2.3.0

name: canvasapi
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - certifi==2025.1.31
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - idna==3.10
      - iniconfig==2.1.0
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pytz==2025.2
      - requests==2.32.3
      - requests-mock==1.12.1
      - six==1.17.0
      - tomli==2.2.1
      - urllib3==2.3.0
prefix: /opt/conda/envs/canvasapi

tests/test_canvas.py::TestCanvas::test_init_strips_extra_spaces_in_base_url
tests/test_canvas.py::TestCanvas::test_init_deprecate_url_contains_version tests/test_canvas.py::TestCanvas::test_list_appointment_groups tests/test_canvas.py::TestCanvas::test_list_calendar_events tests/test_canvas.py::TestCanvas::test_list_group_participants tests/test_canvas.py::TestCanvas::test_list_user_participants
tests/test_canvas.py::TestCanvas::test_clear_course_nicknames tests/test_canvas.py::TestCanvas::test_conversations_batch_update tests/test_canvas.py::TestCanvas::test_conversations_batch_updated_fail_on_event tests/test_canvas.py::TestCanvas::test_conversations_batch_updated_fail_on_ids tests/test_canvas.py::TestCanvas::test_conversations_get_running_batches tests/test_canvas.py::TestCanvas::test_conversations_mark_all_as_read tests/test_canvas.py::TestCanvas::test_conversations_unread_count tests/test_canvas.py::TestCanvas::test_create_account tests/test_canvas.py::TestCanvas::test_create_appointment_group tests/test_canvas.py::TestCanvas::test_create_appointment_group_fail_on_context_codes tests/test_canvas.py::TestCanvas::test_create_appointment_group_fail_on_title tests/test_canvas.py::TestCanvas::test_create_calendar_event tests/test_canvas.py::TestCanvas::test_create_calendar_event_fail tests/test_canvas.py::TestCanvas::test_create_conversation tests/test_canvas.py::TestCanvas::test_create_conversation_multiple_people tests/test_canvas.py::TestCanvas::test_create_group tests/test_canvas.py::TestCanvas::test_get_account tests/test_canvas.py::TestCanvas::test_get_account_fail tests/test_canvas.py::TestCanvas::test_get_account_sis_id tests/test_canvas.py::TestCanvas::test_get_accounts tests/test_canvas.py::TestCanvas::test_get_activity_stream_summary tests/test_canvas.py::TestCanvas::test_get_announcements tests/test_canvas.py::TestCanvas::test_get_appointment_group tests/test_canvas.py::TestCanvas::test_get_appointment_groups tests/test_canvas.py::TestCanvas::test_get_brand_variables tests/test_canvas.py::TestCanvas::test_get_calendar_event tests/test_canvas.py::TestCanvas::test_get_calendar_events tests/test_canvas.py::TestCanvas::test_get_comm_messages tests/test_canvas.py::TestCanvas::test_get_conversation tests/test_canvas.py::TestCanvas::test_get_conversations tests/test_canvas.py::TestCanvas::test_get_course tests/test_canvas.py::TestCanvas::test_get_course_accounts tests/test_canvas.py::TestCanvas::test_get_course_fail tests/test_canvas.py::TestCanvas::test_get_course_nickname tests/test_canvas.py::TestCanvas::test_get_course_nickname_fail tests/test_canvas.py::TestCanvas::test_get_course_nicknames tests/test_canvas.py::TestCanvas::test_get_course_non_unicode_char tests/test_canvas.py::TestCanvas::test_get_course_sis_id tests/test_canvas.py::TestCanvas::test_get_course_with_start_date tests/test_canvas.py::TestCanvas::test_get_courses tests/test_canvas.py::TestCanvas::test_get_epub_exports tests/test_canvas.py::TestCanvas::test_get_file tests/test_canvas.py::TestCanvas::test_get_group tests/test_canvas.py::TestCanvas::test_get_group_category tests/test_canvas.py::TestCanvas::test_get_group_participants tests/test_canvas.py::TestCanvas::test_get_group_sis_id tests/test_canvas.py::TestCanvas::test_get_outcome tests/test_canvas.py::TestCanvas::test_get_outcome_group tests/test_canvas.py::TestCanvas::test_get_progress tests/test_canvas.py::TestCanvas::test_get_root_outcome_group tests/test_canvas.py::TestCanvas::test_get_section tests/test_canvas.py::TestCanvas::test_get_section_sis_id tests/test_canvas.py::TestCanvas::test_get_todo_items tests/test_canvas.py::TestCanvas::test_get_upcoming_events tests/test_canvas.py::TestCanvas::test_get_user tests/test_canvas.py::TestCanvas::test_get_user_by_id_type tests/test_canvas.py::TestCanvas::test_get_user_fail tests/test_canvas.py::TestCanvas::test_get_user_participants tests/test_canvas.py::TestCanvas::test_get_user_self tests/test_canvas.py::TestCanvas::test_graphql tests/test_canvas.py::TestCanvas::test_init_strips_extra_spaces_in_api_key tests/test_canvas.py::TestCanvas::test_init_warns_when_url_is_blank tests/test_canvas.py::TestCanvas::test_init_warns_when_url_is_http tests/test_canvas.py::TestCanvas::test_init_warns_when_url_is_invalid tests/test_canvas.py::TestCanvas::test_reserve_time_slot tests/test_canvas.py::TestCanvas::test_reserve_time_slot_by_participant_id tests/test_canvas.py::TestCanvas::test_search_accounts tests/test_canvas.py::TestCanvas::test_search_all_courses tests/test_canvas.py::TestCanvas::test_search_recipients tests/test_canvas.py::TestCanvas::test_set_course_nickname
canvasapi/canvas.py
canvasapi/canvas.py