Skip to content

Commit 8e70771

Browse files
authored
Merge pull request #107 from SynBioDex/develop
Prepare 1.0a15 release
2 parents 3315211 + fc393d0 commit 8e70771

9 files changed

Lines changed: 319 additions & 55 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Docstrings Coverage
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
schedule:
8+
- cron: '0 0 * * *' # every day at midnight
9+
10+
jobs:
11+
docstr_coverage:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v2
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v2
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
- name: Install Interrogate
21+
run: |
22+
python -m pip install --upgrade pip
23+
python -m pip install pytest
24+
pip install interrogate
25+
- name: Test docstr_coverage with interrogate
26+
run: |
27+
pytest test/test_docstr_coverage.py -s

.github/workflows/python-app.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ jobs:
4040
- name: Test with pytest
4141
run: |
4242
pip install .
43-
pytest -s
43+
pytest --ignore=test/test_docstr_coverage.py -s

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
# pycaches
55
test/__pycache__/
66
sbol_utilities/__pycache__/
7+
__pycache__/

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# SBOL-utilities
22
SBOL-utilities is a collection of scripts and functions for manipulating SBOL 3 data that can be run from the command line or as functions in Python.
33

4-
[![Documentation Status](https://readthedocs.org/projects/sbol-utilities/badge/?version=latest)](http://sbol-utilities.readthedocs.io/?badge=latest)
4+
[![Documentation Status](https://readthedocs.org/projects/sbol-utilities/badge/?version=latest)](http://sbol-utilities.readthedocs.io/)
5+
[![Docstrings Coverage](https://github.com/SynBioDex/SBOL-utilities/actions/workflows/docstr-coverage.yml/badge.svg)](https://github.com/SynBioDex/SBOL-utilities/actions/workflows/docstr-coverage.yml)
6+
[![PyPI version fury.io](https://badge.fury.io/py/sbol-utilities.svg)](https://pypi.python.org/pypi/sbol-utilities/)
7+
[![PyPI license](https://img.shields.io/pypi/l/sbol-utilities.svg)](https://pypi.python.org/pypi/sbol-utilities/)
8+
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/sbol-utilities.svg)](https://pypi.python.org/pypi/sbol-utilities/)
9+
[![gh-action badge](https://github.com/SynBioDex/tyto/workflows/CI/badge.svg)](https://github.com/SynBioDex/SBOL-utilities/actions)
10+
511

612
## Installation
713

sbol_utilities/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
# No shared content for package: import sub packages
2+
3+
# TODO: consider what, if anything, should go into the shared content

sbol_utilities/conversion.py

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,12 @@ def convert2to3(sbol2_doc: Union[str, sbol2.Document], namespaces=None) -> sbol3
7979
namespaces = []
8080
if isinstance(sbol2_doc, sbol2.Document):
8181
sbol2_path = tempfile.mkstemp(suffix='.xml')[1]
82-
# Turn off automatic validation on write to avoid requiring transmitting data to the validator webservice
83-
# If you want validation, you should validate the document explicitly beforehand
84-
was_using_validator = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE)
82+
validate_online = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE_ONLINE)
8583
try:
86-
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, False)
84+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, False)
8785
sbol2_doc.write(sbol2_path)
8886
finally:
89-
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE, was_using_validator)
87+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, validate_online)
9088
else:
9189
sbol2_path = sbol2_doc
9290

@@ -159,6 +157,11 @@ def change_orientation(o):
159157
o.orientation = orientation_remapping[o.orientation]
160158
doc.traverse(change_orientation)
161159

160+
report = doc.validate()
161+
if len(report):
162+
report_string = "\n".join(str(e) for e in doc.validate())
163+
raise ValueError(f'Conversion from SBOL2 to SBOL3 produced an invalid document: {report_string}')
164+
162165
return doc
163166

164167

@@ -196,8 +199,8 @@ def convert3to2(doc3: sbol3.Document) -> sbol2.Document:
196199
}
197200

198201
def change_orientation(o):
199-
if isinstance(o, sbol3.Location):
200-
if hasattr(o, 'orientation') and o.orientation in orientation_remapping:
202+
if isinstance(o, sbol3.Location) or isinstance(o, sbol3.Feature):
203+
if o.orientation in orientation_remapping:
201204
o.orientation = orientation_remapping[o.orientation]
202205
doc3.traverse(change_orientation)
203206

@@ -215,7 +218,7 @@ def change_orientation(o):
215218
# Extract the rdf_xml output from the sbol converter
216219
rdf_xml = proc.stdout.decode('utf-8')
217220
except subprocess.CalledProcessError:
218-
raise ValueError('Embedded SBOL 3-to-2 converter failed opaquely, indicating a likely invalid SBOL file.')
221+
raise ValueError('Embedded SBOL 3-to-2 converter failed opaquely, possibly indicating an invalid SBOL file.')
219222

220223
doc2 = sbol2.Document()
221224
doc2.readString(rdf_xml)
@@ -224,8 +227,17 @@ def change_orientation(o):
224227
for sa in c.sequenceAnnotations:
225228
for loc in sa.locations:
226229
loc.sequence = None # remove optional sequences, per https://github.com/SynBioDex/libSBOLj/issues/621
227-
# We explicitly do NOT validate here in order to avoid requiring transmitting data to the validator webservice
228-
# If you want validation, you should run it on the document that is returned
230+
231+
# Validate document offline
232+
validate_online = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE_ONLINE)
233+
try:
234+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, False)
235+
result = doc2.validate()
236+
if not result == "Valid.":
237+
raise ValueError(f'Conversion from SBOL3 to SBOL2 produced an invalid document: {result}')
238+
finally:
239+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, validate_online)
240+
229241
return doc2
230242

231243

@@ -285,15 +297,19 @@ def convert_from_genbank(path: str, namespace: str, allow_genbank_online: bool =
285297
286298
:param path: path to read GenBank file from
287299
:param namespace: URIs of Components will be set to {namespace}/{genbank_id}
288-
:param allow_genbank_online: Allow use of the online converter (currently required)
300+
:param allow_genbank_online: Use the online converter, rather than the local converter
289301
:return: SBOL3 document containing converted materials
290302
"""
291-
if not allow_genbank_online:
292-
raise NotImplementedError('GenBank conversion currently requires use of the online SBOL validator/converter')
293-
294303
doc2 = sbol2.Document()
295304
sbol2.setHomespace(namespace)
296-
doc2.importFromFormat(path)
305+
# Convert document offline
306+
validate_online = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE_ONLINE)
307+
try:
308+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, allow_genbank_online)
309+
doc2.importFromFormat(path)
310+
finally:
311+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, validate_online)
312+
297313
doc = convert2to3(doc2, [namespace])
298314
return doc
299315

@@ -305,13 +321,10 @@ def convert_to_genbank(doc3: sbol3.Document, path: str, allow_genbank_online: bo
305321
then a fixed bogus datestamp of January 1, 2000 is given
306322
307323
:param doc3: SBOL3 document to convert
308-
:param path: path to write FASTA file to
309-
:param allow_genbank_online: Allow use of the online converter (currently required)
324+
:param path: path to write GenBank file to
325+
:param allow_genbank_online: use the online converter rather than the local converter
310326
:return: BioPython SeqRecord of the GenBank that was written
311327
"""
312-
if not allow_genbank_online:
313-
raise NotImplementedError('GenBank conversion currently requires use of the online SBOL validator/converter')
314-
315328
# first convert to SBOL2, then export to a temp GenBank file
316329
doc2 = convert3to2(doc3)
317330

@@ -322,7 +335,13 @@ def convert_to_genbank(doc3: sbol3.Document, path: str, allow_genbank_online: bo
322335
c.properties = {p: v for p, v in c.properties.items() if any(k for k in keepers if p.startswith(k))}
323336

324337
gb_tmp = tempfile.mkstemp(suffix='.gb')[1]
325-
doc2.exportToFormat('GenBank', gb_tmp)
338+
# Convert document offline
339+
validate_online = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE_ONLINE)
340+
try:
341+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, allow_genbank_online)
342+
doc2.exportToFormat('GenBank', gb_tmp)
343+
finally:
344+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, validate_online)
326345

