Skip to content

Commit a69e691

Browse files
committed
- Convert python2 code to python3 with 2to3
- remove all reference to python2
1 parent 476169c commit a69e691

File tree

9 files changed

+58
-62
lines changed

9 files changed

+58
-62
lines changed

setup.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
extras['ext_modules'] = [Extension("vcf.cparse", ["vcf/cparse.pyx"])]
3030

3131
setup(
32-
name='PyVCF',
32+
name='PyVCF3',
3333
packages=['vcf', 'vcf.test'],
3434
scripts=['scripts/vcf_melt', 'scripts/vcf_filter.py',
3535
'scripts/vcf_sample_filter.py'],
@@ -49,7 +49,7 @@
4949
'snp-only = vcf.filters:SnpOnly',
5050
]
5151
},
52-
url='https://github.com/jamescasbon/PyVCF',
52+
url='https://github.com/dridk/PyVCF3',
5353
version=VERSION,
5454
classifiers = [
5555
'Development Status :: 4 - Beta',
@@ -60,8 +60,6 @@
6060
'Operating System :: OS Independent',
6161
'Programming Language :: Cython',
6262
'Programming Language :: Python',
63-
'Programming Language :: Python :: 2',
64-
'Programming Language :: Python :: 2.7',
6563
'Programming Language :: Python :: 3',
6664
'Programming Language :: Python :: 3.4',
6765
'Programming Language :: Python :: 3.5',
@@ -71,7 +69,6 @@
7169
'Topic :: Scientific/Engineering :: Bio-Informatics',
7270
],
7371
keywords='bioinformatics',
74-
use_2to3=True,
7572
include_package_data=True,
7673
package_data = {
7774
'': ['*.vcf', '*.gz', '*.tbi'],

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# and then run "tox" from this directory.
55

66
[tox]
7-
envlist = py27, py34, py35, py36, pypy, pypy3
7+
envlist = py34, py35, py36, pypy, pypy3
88

99
[testenv]
1010
deps =

vcf/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
from vcf.parser import RESERVED_INFO, RESERVED_FORMAT
1313
from vcf.sample_filter import SampleFilter
1414

15-
VERSION = '0.6.8'
15+
VERSION = '1.0.0'

vcf/model.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def heterozygosity(self):
362362
If there are i alleles with frequency p_i, H=1-sum_i(p_i^2)
363363
"""
364364
allele_freqs = [1-sum(self.aaf)] + self.aaf
365-
return 1 - sum(map(lambda x: x**2, allele_freqs))
365+
return 1 - sum([x**2 for x in allele_freqs])
366366

367367
def get_hom_refs(self):
368368
""" The list of hom ref genotypes"""
@@ -558,9 +558,8 @@ def is_filtered(self):
558558
return True
559559

560560

561-
class _AltRecord(object):
561+
class _AltRecord(object, metaclass=ABCMeta):
562562
'''An alternative allele record: either replacement string, SV placeholder, or breakend'''
563-
__metaclass__ = ABCMeta
564563

565564
def __init__(self, type, **kwargs):
566565
super(_AltRecord, self).__init__(**kwargs)
@@ -596,7 +595,7 @@ def __len__(self):
596595
return len(self.sequence)
597596

598597
def __eq__(self, other):
599-
if isinstance(other, basestring):
598+
if isinstance(other, str):
600599
return self.sequence == other
601600
elif not isinstance(other, self.__class__):
602601
return False

vcf/parser.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
except ImportError:
2323
cparse = None
2424

25-
from model import _Call, _Record, make_calldata_tuple
26-
from model import _Substitution, _Breakend, _SingleBreakend, _SV
25+
from .model import _Call, _Record, make_calldata_tuple
26+
from .model import _Substitution, _Breakend, _SingleBreakend, _SV
2727

2828

2929
# Metadata parsers/constants
@@ -468,7 +468,7 @@ def _parse_samples(self, samples, samp_fmt, site):
468468

469469
nfields = len(samp_fmt._fields)
470470

471-
for name, sample in itertools.izip(self.samples, samples):
471+
for name, sample in zip(self.samples, samples):
472472

473473
# parse the data for this sample
474474
sampdat = [None] * nfields
@@ -548,7 +548,7 @@ def _parse_alt(self, str):
548548
else:
549549
return _Substitution(str)
550550

551-
def next(self):
551+
def __next__(self):
552552
'''Return the next record in the file.'''
553553
line = next(self.reader)
554554
row = self._row_pattern.split(line.rstrip())
@@ -641,7 +641,7 @@ class Writer(object):
641641
"""VCF Writer. On Windows Python 2, open stream with 'wb'."""
642642

643643
# Reverse keys and values in header field count dictionary
644-
counts = dict((v,k) for k,v in field_counts.iteritems())
644+
counts = dict((v,k) for k,v in field_counts.items())
645645

646646
def __init__(self, stream, template, lineterminator="\n"):
647647
self.writer = csv.writer(stream, delimiter="\t",
@@ -654,30 +654,30 @@ def __init__(self, stream, template, lineterminator="\n"):
654654
# get a maximum key).
655655
self.info_order = collections.defaultdict(
656656
lambda: len(template.infos),
657-
dict(zip(template.infos.iterkeys(), itertools.count())))
657+
dict(list(zip(iter(template.infos.keys()), itertools.count()))))
658658

659659
two = '##{key}=<ID={0},Description="{1}">\n'
660660
four = '##{key}=<ID={0},Number={num},Type={2},Description="{3}">\n'
661661
_num = self._fix_field_count
662-
for (key, vals) in template.metadata.iteritems():
662+
for (key, vals) in template.metadata.items():
663663
if key in SINGULAR_METADATA:
664664
vals = [vals]
665665
for val in vals:
666666
if isinstance(val, dict):
667667
values = ','.join('{0}={1}'.format(key, value)
668-
for key, value in val.items())
668+
for key, value in list(val.items()))
669669
stream.write('##{0}=<{1}>\n'.format(key, values))
670670
else:
671671
stream.write('##{0}={1}\n'.format(key, val))
672-
for line in template.infos.itervalues():
672+
for line in template.infos.values():
673673
stream.write(four.format(key="INFO", *line, num=_num(line.num)))
674-
for line in template.formats.itervalues():
674+
for line in template.formats.values():
675675
stream.write(four.format(key="FORMAT", *line, num=_num(line.num)))
676-
for line in template.filters.itervalues():
676+
for line in template.filters.values():
677677
stream.write(two.format(key="FILTER", *line))
678-
for line in template.alts.itervalues():
678+
for line in template.alts.values():
679679
stream.write(two.format(key="ALT", *line))
680-
for line in template.contigs.itervalues():
680+
for line in template.contigs.values():
681681
if line.length:
682682
stream.write('##contig=<ID={0},length={1}>\n'.format(*line))
683683
else:

vcf/sample_filter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import warnings
88

99

10-
from parser import Reader, Writer
10+
from .parser import Reader, Writer
1111

1212

1313
class SampleFilter(object):
@@ -81,13 +81,13 @@ def filt2idx(item):
8181
# is int, check if it's an idx
8282
if item < len(self.samples):
8383
return item
84-
filters = set(filter(lambda x: x is not None, map(filt2idx, filt_s)))
84+
filters = set([x for x in map(filt2idx, filt_s) if x is not None])
8585
if len(filters) < len(filt_s):
8686
# TODO print the filters that were ignored
8787
warnings.warn("Invalid filters, ignoring", RuntimeWarning)
8888

8989
if self.invert:
90-
filters = set(xrange(len(self.samples))).difference(filters)
90+
filters = set(range(len(self.samples))).difference(filters)
9191

9292
# `sample_filter` setter updates `samples`
9393
self.parser.sample_filter = filters

vcf/test/prof.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def parse_1kg():
1919
elif sys.argv[1] == 'time':
2020
n = 1
2121
t = timeit.timeit('parse_1kg()', "from __main__ import parse_1kg", number=n)
22-
print t/n
22+
print(t/n)
2323

2424
elif sys.argv[1] == 'stat':
2525
import statprof
@@ -30,4 +30,4 @@ def parse_1kg():
3030
statprof.stop()
3131
statprof.display()
3232
else:
33-
print 'prof.py profile/time'
33+
print('prof.py profile/time')

vcf/test/test_vcf.py

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
from __future__ import print_function
1+
22
import unittest
33
try:
44
unittest.skip
55
except AttributeError:
66
import unittest2 as unittest
77
import doctest
88
import os
9-
import commands
10-
import cPickle
11-
from StringIO import StringIO
9+
import subprocess
10+
import pickle
11+
from io import StringIO
1212
import subprocess
1313
import sys
1414

@@ -137,7 +137,7 @@ def test_contig_idonly(self):
137137
"""Test VCF inputs with ##contig inputs containing only IDs. produced by bcftools 1.2+
138138
"""
139139
reader = vcf.Reader(fh("contig_idonly.vcf"))
140-
for cid, contig in reader.contigs.items():
140+
for cid, contig in list(reader.contigs.items()):
141141
if cid == "1":
142142
assert contig.length is None
143143
elif cid == "2":
@@ -390,24 +390,24 @@ def test_write(self):
390390
reader2 = vcf.Reader(out)
391391

392392
for l, r in zip(records, reader2):
393-
self.assertEquals(l.INFO, r.INFO)
393+
self.assertEqual(l.INFO, r.INFO)
394394

395395

396396
class TestBadInfoFields(unittest.TestCase):
397397
def test_parse(self):
398398
reader = vcf.Reader(fh('bad-info-character.vcf'))
399399
record = next(reader)
400-
self.assertEquals(record.INFO['DOT_1'], None)
401-
self.assertEquals(record.INFO['DOT_3'], [None, None, None])
402-
self.assertEquals(record.INFO['DOT_N'], [None])
403-
self.assertEquals(record.INFO['EMPTY_1'], None)
400+
self.assertEqual(record.INFO['DOT_1'], None)
401+
self.assertEqual(record.INFO['DOT_3'], [None, None, None])
402+
self.assertEqual(record.INFO['DOT_N'], [None])
403+
self.assertEqual(record.INFO['EMPTY_1'], None)
404404
# Perhaps EMPTY_3 should yield [None, None, None] but this is really a
405405
# cornercase of unspecified behaviour.
406-
self.assertEquals(record.INFO['EMPTY_3'], [None])
407-
self.assertEquals(record.INFO['EMPTY_N'], [None])
408-
self.assertEquals(record.INFO['NOTEMPTY_1'], 1)
409-
self.assertEquals(record.INFO['NOTEMPTY_3'], [1, 2, 3])
410-
self.assertEquals(record.INFO['NOTEMPTY_N'], [1])
406+
self.assertEqual(record.INFO['EMPTY_3'], [None])
407+
self.assertEqual(record.INFO['EMPTY_N'], [None])
408+
self.assertEqual(record.INFO['NOTEMPTY_1'], 1)
409+
self.assertEqual(record.INFO['NOTEMPTY_3'], [1, 2, 3])
410+
self.assertEqual(record.INFO['NOTEMPTY_N'], [1])
411411
pass
412412

413413

@@ -440,7 +440,7 @@ def test_write(self):
440440
self.assertEqual(f['Options'], '"< 4 and > 3"')
441441

442442
for l, r in zip(records, reader2):
443-
self.assertEquals(l.INFO, r.INFO)
443+
self.assertEqual(l.INFO, r.INFO)
444444

445445

446446
class TestGatkOutputWriter(unittest.TestCase):
@@ -463,13 +463,13 @@ def testWrite(self):
463463
print (out_str)
464464
reader2 = vcf.Reader(out)
465465

466-
self.assertEquals(reader.samples, reader2.samples)
467-
self.assertEquals(reader.formats, reader2.formats)
468-
self.assertEquals(reader.infos, reader2.infos)
469-
self.assertEquals(reader.contigs, reader2.contigs)
466+
self.assertEqual(reader.samples, reader2.samples)
467+
self.assertEqual(reader.formats, reader2.formats)
468+
self.assertEqual(reader.infos, reader2.infos)
469+
self.assertEqual(reader.contigs, reader2.contigs)
470470

471471
for l, r in zip(records, reader2):
472-
self.assertEquals(l.samples, r.samples)
472+
self.assertEqual(l.samples, r.samples)
473473

474474
# test for call data equality, since equality on the sample calls
475475
# may not always mean their data are all equal
@@ -493,12 +493,12 @@ def testWrite(self):
493493
print (out.getvalue())
494494
reader2 = vcf.Reader(out)
495495

496-
self.assertEquals(reader.samples, reader2.samples)
497-
self.assertEquals(reader.formats, reader2.formats)
498-
self.assertEquals(reader.infos, reader2.infos)
496+
self.assertEqual(reader.samples, reader2.samples)
497+
self.assertEqual(reader.formats, reader2.formats)
498+
self.assertEqual(reader.infos, reader2.infos)
499499

500500
for l, r in zip(records, reader2):
501-
self.assertEquals(l.samples, r.samples)
501+
self.assertEqual(l.samples, r.samples)
502502

503503
# test for call data equality, since equality on the sample calls
504504
# may not always mean their data are all equal
@@ -522,7 +522,7 @@ def testWrite(self):
522522
out_str = out.getvalue()
523523
for line in out_str.split("\n"):
524524
if line.startswith("##PEDIGREE"):
525-
self.assertEquals(line, '##PEDIGREE=<Derived="Tumor",Original="Germline">')
525+
self.assertEqual(line, '##PEDIGREE=<Derived="Tumor",Original="Germline">')
526526
if line.startswith("##SAMPLE"):
527527
assert line.startswith('##SAMPLE=<'), "Found dictionary in meta line: {0}".format(line)
528528

@@ -955,7 +955,7 @@ def test_info_multiple_values(self):
955955
def test_pickle(self):
956956
reader = vcf.Reader(fh('example-4.0.vcf'))
957957
for var in reader:
958-
self.assertEqual(cPickle.loads(cPickle.dumps(var)), var)
958+
self.assertEqual(pickle.loads(pickle.dumps(var)), var)
959959

960960

961961
def assert_has_expected_coordinates(
@@ -1498,7 +1498,7 @@ class TestFilter(unittest.TestCase):
14981498
@unittest.skip("test currently broken")
14991499
def testApplyFilter(self):
15001500
# FIXME: broken with distribute
1501-
s, out = commands.getstatusoutput('python scripts/vcf_filter.py --site-quality 30 test/example-4.0.vcf sq')
1501+
s, out = subprocess.getstatusoutput('python scripts/vcf_filter.py --site-quality 30 test/example-4.0.vcf sq')
15021502
#print(out)
15031503
self.assertEqual(s, 0)
15041504
buf = StringIO()
@@ -1528,7 +1528,7 @@ def testApplyFilter(self):
15281528
@unittest.skip("test currently broken")
15291529
def testApplyMultipleFilters(self):
15301530
# FIXME: broken with distribute
1531-
s, out = commands.getstatusoutput('python scripts/vcf_filter.py --site-quality 30 '
1531+
s, out = subprocess.getstatusoutput('python scripts/vcf_filter.py --site-quality 30 '
15321532
'--genotype-quality 50 test/example-4.0.vcf sq mgq')
15331533
self.assertEqual(s, 0)
15341534
#print(out)
@@ -1599,7 +1599,7 @@ def test_walk(self):
15991599
assert recs[1] is not None
16001600

16011601
# test files with many chromosomes, set 'vcf_record_sort_key' to define chromosome order
1602-
chr_order = map(str, range(1, 30)) + ['X', 'Y', 'M']
1602+
chr_order = list(map(str, list(range(1, 30)))) + ['X', 'Y', 'M']
16031603
get_key = lambda r: (chr_order.index(r.CHROM.replace('chr','')), r.POS)
16041604
reader1 = vcf.Reader(fh('issue-140-file1.vcf'))
16051605
reader2 = vcf.Reader(fh('issue-140-file2.vcf'))

vcf/utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ def walk_together(*readers, **kwargs):
3737
next_idx_to_k = dict(
3838
(i, get_key(r)) for i, r in enumerate(nexts) if r is not None)
3939
keys_with_prev_contig = [
40-
k for k in next_idx_to_k.values() if k[0] == min_k[0]]
40+
k for k in list(next_idx_to_k.values()) if k[0] == min_k[0]]
4141

4242
if any(keys_with_prev_contig):
4343
min_k = min(keys_with_prev_contig) # finish previous contig
4444
else:
4545
min_k = min(next_idx_to_k.values()) # move on to next contig
4646

47-
min_k_idxs = set([i for i, k in next_idx_to_k.items() if k == min_k])
47+
min_k_idxs = set([i for i, k in list(next_idx_to_k.items()) if k == min_k])
4848
yield [nexts[i] if i in min_k_idxs else None for i in range(len(nexts))]
4949

5050
for i in min_k_idxs:
5151
try:
52-
nexts[i] = readers[i].next()
52+
nexts[i] = next(readers[i])
5353
except StopIteration:
5454
nexts[i] = None
5555

0 commit comments

Comments
 (0)