diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index d161d48..4984b79 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -24,6 +24,7 @@ name: tests env: APP_NAME: uw_gws + COVERAGE_PYTHON_VERSION: '3.10' on: push: @@ -37,22 +38,29 @@ on: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + + strategy: + matrix: + python-version: + - '3.8' + - '3.9' + - '3.10' steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - - name: Setup Python - uses: actions/setup-python@v2 + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: ${{ matrix.python-version }} - name: Install Dependencies run: | python -m pip install --upgrade pip pip install -e . - pip install commonconf nose2 coverage coveralls==2.2.0 + pip install commonconf nose2 coverage coveralls==3.3.1 - name: Run Python Linters uses: uw-it-aca/actions/python-linters@main @@ -62,9 +70,10 @@ jobs: - name: Run Tests run: | python -m compileall ${APP_NAME}/ - coverage run ${APP_NAME}/test.py -v + python -Wd -m coverage run ${APP_NAME}/test.py -v - name: Report Test Coverage + if: matrix.python-version == env.COVERAGE_PYTHON_VERSION env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash @@ -75,16 +84,16 @@ jobs: needs: test - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout Repo - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: - python-version: '3.x' + python-version: '3.10' - name: Publish to PyPi uses: uw-it-aca/actions/publish-pypi@main diff --git a/examples/get_groups.py b/examples/get_groups.py index 17c1707..d73f0aa 100644 --- a/examples/get_groups.py +++ b/examples/get_groups.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from commonconf.backends import use_configparser_backend diff --git a/examples/get_members.py b/examples/get_members.py index 5ddf66c..b1d0e3e 100644 --- a/examples/get_members.py +++ b/examples/get_members.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from commonconf.backends import use_configparser_backend diff --git a/examples/update_members.py b/examples/update_members.py index f7a976d..4aa2c5e 100644 --- a/examples/update_members.py +++ b/examples/update_members.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 from commonconf.backends import use_configparser_backend, use_django_backend diff --git a/setup.py b/setup.py index c26d2b0..9e02a47 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 import os @@ -21,11 +21,10 @@ name='UW-RestClients-GWS', version=VERSION, packages=['uw_gws'], - author="UW-IT AXDD", + author="UW-IT T&LS", author_email="aca-it@uw.edu", include_package_data=True, - install_requires=['UW-RestClients-Core', - 'pytz'], + install_requires=['UW-RestClients-Core'], license='Apache License, Version 2.0', description=('A library for connecting to the Groups Web Service at the ' 'University of Washington'), @@ -36,6 +35,5 @@ 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 3.8', ], ) diff --git a/uw_gws/__init__.py b/uw_gws/__init__.py index 6245672..3218d3c 100644 --- a/uw_gws/__init__.py +++ b/uw_gws/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 diff --git a/uw_gws/dao.py b/uw_gws/dao.py index 481a6e4..8e76362 100644 --- a/uw_gws/dao.py +++ b/uw_gws/dao.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 diff --git a/uw_gws/exceptions.py b/uw_gws/exceptions.py index 4555aff..8c89265 100644 --- a/uw_gws/exceptions.py +++ b/uw_gws/exceptions.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 diff --git a/uw_gws/models.py b/uw_gws/models.py index 197e066..991eda4 100644 --- a/uw_gws/models.py +++ b/uw_gws/models.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 diff --git a/uw_gws/test.py b/uw_gws/test.py index 5aae9f5..750a3c9 100644 --- a/uw_gws/test.py +++ b/uw_gws/test.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 diff --git a/uw_gws/tests/test_group.py b/uw_gws/tests/test_group.py index 00f62b2..70a1c14 100644 --- a/uw_gws/tests/test_group.py +++ b/uw_gws/tests/test_group.py @@ -1,9 +1,6 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0 - -from datetime import datetime -from pytz import timezone from unittest import TestCase from restclients_core.exceptions import DataFailureException from uw_gws import GWS @@ -12,7 +9,7 @@ GroupHistory) from uw_gws.utilities import fdao_gws_override from uw_gws.exceptions import InvalidGroupID -from restclients_core.exceptions import DataFailureException +from datetime import datetime, timedelta, timezone import mock @@ -27,13 +24,16 @@ def test_init(self): def test_request_headers(self): gws = GWS() - self.assertEquals(gws._headers(), {'Accept': 'application/json', - 'Connection': 'keep-alive'}) + + self.assertEqual(gws._headers(), + {'Accept': 'application/json', + 'Connection': 'keep-alive'}) gws = GWS(act_as='javerage') - self.assertEquals(gws._headers(), {'Accept': 'application/json', - 'Connection': 'keep-alive', - 'X-UW-Act-as': 'javerage'}) + self.assertEqual(gws._headers(), + {'Accept': 'application/json', + 'Connection': 'keep-alive', + 'X-UW-Act-as': 'javerage'}) def test_get_nonexistent_group(self): gws = GWS() @@ -48,27 +48,27 @@ def test_get_nonexistent_group(self): def test_get_group(self): gws = GWS() group = gws.get_group_by_id('u_acadev_tester') - self.assertEquals(group.name, "u_acadev_tester") - self.assertEquals(group.uwregid, "2a815628b04c4ada8fa490ea8f4364c8") - self.assertEquals(group.display_name, "Friends and Partners of ACA") - self.assertEquals( + self.assertEqual(group.name, "u_acadev_tester") + self.assertEqual(group.uwregid, "2a815628b04c4ada8fa490ea8f4364c8") + self.assertEqual(group.display_name, "Friends and Partners of ACA") + self.assertEqual( group.description, "Folks outside of uw-it that need access to ACA resources") - self.assertEquals(group.contact, "javerage") - self.assertEquals(group.authnfactor, 1) - self.assertEquals(group.classification, "u") - self.assertEquals(group.dependson, "") + self.assertEqual(group.contact, "javerage") + self.assertEqual(group.authnfactor, 1) + self.assertEqual(group.classification, "u") + self.assertEqual(group.dependson, "") def test_get_course_group(self): gws = GWS() group = gws.get_group_by_id("course_2012aut-train102a") - self.assertEquals(group.name, "course_2012aut-train102a") - self.assertEquals(group.curriculum_abbr, "train") - self.assertEquals(group.course_number, 102) - self.assertEquals(group.section_id, "a") - self.assertEquals(group.year, 2012) - self.assertEquals(group.quarter, "autumn") - self.assertEquals(len(group.instructors), 11) + self.assertEqual(group.name, "course_2012aut-train102a") + self.assertEqual(group.curriculum_abbr, "train") + self.assertEqual(group.course_number, 102) + self.assertEqual(group.section_id, "a") + self.assertEqual(group.year, 2012) + self.assertEqual(group.quarter, "autumn") + self.assertEqual(len(group.instructors), 11) self.assertIsNotNone(group.json_data()) def test_create_group(self): @@ -85,7 +85,7 @@ def test_create_group(self): self.assertTrue('classification' in json_data) self.assertTrue('name' in json_data['admins'][0]) group1 = gws._group_from_json(json_data) - self.assertEquals(group1.name, group.name) + self.assertEqual(group1.name, group.name) json_for_creat = group.json_data(is_put_req=True) self.assertFalse('regid' in json_for_creat) @@ -94,12 +94,12 @@ def test_create_group(self): self.assertFalse('lastMemberModified' in json_for_creat) self.assertFalse('contact' in json_for_creat) self.assertFalse('classification' in json_for_creat) - self.assertEquals(len(json_for_creat['admins']), 1) - self.assertEquals(len(json_for_creat['readers']), 1) - self.assertEquals(len(json_for_creat['optins']), 0) - self.assertEquals(len(json_for_creat['optouts']), 0) - self.assertEquals(len(json_for_creat['creators']), 0) - self.assertEquals(len(json_for_creat['updaters']), 0) + self.assertEqual(len(json_for_creat['admins']), 1) + self.assertEqual(len(json_for_creat['readers']), 1) + self.assertEqual(len(json_for_creat['optins']), 0) + self.assertEqual(len(json_for_creat['optouts']), 0) + self.assertEqual(len(json_for_creat['creators']), 0) + self.assertEqual(len(json_for_creat['updaters']), 0) self.assertRaises(DataFailureException, gws.create_group, group) @@ -134,35 +134,39 @@ def test_group_member(self): member1 = GroupMember(type="uwnetid", name="javerage", mtype="direct") - self.assertEquals(member1.is_uwnetid(), True) - self.assertEquals(member1.json_data(), - {"type": "uwnetid", - "mtype": "direct", - "source": None, - "id": "javerage"}) - self.assertEquals(member1.json_data(is_put_req=True), - {"type": "uwnetid", - "id": "javerage"}) + self.assertEqual(member1.is_uwnetid(), True) + + self.assertEqual( + member1.json_data(), + {"type": "uwnetid", + "mtype": "direct", + "source": None, + "id": "javerage"}) + self.assertEqual( + member1.json_data(is_put_req=True), + {"type": "uwnetid", + "id": "javerage"}) + member2 = GroupMember(type="uwnetid", name="javerage") - self.assertEquals(member2.type, "uwnetid") - self.assertEquals(member2.name, "javerage") - self.assertEquals(member2.mtype, GroupMember.DIRECT_MTYPE) - self.assertEquals(member1 == member2, True) + self.assertEqual(member2.type, "uwnetid") + self.assertEqual(member2.name, "javerage") + self.assertEqual(member2.mtype, GroupMember.DIRECT_MTYPE) + self.assertEqual(member1 == member2, True) member3 = GroupMember(type="eppn", name="javerage@washington.edu") - self.assertEquals(member3.is_uwnetid(), False) - self.assertEquals(member3.is_eppn(), True) - self.assertEquals(member1 == member3, False) + self.assertEqual(member3.is_uwnetid(), False) + self.assertEqual(member3.is_eppn(), True) + self.assertEqual(member1 == member3, False) member4 = GroupMember(type="group", name="u_acadev_unittest") - self.assertEquals(member4.is_uwnetid(), False) - self.assertEquals(member4.is_group(), True) - self.assertEquals(member1 == member4, False) + self.assertEqual(member4.is_uwnetid(), False) + self.assertEqual(member4.is_group(), True) + self.assertEqual(member1 == member4, False) def test_group_membership(self): gws = GWS() members = gws.get_members('u_acadev_unittest') - self.assertEquals(len(members), 2) + self.assertEqual(len(members), 2) self.assertIn(GroupMember(type="uwnetid", name="eight"), members) self.assertNotIn(GroupMember(type="eppn", name="j@washington.edu"), members) @@ -190,7 +194,7 @@ def test_update_members(self, mock_put): gws = GWS() members = gws.get_members('u_acadev_unittest') - self.assertEquals(len(members), 2) + self.assertEqual(len(members), 2) members.remove(GroupMember(type="uwnetid", name="eight")) @@ -223,13 +227,13 @@ def test_update_members_notfound(self): bad_members = gws.update_members("u_acadev_bad_members", members) - self.assertEquals(len(bad_members), 1) + self.assertEqual(len(bad_members), 1) def test_effective_group_membership(self): gws = GWS() members = gws.get_effective_members('u_acadev_unittest') - self.assertEquals(len(members), 3) + self.assertEqual(len(members), 3) has_seven = False has_javerage = False has_eight = False @@ -242,24 +246,24 @@ def test_effective_group_membership(self): elif member.name == "eight": has_eight = True - self.assertEquals(has_seven, True) - self.assertEquals(has_javerage, True) - self.assertEquals(has_eight, True) + self.assertEqual(has_seven, True) + self.assertEqual(has_javerage, True) + self.assertEqual(has_eight, True) count = gws.get_effective_member_count('u_acadev_unittest') - self.assertEquals(count, 3) + self.assertEqual(count, 3) def test_is_effective_member(self): gws = GWS() self.assertTrue( gws.is_effective_member('u_acadev_unittest', 'javerage')) - self.assertEquals( + self.assertEqual( gws.is_effective_member( 'u_acadev_unittest', 'javerage@washington.edu'), True) - self.assertEquals( + self.assertEqual( gws.is_effective_member('u_acadev_unittest', 'eight'), True) - self.assertEquals( + self.assertEqual( gws.is_effective_member('u_acadev_unittest', 'not_member'), False) def test_is_direct_member(self): @@ -274,16 +278,16 @@ def test_is_direct_member(self): def test_group_search(self): gws = GWS() groups = gws.search_groups(member="javerage") - self.assertEquals(len(groups), 15) + self.assertEqual(len(groups), 15) groups = gws.search_groups(member="JAVERAGE") - self.assertEquals(len(groups), 15) + self.assertEqual(len(groups), 15) groups = gws.search_groups(member="javerage", type="effective") - self.assertEquals(len(groups), 7) + self.assertEqual(len(groups), 7) groups = gws.search_groups(stem='cal_sea') - self.assertEquals(len(groups), 5) + self.assertEqual(len(groups), 5) self.assertEqual(groups[0].json_data(), {'displayName': 'cal_sea parent group', 'id': 'cal_sea', @@ -293,51 +297,51 @@ def test_group_search(self): def test_affiliates(self): group = GWS().get_group_by_id('u_acadev_unittest') - self.assertEquals(len(group.affiliates), 0) + self.assertEqual(len(group.affiliates), 0) group = GWS().get_group_by_id('u_acadev_tester') - self.assertEquals(len(group.affiliates), 1) + self.assertEqual(len(group.affiliates), 1) affiliate = group.affiliates[0] - self.assertEquals(affiliate.name, 'google') - self.assertEquals(affiliate.is_active(), True) - self.assertEquals(len(affiliate.senders), 0) + self.assertEqual(affiliate.name, 'google') + self.assertEqual(affiliate.is_active(), True) + self.assertEqual(len(affiliate.senders), 0) def test_group_roles(self): group = GWS().get_group_by_id('u_acadev_tester') self.assertIsNotNone(group.admins) - self.assertEquals(len(group.admins), 2) + self.assertEqual(len(group.admins), 2) self.assertIn( GroupEntity(name="u_javerage_admin", type=GroupEntity.GROUP_TYPE), group.admins) self.assertIsNotNone(group.updaters) - self.assertEquals(len(group.updaters), 1) + self.assertEqual(len(group.updaters), 1) self.assertIn( GroupEntity(name="u_javerage_update", type=GroupEntity.GROUP_TYPE), group.updaters) self.assertIsNotNone(group.readers) - self.assertEquals(len(group.readers), 1) + self.assertEqual(len(group.readers), 1) self.assertIn( GroupEntity(name="all", type=GroupEntity.SET_TYPE), group.readers) self.assertIsNotNone(group.creators) - self.assertEquals(len(group.creators), 1) + self.assertEqual(len(group.creators), 1) self.assertIn( GroupEntity(name="jcreator", type=GroupEntity.UWNETID_TYPE), group.creators) self.assertIsNotNone(group.optins) - self.assertEquals(len(group.optins), 1) + self.assertEqual(len(group.optins), 1) self.assertIn( GroupEntity(name="joptin", type=GroupEntity.UWNETID_TYPE), group.optins) self.assertIsNotNone(group.optouts) - self.assertEquals(len(group.optouts), 1) + self.assertEqual(len(group.optouts), 1) self.assertIn( GroupEntity(name="all", type=GroupEntity.SET_TYPE), group.optouts) @@ -367,7 +371,7 @@ def test_get_group_history(self): changes = GWS().get_group_history( 'u_acadev_tester', id='eight') self.assertEqual(len(changes), 1) - self.assertEquals( + self.assertEqual( changes[0].json_data(), {"description": "delete member: 'eight'", "activity": "membership", @@ -378,14 +382,14 @@ def test_get_group_history(self): "is_delete_member": True}) # get history of membership changes since a given timestamp - d = int(timezone("US/Pacific").localize( - datetime(2021, 7, 13, 15, 30, 00)).timestamp()) + ts = datetime(2021, 7, 13, 15, 30, 00, tzinfo=timezone( + timedelta(seconds=-7*60*60))).timestamp() changes = GWS().get_group_history( 'u_acadev_tester', activity='membership', - start=d) + start=int(ts)) self.assertEqual(len(changes), 2) - self.assertEquals( + self.assertEqual( changes[0].json_data(), {"description": "delete member: 'eight'", "activity": "membership", @@ -394,7 +398,7 @@ def test_get_group_history(self): "timestamp": 1626193233239, "is_add_member": False, "is_delete_member": True}) - self.assertEquals( + self.assertEqual( changes[1].json_data(), {"description": "add member: 'five'", "activity": "membership", diff --git a/uw_gws/utilities.py b/uw_gws/utilities.py index 15d2138..e4045a1 100644 --- a/uw_gws/utilities.py +++ b/uw_gws/utilities.py @@ -1,4 +1,4 @@ -# Copyright 2023 UW-IT, University of Washington +# Copyright 2024 UW-IT, University of Washington # SPDX-License-Identifier: Apache-2.0