327346
# Read and re-write in order to sort and to purge invalid date information and standardize GenBank formatting
328347
with open(gb_tmp, 'r') as tmp:
@@ -393,7 +412,12 @@ def command_line_converter(args_dict: Dict[str, Any]):
393412
convert_to_genbank(doc3, output_file, args_dict['allow_genbank_online'])
394413
elif output_file_type == 'SBOL2':
395414
doc2 = convert3to2(doc3)
396-
doc2.write(output_file)
415+
validate_online = sbol2.Config.getOption(sbol2.ConfigOptions.VALIDATE_ONLINE)
416+
try:
417+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, False)
418+
doc2.write(output_file)
419+
finally:
420+
sbol2.Config.setOption(sbol2.ConfigOptions.VALIDATE_ONLINE, validate_online)
397421
elif output_file_type == 'SBOL3':
398422
doc3.write(output_file, sbol3.SORTED_NTRIPLES)
399423
else:
@@ -413,8 +437,7 @@ def main():
413437
parser.add_argument('--verbose', '-v', dest='verbose', action='count', default=0,
414438
help="Print running explanation of conversion process")
415439
parser.add_argument('--allow-genbank-online', dest='allow_genbank_online', action='store_true', default=False,
416-
help='Allow GenBank conversion to send material to online converter; '
417-
'currently required to be True')
440+
help='Perform GenBank conversion using online converter')
418441
args_dict = vars(parser.parse_args())
419442
# Call the shared command-line conversion routine
420443
command_line_converter(args_dict)
@@ -448,8 +471,7 @@ def genbank2sbol():
448471
parser.add_argument('--verbose', '-v', dest='verbose', action='count', default=0,
449472
help='Print running explanation of conversion process')
450473
parser.add_argument('--allow-genbank-online', dest='allow_genbank_online', action='store_true', default=False,
451-
help='Allow GenBank conversion to send material to online converter; '
452-
'currently required to be True')
474+
help='Perform GenBank conversion using online converter')
453475
args_dict = vars(parser.parse_args())
454476
args_dict['input_file_type'] = 'GenBank'
455477
args_dict['output_file_type'] = 'SBOL3'
@@ -499,8 +521,7 @@ def sbol2genbank():
499521
parser.add_argument('--verbose', '-v', dest='verbose', action='count', default=0,
500522
help="Print running explanation of conversion process")
501523
parser.add_argument('--allow-genbank-online', dest='allow_genbank_online', action='store_true', default=False,
502-
help='Allow GenBank conversion to send material to online converter; '
503-
'currently required to be True')
524+
help='Perform GenBank conversion using online converter')
504525
args_dict = vars(parser.parse_args())
505526
args_dict['input_file_type'] = 'SBOL3'
506527
args_dict['output_file_type'] = 'GenBank'

