Skip to content

Commit 63ea1df

Browse files
AbelarmBorda
andcommitted
Added the function for downloading the badges locally and replace the url with downlaod path (#4250)
* Added the function for downloading the badge locally, replacing the url * Fixed the pep8 errors, pointed out during pull request * Update setup.py * refactor * format * test * Added Doctest on the functions * test * test * fix * format * fix * fix * prune * fiix * fiix * flake8 * fix * imports * imports * imports * fixx * impoets * win * min Co-authored-by: Jirka Borovec <[email protected]> Co-authored-by: Jirka Borovec <[email protected]>
1 parent c971fe3 commit 63ea1df

File tree

4 files changed

+179
-43
lines changed

4 files changed

+179
-43
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ exclude tests
4242
recursive-exclude docs *
4343
exclude docs
4444
recursive-include docs/source/_images/logos/ *
45+
recursive-include docs/source/_images/badges/ *
4546
recursive-include docs/source/_images/general/ pl_overview* tf_* tutorial_* PTL101_*
4647

4748
# Include the Requirements

pytorch_lightning/__init__.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@
3434
"""
3535

3636
import logging as python_logging
37+
import os
3738

3839
_logger = python_logging.getLogger("lightning")
3940
_logger.addHandler(python_logging.StreamHandler())
4041
_logger.setLevel(python_logging.INFO)
4142

43+
PACKAGE_ROOT = os.path.dirname(__file__)
44+
PROJECT_ROOT = os.path.dirname(PACKAGE_ROOT)
45+
4246
try:
4347
# This variable is injected in the __builtins__ by the build
4448
# process. It used to enable importing subpackages of skimage when
@@ -68,12 +72,5 @@
6872
'metrics',
6973
]
7074

71-
# necessary for regular bolts imports. Skip exception since bolts is not always installed
72-
try:
73-
from pytorch_lightning import bolts
74-
except ImportError:
75-
pass
76-
# __call__ = __all__
77-
7875
# for compatibility with namespace packages
7976
__import__('pkg_resources').declare_namespace(__name__)

pytorch_lightning/setup_tools.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/usr/bin/env python
2+
# Copyright The PyTorch Lightning team.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
import os
16+
import re
17+
import warnings
18+
from urllib.error import HTTPError, URLError
19+
from urllib.request import Request, urlopen
20+
21+
from pytorch_lightning import PROJECT_ROOT, __homepage__, __version__
22+
23+
_PATH_BADGES = os.path.join('.', 'docs', 'source', '_images', 'badges')
24+
# badge to download
25+
_DEFAULT_BADGES = [
26+
'PyPI - Python Version',
27+
'PyPI Status',
28+
'PyPI Status',
29+
'Conda',
30+
'DockerHub',
31+
'codecov',
32+
'ReadTheDocs',
33+
'Slack',
34+
'Discourse status',
35+
'license',
36+
'Next Release'
37+
]
38+
39+
40+
def _load_requirements(path_dir, file_name='requirements.txt', comment_char='#'):
41+
"""Load requirements from a file
42+
43+
>>> _load_requirements(PROJECT_ROOT) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
44+
['numpy...', 'torch...', ...]
45+
"""
46+
with open(os.path.join(path_dir, file_name), 'r') as file:
47+
lines = [ln.strip() for ln in file.readlines()]
48+
reqs = []
49+
for ln in lines:
50+
# filer all comments
51+
if comment_char in ln:
52+
ln = ln[:ln.index(comment_char)].strip()
53+
# skip directly installed dependencies
54+
if ln.startswith('http'):
55+
continue
56+
if ln: # if requirement is not empty
57+
reqs.append(ln)
58+
return reqs
59+
60+
61+
def _parse_for_badge(text: str, path_badges: str = _PATH_BADGES, badge_names: list = _DEFAULT_BADGES):
62+
""" Returns the new parsed text with url change with local downloaded files
63+
64+
>>> _parse_for_badge('Some text here... ' # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
65+
... '[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pytorch-lightning)]'
66+
... '(https://pypi.org/project/pytorch-lightning/) and another text later')
67+
'Some text here...
68+
[![PyPI - Python Version](...docs...source..._images...badges...PyPI_Python_Version_badge.png)](https://pypi.org/project/pytorch-lightning/)
69+
and another text later'
70+
>>> import shutil
71+
>>> shutil.rmtree(_PATH_BADGES)
72+
"""
73+
for line in text.split(os.linesep):
74+
search_string = r'\[\!\[(.*)]\((.*)\)]'
75+
match = re.search(search_string, line)
76+
if match is None:
77+
continue
78+
79+
badge_name, badge_url = match.groups()
80+
# check if valid name
81+
if badge_name not in badge_names:
82+
continue
83+
84+
# download badge
85+
saved_badge_name = _download_badge(badge_url, badge_name, path_badges)
86+
87+
# replace url with local file path
88+
text = text.replace(f'[![{badge_name}]({badge_url})]', f'[![{badge_name}]({saved_badge_name})]')
89+
90+
return text
91+
92+
93+
def _save_file(url_badge, save, extension, headers):
94+
"""function for saving the badge either in `.png` or `.svg`"""
95+
96+
# because there are two badge with name `PyPI Status` the second one is download
97+
if 'https://pepy.tech/badge/pytorch-lightning' in url_badge:
98+
save += '_downloads'
99+
100+
try:
101+
req = Request(url=url_badge, headers=headers)
102+
resp = urlopen(req)
103+
except URLError:
104+
warnings.warn("Error while downloading the badge", UserWarning)
105+
else:
106+
save += extension
107+
with open(save, 'wb') as download_file:
108+
download_file.write(resp.read())
109+
110+
111+
def _download_badge(url_badge, badge_name, target_dir):
112+
"""Download badge from url
113+
114+
>>> path_img = _download_badge('https://img.shields.io/pypi/pyversions/pytorch-lightning',
115+
... 'PyPI - Python Version', '.')
116+
>>> os.path.isfile(path_img)
117+
True
118+
>>> path_img # doctest: +ELLIPSIS
119+
'...PyPI_Python_Version_badge.png'
120+
>>> os.remove(path_img)
121+
"""
122+
os.makedirs(target_dir, exist_ok=True)
123+
124+
headers = {
125+
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0',
126+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/svg,*/*;q=0.8',
127+
}
128+
129+
save_path = badge_name.replace(' - ', ' ')
130+
save_path = os.path.join(target_dir, f"{save_path.replace(' ', '_')}_badge")
131+
132+
if "?" in url_badge and ".png" not in url_badge:
133+
_save_file(url_badge, save_path, extension='.svg', headers=headers)
134+
return save_path + '.svg'
135+
else:
136+
try:
137+
# always try to download the png versions (some url have an already png version available)
138+
_save_file(url_badge, save_path, extension='.png', headers=headers)
139+
return save_path + '.png'
140+
except HTTPError as err:
141+
if err.code == 404:
142+
# save the `.svg`
143+
url_badge = url_badge.replace('.png', '.svg')
144+
_save_file(url_badge, save_path, extension='.svg', headers=headers)
145+
return save_path + '.svg'
146+
147+
148+
def _load_long_description(path_dir):
149+
"""Load readme as decribtion
150+
151+
>>> _load_long_description(PROJECT_ROOT) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
152+
'<div align="center">...'
153+
>>> import shutil
154+
>>> shutil.rmtree(_PATH_BADGES)
155+
"""
156+
# https://github.com/PyTorchLightning/pytorch-lightning/raw/master/docs/source/_images/lightning_module/pt_to_pl.png
157+
url = os.path.join(__homepage__, 'raw', __version__, 'docs')
158+
path_readme = os.path.join(path_dir, 'README.md')
159+
text = open(path_readme, encoding='utf-8').read()
160+
# replace relative repository path to absolute link to the release
161+
text = text.replace('](docs', f']({url}')
162+
# SVG images are not readable on PyPI, so replace them with PNG
163+
text = text.replace('.svg', '.png')
164+
# download badge and replace url with local file
165+
text = _parse_for_badge(text)
166+
return text

setup.py

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# limitations under the License.
1515

1616
import os
17-
from io import open
1817

1918
# Always prefer setuptools over distutils
2019
from setuptools import find_packages, setup
@@ -30,45 +29,18 @@
3029
builtins.__LIGHTNING_SETUP__ = True
3130

3231
import pytorch_lightning # noqa: E402
33-
34-
35-
def load_requirements(path_dir=PATH_ROOT, file_name='requirements.txt', comment_char='#'):
36-
with open(os.path.join(path_dir, file_name), 'r') as file:
37-
lines = [ln.strip() for ln in file.readlines()]
38-
reqs = []
39-
for ln in lines:
40-
# filer all comments
41-
if comment_char in ln:
42-
ln = ln[:ln.index(comment_char)].strip()
43-
# skip directly installed dependencies
44-
if ln.startswith('http'):
45-
continue
46-
if ln: # if requirement is not empty
47-
reqs.append(ln)
48-
return reqs
49-
50-
51-
def load_long_description():
52-
# https://github.com/PyTorchLightning/pytorch-lightning/raw/master/docs/source/_images/lightning_module/pt_to_pl.png
53-
url = os.path.join(pytorch_lightning.__homepage__, 'raw', pytorch_lightning.__version__, 'docs')
54-
text = open('README.md', encoding='utf-8').read()
55-
# replace relative repository path to absolute link to the release
56-
text = text.replace('](docs', f']({url}')
57-
# SVG images are not readable on PyPI, so replace them with PNG
58-
text = text.replace('.svg', '.png')
59-
return text
60-
32+
from pytorch_lightning.setup_tools import _load_long_description, _load_requirements # noqa: E402
6133

6234
# https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras
6335
# Define package extras. These are only installed if you specify them.
6436
# From remote, use like `pip install pytorch-lightning[dev, docs]`
6537
# From local copy of repo, use like `pip install ".[dev, docs]"`
6638
extras = {
6739
# 'docs': load_requirements(file_name='docs.txt'),
68-
'examples': load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='examples.txt'),
69-
'loggers': load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='loggers.txt'),
70-
'extra': load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='extra.txt'),
71-
'test': load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='test.txt')
40+
'examples': _load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='examples.txt'),
41+
'loggers': _load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='loggers.txt'),
42+
'extra': _load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='extra.txt'),
43+
'test': _load_requirements(path_dir=os.path.join(PATH_ROOT, 'requirements'), file_name='test.txt')
7244
}
7345
extras['dev'] = extras['extra'] + extras['loggers'] + extras['test']
7446
extras['all'] = extras['dev'] + extras['examples'] # + extras['docs']
@@ -89,7 +61,7 @@ def load_long_description():
8961
# the goal of the project is simplicity for researchers, don't want to add too much
9062
# engineer specific practices
9163
setup(
92-
name='pytorch-lightning',
64+
name="pytorch-lightning",
9365
version=pytorch_lightning.__version__,
9466
description=pytorch_lightning.__docs__,
9567
author=pytorch_lightning.__author__,
@@ -99,15 +71,15 @@ def load_long_description():
9971
license=pytorch_lightning.__license__,
10072
packages=find_packages(exclude=['tests', 'tests/*', 'benchmarks']),
10173

102-
long_description=load_long_description(),
74+
long_description=_load_long_description(PATH_ROOT),
10375
long_description_content_type='text/markdown',
10476
include_package_data=True,
10577
zip_safe=False,
10678

10779
keywords=['deep learning', 'pytorch', 'AI'],
10880
python_requires='>=3.6',
10981
setup_requires=[],
110-
install_requires=load_requirements(),
82+
install_requires=_load_requirements(PATH_ROOT),
11183
extras_require=extras,
11284

11385
project_urls={

0 commit comments

Comments
 (0)