Commit 739f7379 authored by Steffen Möller's avatar Steffen Möller
Browse files

New upstream version 0.5.7

parent 064d13a0
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -7,9 +7,7 @@ python:
    - '3.6'
    - '3.5'
    - '3.4'
    - '3.3'
    - '2.7'
    - '2.6'
    - 'pypy'
    - 'pypy3'
install:
+4 −3
Original line number Diff line number Diff line
|Travis| |PyPI| |Landscape| |Coverage| |Depsy| |Appveyor|
|Travis| |PyPI| |Coverage| |Depsy|

Description
-----------
@@ -54,7 +54,8 @@ Acts like a dictionary.

.. code:: python

    >>> genes.keys() ('AB821309.1', 'KF435150.1', 'KF435149.1', 'NR_104216.1', 'NR_104215.1', 'NR_104212.1', 'NM_001282545.1', 'NM_001282543.1', 'NM_000465.3', 'NM_001282549.1', 'NM_001282548.1', 'XM_005249645.1', 'XM_005249644.1', 'XM_005249643.1', 'XM_005249642.1', 'XM_005265508.1', 'XM_005265507.1', 'XR_241081.1', 'XR_241080.1', 'XR_241079.1')
    >>> genes.keys()
    ('AB821309.1', 'KF435150.1', 'KF435149.1', 'NR_104216.1', 'NR_104215.1', 'NR_104212.1', 'NM_001282545.1', 'NM_001282543.1', 'NM_000465.3', 'NM_001282549.1', 'NM_001282548.1', 'XM_005249645.1', 'XM_005249644.1', 'XM_005249643.1', 'XM_005249642.1', 'XM_005265508.1', 'XM_005265507.1', 'XR_241081.1', 'XR_241080.1', 'XR_241079.1')

    >>> genes['NM_001282543.1'][200:230]
    >NM_001282543.1:201-230
@@ -544,7 +545,7 @@ Support for compressed FASTA
----------------------------

``pyfaidx`` can create and read ``.fai`` indices for FASTA files that have
been compressed using the `bgzip <http://www.htslib.org/doc/tabix.html>`_
been compressed using the `bgzip <https://www.htslib.org/doc/bgzip.html>`_
tool from `samtools <http://www.htslib.org/>`_. ``bgzip`` writes compressed
data in a ``BGZF`` format. ``BGZF`` is ``gzip`` compatible, consisting of
multiple concatenated ``gzip`` blocks, each with an additional ``gzip``
+41 −18
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ if sys.version_info > (3, ):

dna_bases = re.compile(r'([ACTGNactgnYRWSKMDVHBXyrwskmdvhbx]+)')

__version__ = '0.5.5.2'
__version__ = '0.5.7'