setup.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
long_description_content_type='text/markdown',
88
url='https://github.com/SynBioDex/SBOL-utilities',
99
license='MIT License',
10-
version='1.0a14',
10+
version='1.0a15',
1111
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
1212
classifiers=[
1313
# How mature is this project? Common values are
@@ -27,18 +27,20 @@
2727
'Programming Language :: Python :: 3 :: Only',
2828
'Programming Language :: Python :: 3.7',
2929
'Programming Language :: Python :: 3.8',
30-
'Programming Language :: Python :: 3.9'
30+
'Programming Language :: Python :: 3.9',
31+
'Programming Language :: Python :: 3.10'
3132
],
3233
# What does your project relate to?
3334
keywords='synthetic biology',
3435
install_requires=[
35-
'sbol3>=1.0b8,!=1.0b9',
36-
'sbol2>=1.3',
36+
'sbol3>=1.0b11',
37+
'sbol2>=1.4',
3738
'rdflib',
3839
'biopython',
3940
'graphviz',
40-
'tyto>=1.0-beta',
41-
'openpyxl'
41+
'tyto>=1.0',
42+
'openpyxl',
43+
'sbol_factory>=1.0a11'
4244
],
4345
extras_require={ # requirements for development
4446
'dev': ['pytest', 'interrogate']

0 commit comments

Comments
 (0)