diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index ef5d65d..d1beb78 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -19,7 +19,7 @@ jobs: matrix: # Default builds are on Ubuntu os: [ubuntu-latest] - python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', 'pypy-3.10'] + python-version: ['3.11', '3.12', '3.13', '3.14', 'pypy-3.11'] include: # Also test on macOS and Windows using latest Python 3 - os: macos-latest @@ -27,11 +27,13 @@ jobs: - os: windows-latest python-version: 3.x steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 + # https://github.com/actions/checkout with: submodules: 'recursive' - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + # https://github.com/actions/setup-python + uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c44e13e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Changed + +- Temporarily skip SynBioHub unit tests to fix failing builds. + [449](https://github.com/SynBioDex/pySBOL2/issues/449), + [451](https://github.com/SynBioDex/pySBOL2/issues/451) +- Constrain `packaging` version to `<26.1` to keep using `NegativeInfinity`. + [449](https://github.com/SynBioDex/pySBOL2/issues/449), + [450](https://github.com/SynBioDex/pySBOL2/issues/450) + +## [1.4.1] - 2022-04-14 + +- Changes were not recorded. + +## [1.4.1] - 2022-02-04 + +- Changes were not recorded. diff --git a/setup.py b/setup.py index 4a9faa0..057b8dd 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup(name='sbol2', version='1.5', description='Pure Python implementation of SBOL 2 standard', - python_requires='>=3.7', + python_requires='>=3.11', url='https://github.com/SynBioDex/pySBOL2', author='Bryan Bartley', author_email='editors@sbolstandard.org', @@ -36,7 +36,9 @@ 'lxml', 'requests', 'urllib3', - 'packaging>=20.0' + # As of August 2026 the code is incompatible with packaging >= 26.1 + # https://github.com/SynBioDex/pySBOL2/issues/450 + 'packaging<26.1' ], package_data={'sbol2': ['libSBOLj.jar']}, tests_require=[ diff --git a/test/test_partshop.py b/test/test_partshop.py index f56e231..119f6a3 100644 --- a/test/test_partshop.py +++ b/test/test_partshop.py @@ -1,6 +1,7 @@ import os import unittest import json + import requests import sbol2 as sbol @@ -23,6 +24,9 @@ class TestPartShop(unittest.TestCase): + + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_pull_00(self): # Based on tutorial: https://pysbol2.readthedocs.io/en/latest/repositories.html doc = sbol.Document() @@ -33,6 +37,8 @@ def test_pull_00(self): # print(obj) self.assertEqual(3, len(doc)) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_pull_01(self): # Based on tutorial: https://pysbol2.readthedocs.io/en/latest/repositories.html doc = sbol.Document() @@ -45,6 +51,8 @@ def test_pull_01(self): # print(obj) self.assertEqual(7, len(doc)) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_pull_02(self): # I don't know what this adds over test_pull_01 # This is a replacement for a previous test whose part was no @@ -57,6 +65,8 @@ def test_pull_02(self): # print(obj) self.assertEqual(1, len(doc)) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skip("SynBioHub no longer allows this kind of anonymous access") def test_login(self): # NOTE: Add /login because login pages may be different # depending on what site you're accessing @@ -73,7 +83,7 @@ def test_login_bad(self): self.assertEqual(sbol_error.error_code(), sbol.SBOLErrorCode.SBOL_ERROR_BAD_HTTP_REQUEST) - @unittest.skipIf(password is None, "No password supplied") + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_submit_00(self): RESOURCE = 'https://synbiohub.utah.edu' doc = sbol.Document() @@ -86,6 +96,8 @@ def test_submit_00(self): response = ps.submit(doc, overwrite=1) self.assertEqual(response.status_code, 200) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skip("SynBioHub no longer allows this kind of anonymous access") def test_sparqlQuery_00(self): ps = sbol.PartShop(TEST_RESOURCE_MAIN) response = ps.login('johndoe', 'test') @@ -148,7 +160,7 @@ def test_spoof(self): part_shop.spoof(spoofed_url) self.assertEqual(part_shop.getSpoofedURL(), spoofed_url) - @unittest.skipIf(password is None, "No password supplied") + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_submit(self): # This test is derived from an etl-to-synbiohub_pipeline test # case that was failing. @@ -217,7 +229,7 @@ def test_uri2url_spoofed(self): else: self.fail('Expected SBOLError') - @unittest.skipIf(password is None, "No password supplied") + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_attach_file(self): sbol2.Config.setOption('sbol_typed_uris', False) doc = sbol2.Document() @@ -267,6 +279,8 @@ def test_attach_file(self): e = cm.exception self.assertEqual(e.error_code(), sbol2.SBOLErrorCode.SBOL_ERROR_NOT_FOUND) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_search_general(self): sbh = sbol2.PartShop(TEST_RESOURCE_MAIN) # sbh.login(username, password) @@ -277,6 +291,8 @@ def test_search_general(self): self.assertTrue(all([isinstance(x, sbol2.Identified) for x in results])) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_search_general_offset_limit(self): # Test a general search using offset and limit # This comes from a documentation example that was failing @@ -294,6 +310,8 @@ def test_search_general_offset_limit(self): self.assertTrue(all([isinstance(x, sbol2.Identified) for x in results])) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_search_exact(self): igem = sbol.PartShop(TEST_RESOURCE_MAIN) limit = 10 @@ -314,6 +332,8 @@ def test_search_exact(self): for cd in doc.componentDefinitions: self.assertIn(sbol2.SO_PROMOTER, cd.roles) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_pull_doc_version(self): # After a pull the document version was erroneously set to None (#281) doc = sbol.Document() @@ -325,6 +345,8 @@ def test_pull_doc_version(self): self.assertIsNotNone(doc.version) self.assertEqual(old_version, doc.version) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_search_count(self): part_shop = sbol2.PartShop('https://synbiohub.org/public/igem') # searchCount did not exist, see #322 diff --git a/test/test_searchquery.py b/test/test_searchquery.py index 61c09b5..77e1ef6 100644 --- a/test/test_searchquery.py +++ b/test/test_searchquery.py @@ -1,3 +1,4 @@ +import os import unittest import sbol2 @@ -5,6 +6,15 @@ GSOC_SBH_URL = 'https://synbiohub.org' +if 'SBH_USER' in os.environ: + username = os.environ['SBH_USER'] +else: + username = None +if 'SBH_PASSWORD' in os.environ: + password = os.environ['SBH_PASSWORD'] +else: + password = None + class TestSearchQuery(unittest.TestCase): @@ -14,6 +24,8 @@ def test_search_query1(self): self.assertIn(sbol2.SBOL_TYPES, query.properties) self.assertEqual(sbol2.BIOPAX_DNA, query[sbol2.SBOL_TYPES]) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_1_title(self): # See issue #240 collection = 'https://synbiohub.org/public/igem/igem_collection/1' @@ -34,6 +46,8 @@ def test_gsoc_example_1_title(self): names = [r.name == title for r in response] self.assertTrue(all(names)) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_1_display_id(self): # See issue #240 collection = 'https://synbiohub.org/public/igem/igem_collection/1' @@ -76,6 +90,8 @@ def do_gsoc_search(self, collection, term): results.extend(self.gsoc_search_display_id(part_shop, collection, term)) return results + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_2(self): # Looking for: https://synbiohub.org/public/igem/BBa_R0010/1 # and/or https://synbiohub.org/public/igem/BBa_C0012/1 @@ -93,6 +109,8 @@ def test_gsoc_example_2(self): self.assertNotIn('https://synbiohub.org/public/igem/BBa_S03334/1', identities) self.assertNotIn('https://synbiohub.org/public/igem/BBa_K1444015/1', identities) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_3(self): # Looking for: https://synbiohub.org/public/igem/BBa_R0010/1 # Collection: https://synbiohub.org/public/igem/igem_collection/1 @@ -107,6 +125,8 @@ def test_gsoc_example_3(self): self.assertNotIn('https://synbiohub.org/public/igem/BBa_S03334/1', identities) self.assertNotIn('https://synbiohub.org/public/igem/BBa_K1444015/1', identities) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_4(self): # Looking for: https://synbiohub.org/public/igem/BBa_B0034/1 # Collection: https://synbiohub.org/public/igem/igem_collection/1 @@ -119,6 +139,8 @@ def test_gsoc_example_4(self): self.assertIn('https://synbiohub.org/public/igem/BBa_B0034/1', identities) self.assertNotIn('https://synbiohub.org/public/igem/BBa_I13617/1', identities) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_example_5(self): # Looking for: https://synbiohub.org/public/bsu/BO_28874/1 # Collection: https://synbiohub.org/public/bsu/bsu_collection/1 @@ -132,6 +154,8 @@ def test_gsoc_example_5(self): self.assertIn('https://synbiohub.org/public/bsu/BO_28874/1', identities) self.assertNotIn('https://synbiohub.org/public/bsu/BO_26604/1', identities) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skipIf(password is None, "No SynBioHub password supplied") def test_gsoc_count_5(self): part_shop = sbol2.PartShop(GSOC_SBH_URL) query = sbol2.SearchQuery() diff --git a/test/test_tutorial.py b/test/test_tutorial.py index dae7f0b..20ca767 100644 --- a/test/test_tutorial.py +++ b/test/test_tutorial.py @@ -119,6 +119,8 @@ def create_new_device(self, doc: sbol2.Document): my_device.compile() self.assertEqual(expected_sequence, my_device.sequence.elements) + # https://github.com/SynBioDex/pySBOL2/issues/451 + @unittest.skip("SynBioHub no longer allows anonymous access") def test_tutorial(self): doc = self.init_tutorial() self.get_device_from_xml(doc)