class KeyFunctionError(ValueError):
@@ -123,7 +123,7 @@ class Sequence(object):
        >chr1
        AC
        """
        if self.start is None or self.end is None:
        if self.start is None or self.end is None or len(self.seq) == 0:
            correction_factor = 0
        elif len(
                self.seq
@@ -461,7 +461,7 @@ class Faidx(object):
                    rname, rlen, offset, lenc, lenb = line.split('\t')
                    rlen, offset, lenc, lenb = map(int,
                                                   (rlen, offset, lenc, lenb))
                    newlines = int(ceil(rlen / lenc) * (lenb - lenc))
                    newlines = int(ceil(rlen / lenc) * (lenb - lenc)) if lenc else 0
                    bend = offset + newlines + rlen
                    rec = IndexRecord(rlen, offset, lenc, lenb, bend,
                                      prev_bend)
@@ -508,8 +508,8 @@ class Faidx(object):
                    rname = None  # reference sequence name
                    offset = 0  # binary offset of end of current line
                    rlen = 0  # reference character length
                    blen = None  # binary line length (includes newline)
                    clen = None  # character line length
                    blen = 0  # binary line length (includes newline)
                    clen = 0  # character line length
                    bad_lines = []  # lines > || < than blen
                    thisoffset = offset
                    valid_entry = False
@@ -535,9 +535,9 @@ class Faidx(object):
                                    "Inconsistent line found in >{0} at "
                                    "line {1:n}.".format(
                                        rname, bad_lines[0][0] + 1))
                            blen = None
                            blen = 0
                            rlen = 0
                            clen = None
                            clen = 0
                            bad_lines = []
                            try:  # must catch empty deflines (actually these might be okay: https://github.com/samtools/htslib/pull/258)
                                rname = line.rstrip('\n\r')[1:].split()[
@@ -648,8 +648,8 @@ class Faidx(object):

        # Calculate offset (https://github.com/samtools/htslib/blob/20238f354894775ed22156cdd077bc0d544fa933/faidx.c#L398)
        newlines_before = int(
            (start0 - 1) / i.lenc * (i.lenb - i.lenc)) if start0 > 0 else 0
        newlines_to_end = int(end / i.lenc * (i.lenb - i.lenc))
            (start0 - 1) / i.lenc * (i.lenb - i.lenc)) if start0 > 0 and i.lenc else 0
        newlines_to_end = int(end / i.lenc * (i.lenb - i.lenc)) if i.lenc else 0
        newlines_inside = newlines_to_end - newlines_before
        seq_blen = newlines_inside + seq_len
        bstart = i.offset + newlines_before + start0
@@ -669,12 +669,15 @@ class Faidx(object):
            else:
                self.file.seek(bstart)

                # If the requested sequence exceeds len(FastaRecord), return as much as possible
                if bstart + seq_blen > i.bend and not self.strict_bounds:
                    seq_blen = i.bend - bstart

                # Otherwise it should be safe to read the sequence
                if seq_blen > 0:
                    seq = self.file.read(seq_blen).decode()
                elif seq_blen <= 0 and not self.strict_bounds:
                # If the requested sequence is negative, we will pad the empty string with default_seq.
                # This was changed to support #155 with strict_bounds=True.
                elif seq_blen <= 0:
                    seq = ''

        if not internals:
@@ -994,13 +997,9 @@ class Fasta(object):
            sequence_always_upper=sequence_always_upper,
            rebuild=rebuild,
            build_index=build_index)
        self.keys = self.faidx.index.keys
        if not self.mutable:
            self.records = dict(
                [(rname, FastaRecord(rname, self)) for rname in self.keys()])
        elif self.mutable:
            self.records = dict([(rname, MutableFastaRecord(rname, self))
                                 for rname in self.keys()])
        
        _record_constructor = MutableFastaRecord if self.mutable else FastaRecord
        self.records = OrderedDict([(rname, _record_constructor(rname, self)) for rname in self.faidx.index.keys()])

    def __contains__(self, rname):
        """Return True if genome contains record."""
@@ -1057,6 +1056,15 @@ class Fasta(object):
        # len(Sequence.seq) != end - start
        return Sequence(name=name, seq=seq, start=None, end=None)

    def keys(self):
        return self.records.keys()

    def values(self):
        return self.records.values()

    def items(self):
        return self.records.items()

    def close(self):
        self.__exit__()

@@ -1259,6 +1267,21 @@ def check_bad_lines(rname, bad_lines, i):
                       "Please report this issue at https://github.com/mdshw5/pyfaidx/issues " + \
                       str(bad_lines))
    
def get_valid_filename(s):
    """
    From https://github.com/django/django/blob/efc3e32d6d7fb9bb41be73b80c8607b653c1fbd6/django/utils/text.py#L222-L232
    Return the given string converted to a string that can be used for a clean
    filename. Remove leading and trailing spaces; convert other spaces to
    underscores; and remove anything that is not an alphanumeric, dash,
    underscore, or dot.
    >>> get_valid_filename("HPV16_144-1.fa")
    'HPV16_144-1.fa'
    >>> get_valid_filename("chromosome 6.fa")
    'chromosome_6.fa'
    """
    s = str(s).strip().replace(' ', '_')
    return re.sub(r'(?u)[^-\w.]', '', s)


if __name__ == "__main__":
    import doctest
+2 −4
Original line number Diff line number Diff line
@@ -3,11 +3,9 @@ import argparse
import sys
import os.path
import re
from pyfaidx import Fasta, wrap_sequence, FetchError, ucsc_split, bed_split
from pyfaidx import Fasta, wrap_sequence, FetchError, ucsc_split, bed_split, get_valid_filename
from collections import defaultdict

keepcharacters = (' ', '.', '_')

def write_sequence(args):
    _, ext = os.path.splitext(args.fasta)
    if ext:
@@ -36,7 +34,7 @@ def write_sequence(args):
                continue
        if args.split_files:  # open output file based on sequence name
            filename = '.'.join(str(e) for e in (name, start, end, ext) if e)
            filename = ''.join(c for c in filename if c.isalnum() or c in keepcharacters)
            filename = get_valid_filename(filename)
            outfile = open(filename, 'w')
        elif args.out:
            outfile = args.out
+2 −3
Original line number Diff line number Diff line
@@ -36,12 +36,11 @@ setup(
            "Intended Audience :: Science/Research",
            "Natural Language :: English",
            "Operating System :: Unix",
            "Programming Language :: Python :: 3.7",
            "Programming Language :: Python :: 3.6",
            "Programming Language :: Python :: 3.5",
            "Programming Language :: Python :: 3.4",
            "Programming Language :: Python :: 3.3",
            "Programming Language :: Python :: 3.2",
            "Programming Language :: Python :: 2.7",
            "Programming Language :: Python :: 2.6",
            "Programming Language :: Python :: Implementation :: PyPy",
            "Topic :: Scientific/Engineering :: Bio-Informatics"
    ]
Loading