Skip to content

Commit 93b4fb8

Browse files
siebrenfsimonvh
andauthored
release 0.9.3 (#150)
* gzip sanitized gtfs (#127) * more stabile testing(?) (#128) * added rm -rf function (#126) * added rm -rf function to fix clean * updated code for rm_rf * bucket changes (#129) * update readme (#132) * update readme * black. extended genomepy search (was an issue to black anyway) * fix (#133) * argparse action to parse genome from command line option * use genomes_dir argument * increased maximum complexity to 10 (#137) * remove 'alt' regions by default (#136) * remove 'alt' regions by default * Update CHANGELOG.md * increase rerun delay (1 -> 5 sec) * increase rerun delay (1 -> 10 sec) * updated CHANGELOG.md * Update version * fix CHANGELOG.md * Update CHANGELOG.md * Progress (#141) * tqdm progress bar for downloads & bgzipping, spinner for indexing * improve mkdir_p and rm_rf functionality * log removed alt-regions (#140) * Fix 142 (#143) * replace tempfile.TemporaryDirectory with mkdtemp and rm_rf * updated DOI * Update CHANGELOG.md * update tests * add mamba to travis * update version & changelog * update release checklist * variable fixed * Fix ftp (#148) * implement ftp downloading * implemented ftp link checking * added ftp fallback for NCBI * improved URL annotation searching * update version & changelog * catch ftp.nlst file not found error * update release checklist Co-authored-by: Simon van Heeringen <simon.vanheeringen@gmail.com>
1 parent ffc3135 commit 93b4fb8

15 files changed

Lines changed: 257 additions & 134 deletions

.travis.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ env:
99
global:
1010
- CC_TEST_REPORTER_ID=951f438ac8a0fa93801ff0bf69922df59fe03800bf7ea8ab77a3c26cda444979
1111
jobs:
12-
- PYTHON_VERSION: "3.6"
12+
- PYTHON_VERSION=3.6
13+
- PYTHON_VERSION=3.9
1314

1415
before_install:
1516
# install miniconda
@@ -32,8 +33,13 @@ install:
3233

3334
before_script:
3435
# install codeclimate test coverage
35-
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
36-
wget -O cc-test-reporter https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64;
36+
# - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
37+
# wget -O cc-test-reporter https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64;
38+
# chmod +x ./cc-test-reporter;
39+
# ./cc-test-reporter before-build;
40+
# fi
41+
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
42+
wget -O cc-test-reporter https://codeclimate.com/downloads/test-reporter/test-reporter-latest-darwin-amd64;
3743
chmod +x ./cc-test-reporter;
3844
./cc-test-reporter before-build;
3945
fi
@@ -47,6 +53,6 @@ script:
4753

4854
after_script:
4955
# send the coverage data to Code Climate
50-
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
56+
- if [ -f ./cc-test-reporter ]; then
5157
./cc-test-reporter after-build -t coverage.py --exit-code $TRAVIS_TEST_RESULT;
5258
fi

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
66

77
## [Unreleased]
88

9+
## [0.9.3] - 2021-02-03
10+
11+
### Changed
12+
- URL provider got better at searching for annotation files
13+
- NCBI provider will fall back on FTP if HTTPS is offline
14+
15+
### Fixed
16+
- genomes from ftp locations not working
17+
918
## [0.9.2] - 2021-01-28
1019

1120
### Added
@@ -277,6 +286,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
277286
- Added `-r` and `--match/--no-match` option to select sequences by regex.
278287

279288
[Unreleased]: https://github.com/vanheeringen-lab/genomepy/compare/master...develop
289+
[0.9.3]: https://github.com/vanheeringen-lab/genomepy/compare/0.9.2...0.9.3
280290
[0.9.2]: https://github.com/vanheeringen-lab/genomepy/compare/0.9.1...0.9.2
281291
[0.9.1]: https://github.com/vanheeringen-lab/genomepy/compare/0.9.0...0.9.1
282292
[0.9.0]: https://github.com/vanheeringen-lab/genomepy/compare/0.8.4...0.9.0

docs/release_checklist.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ twine upload --repository-url https://test.pypi.org/legacy/ dist/genomepy-${new_
2727
# the \ is to escape the ==, so the variable ${new_version} can be called
2828
pip install --extra-index-url https://test.pypi.org/simple/ genomepy\==${new_version}
2929
30-
genomepy search xenopus_tropicalis
30+
# tests
31+
genomepy --version;
32+
genomepy --help;
33+
genomepy install --help;
34+
genomepy clean
35+
genomepy search xenopus_tropicalis;
36+
genomepy install TAIR10 -af -p ensembl;
37+
genomepy install sacCer3 -af -p ucsc;
38+
genomepy install ASM2732v1 -af -p ncbi;
3139
```
3240

3341
6. Finish the release:
@@ -48,7 +56,7 @@ git push --follow-tags origin develop
4856

4957
```
5058
python setup.py sdist bdist_wheel
51-
twine upload dist/genomepy-${version}*
59+
twine upload dist/genomepy-${new_version}*
5260
```
5361

5462
10. Create release on github (if it not already exists)
@@ -57,8 +65,14 @@ twine upload dist/genomepy-${version}*
5765
* Download the tarball from the github release (`.tar.gz`).
5866
* Attach downloaded tarball to release as binary (this way the download count get tracked).
5967

68+
11a. Update bioconda package
6069

61-
11. Update bioconda package
70+
* wait for the bioconda bot to create a PR
71+
* update dependencies in the bioconda recipe.yaml if needed
72+
* approve the PR
73+
* comment: @bioconda-bot please merge
74+
75+
11b. Update bioconda package
6276

6377
* fork bioconda/bioconda-recipes
6478
* follow the steps in the [docs](https://bioconda.github.io/contributor/workflow.html)

genomepy/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Metadata"""
2-
__version__ = "0.9.2"
2+
__version__ = "0.9.3"
33
__author__ = "Simon van Heeringen"

genomepy/genome.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def __init__(self, name, genomes_dir=None):
4949
# file paths
5050
self.genome_file = self.filename
5151
self.genome_dir = os.path.dirname(self.filename)
52-
self.index_file = self.filename + ".fai"
52+
self.index_file = self.genome_file + ".fai"
5353
self.sizes_file = self.genome_file + ".sizes"
5454
self.gaps_file = os.path.join(self.genome_dir, self.name + ".gaps.bed")
5555
self.readme_file = os.path.join(self.genome_dir, "README.txt")

genomepy/plugins/__init__.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +0,0 @@
1-
# def list_plugins():
2-
# path = os.path.dirname(__file__)
3-
# for x in os.listdir(path):
4-
# if x != "__init__.py" and x.endswith(".py"):
5-
# print(x)
6-
# module = __import__(x)
7-
# print(help(module))
8-
#
9-
#
10-
# list_plugins()

genomepy/provider.py

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ def download_and_generate_annotation(genomes_dir, annot_url, localname):
371371
elif "gff" in ext:
372372
cmd = "gff3ToGenePred -geneNameAttr=gene {0} {1}"
373373
elif "gtf" in ext:
374-
cmd = "gtfToGenePred {0} {1}"
374+
cmd = "gtfToGenePred -ignoreGroupsWithoutExons {0} {1}"
375375
elif "txt" in ext:
376376
# UCSC annotations only
377377
with open(annot_file) as f:
@@ -524,7 +524,7 @@ def search(self, term):
524524
term = safe(str(term))
525525
if term.startswith("GCA_") and self.name != "NCBI":
526526
for row in self._search_accessions(term):
527-
yield (row)
527+
yield row
528528

529529
elif is_number(term):
530530
for name in genomes:
@@ -1055,14 +1055,10 @@ def get_genome_download_link(self, name, mask="soft", **kwargs):
10551055
------
10561056
str with the http/ftp download link.
10571057
"""
1058-
genome = self.genomes[safe(name)]
1058+
# only soft masked genomes available. can be (un)masked in _post_process_download
1059+
link = self._ftp_or_html_link(name, file_suffix="_genomic.fna.gz")
10591060

1060-
# only soft masked genomes available. can be (un)masked in _post _process_download
1061-
link = genome["ftp_path"]
1062-
link = link.replace("ftp://", "https://")
1063-
link += "/" + link.split("/")[-1] + "_genomic.fna.gz"
1064-
1065-
if check_url(link, 2):
1061+
if link:
10661062
return link
10671063

10681064
raise GenomeDownloadError(
@@ -1092,10 +1088,9 @@ def _post_process_download(self, name, localname, out_dir, mask="soft"):
10921088
masking level: soft/hard/none, default=soft
10931089
"""
10941090
# Create mapping of accessions to names
1095-
genome = self.genomes[safe(name)]
1096-
url = genome["ftp_path"]
1097-
url += f"/{url.split('/')[-1]}_assembly_report.txt"
1098-
url = url.replace("ftp://", "https://")
1091+
url = self._ftp_or_html_link(
1092+
name, file_suffix="_assembly_report.txt", skip_check=True
1093+
)
10991094

11001095
tr = {}
11011096
urlcleanup()
@@ -1148,13 +1143,21 @@ def get_annotation_download_link(self, name, **kwargs):
11481143
name : str
11491144
Genome name
11501145
"""
1146+
return self._ftp_or_html_link(name, file_suffix="_genomic.gff.gz")
1147+
1148+
def _ftp_or_html_link(self, name, file_suffix, skip_check=False):
1149+
"""
1150+
NCBI's files are accessible over FTP and HTTPS
1151+
Try HTTPS first and return the first functioning link
1152+
"""
11511153
genome = self.genomes[safe(name)]
1152-
link = genome["ftp_path"]
1153-
link = link.replace("ftp://", "https://")
1154-
link += "/" + link.split("/")[-1] + "_genomic.gff.gz"
1154+
ftp_link = genome["ftp_path"]
1155+
html_link = ftp_link.replace("ftp://", "https://")
1156+
for link in [html_link, ftp_link]:
1157+
link += "/" + link.split("/")[-1] + file_suffix
11551158

1156-
if check_url(link, 2):
1157-
return link
1159+
if skip_check or check_url(link, max_tries=2, timeout=10):
1160+
return link
11581161

11591162

11601163
@register_provider("URL")
@@ -1188,6 +1191,9 @@ def search(self, term):
11881191
same as if no genomes were found at the other providers"""
11891192
yield from ()
11901193

1194+
def _genome_info_tuple(self, name):
1195+
return tuple()
1196+
11911197
def get_genome_download_link(self, url, mask=None, **kwargs):
11921198
return url
11931199

@@ -1203,55 +1209,41 @@ def get_annotation_download_link(self, name, **kwargs):
12031209
"Only (gzipped) gtf, gff and bed files are supported.\n"
12041210
)
12051211

1206-
if check_url(link):
1207-
return link
1212+
return link
12081213

12091214
@staticmethod
1210-
def search_url_for_annotation(url):
1211-
"""Attempts to find a gtf or gff3 file in the same location as the genome url"""
1215+
def search_url_for_annotations(url, name):
1216+
"""Attempts to find gtf or gff3 files in the same location as the genome url"""
12121217
urldir = os.path.dirname(url)
12131218
sys.stderr.write(
1214-
"You have requested gene annotation to be downloaded.\n"
1219+
"You have requested the gene annotation to be downloaded.\n"
12151220
"Genomepy will check the remote directory:\n"
12161221
f"{urldir} for annotation files...\n"
12171222
)
12181223

1219-
# try to find a GTF or GFF3 file
1220-
name = get_localname(url)
1221-
with urlopen(urldir) as f:
1222-
for urlline in f.readlines():
1223-
urlstr = str(urlline)
1224-
if any(
1225-
substring in urlstr.lower() for substring in [".gtf", name + ".gff"]
1226-
):
1227-
break
1224+
def fuzzy_annotation_search(search_name, search_list):
1225+
"""Returns all files containing both name and an annotation extension"""
1226+
hits = []
1227+
for ext in ["gtf", "gff"]:
1228+
# .*? = non greedy filler. 3? = optional 3 (for gff3). (\.gz)? = optional .gz
1229+
expr = f"{search_name}.*?\.{ext}3?(\.gz)?" # noqa: W605
1230+
for line in search_list:
1231+
hit = re.search(expr, line, flags=re.IGNORECASE)
1232+
if hit:
1233+
hits.append(hit[0])
1234+
return hits
12281235

1229-
# retrieve the filename from the HTML line
1230-
fname = ""
1231-
for split in re.split('>|<|><|/|"', urlstr):
1232-
if split.lower().endswith(
1233-
(
1234-
".gtf",
1235-
".gtf.gz",
1236-
name + ".gff",
1237-
name + ".gff.gz",
1238-
name + ".gff3",
1239-
name + ".gff3.gz",
1240-
)
1241-
):
1242-
fname = split
1243-
break
1244-
else:
1236+
# try to find a GTF or GFF3 file
1237+
dirty_list = [str(line) for line in urlopen(urldir).readlines()]
1238+
fnames = fuzzy_annotation_search(name, dirty_list)
1239+
if not fnames:
12451240
raise FileNotFoundError(
12461241
"Could not parse the remote directory. "
12471242
"Please supply a URL using --url-to-annotation.\n"
12481243
)
12491244

1250-
# set variables for downloading
1251-
link = urldir + "/" + fname
1252-
1253-
if check_url(link):
1254-
return link
1245+
links = [urldir + "/" + fname for fname in fnames]
1246+
return links
12551247

12561248
def download_annotation(self, url, genomes_dir=None, localname=None, **kwargs):
12571249
"""
@@ -1279,8 +1271,20 @@ def download_annotation(self, url, genomes_dir=None, localname=None, **kwargs):
12791271
genomes_dir = get_genomes_dir(genomes_dir, check_exist=False)
12801272

12811273
if kwargs.get("to_annotation"):
1282-
link = self.get_annotation_download_link(None, **kwargs)
1274+
links = [self.get_annotation_download_link(None, **kwargs)]
12831275
else:
1284-
link = self.search_url_for_annotation(url)
1276+
# can return multiple possible hits
1277+
links = self.search_url_for_annotations(url, name)
12851278

1286-
self.attempt_and_report(name, localname, link, genomes_dir)
1279+
for link in links:
1280+
try:
1281+
self.attempt_and_report(name, localname, link, genomes_dir)
1282+
break
1283+
except GenomeDownloadError as e:
1284+
if not link == links[-1]:
1285+
sys.stdout.write(
1286+
"\nOne of the potential annotations was incompatible with genomepy."
1287+
+ "\nAttempting another...\n\n"
1288+
)
1289+
continue
1290+
return e

0 commit comments

Comments
 (0)