Skip to content
Merged
8 changes: 5 additions & 3 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@ 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
python-version: 3.x
- 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
Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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=[
Expand Down
28 changes: 25 additions & 3 deletions test/test_partshop.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import unittest
import json

import requests

import sbol2 as sbol
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand All @@ -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')
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand All @@ -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
Expand Down
24 changes: 24 additions & 0 deletions test/test_searchquery.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import os
import unittest

import sbol2


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):

Expand All @@ -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'
Expand All @@ -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'
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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()
Expand Down
2 changes: 2 additions & 0 deletions test/test_tutorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down