mirror of
https://github.com/google/pybadges.git
synced 2025-07-21 12:41:08 +02:00
Enforce yapf for lint.
This commit is contained in:
6
.yapfignore
Normal file
6
.yapfignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Virtual environments
|
||||||
|
venv
|
||||||
|
**/venv
|
||||||
|
|
||||||
|
# Automatically generated nox files
|
||||||
|
.nox
|
@@ -22,6 +22,13 @@ use GitHub pull requests for this purpose. Consult
|
|||||||
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||||
information on using pull requests.
|
information on using pull requests.
|
||||||
|
|
||||||
|
Please run the nox tests before sending your code for review. You can do that
|
||||||
|
with:
|
||||||
|
```sh
|
||||||
|
pip install .[dev]
|
||||||
|
nox
|
||||||
|
```
|
||||||
|
|
||||||
## Community Guidelines
|
## Community Guidelines
|
||||||
|
|
||||||
This project follows [Google's Open Source Community
|
This project follows [Google's Open Source Community
|
||||||
|
@@ -22,6 +22,7 @@ import pkg_resources
|
|||||||
|
|
||||||
import pybadges
|
import pybadges
|
||||||
|
|
||||||
|
|
||||||
def generate_images(source_json_path, target_directory):
|
def generate_images(source_json_path, target_directory):
|
||||||
os.makedirs(target_directory, exist_ok=True)
|
os.makedirs(target_directory, exist_ok=True)
|
||||||
with open(source_json_path) as f:
|
with open(source_json_path) as f:
|
||||||
@@ -34,15 +35,20 @@ def generate_images(source_json_path, target_directory):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description='generate a github-style badge given some text and colors')
|
parser = argparse.ArgumentParser(
|
||||||
|
description='generate a github-style badge given some text and colors')
|
||||||
|
|
||||||
parser.add_argument('--source-path',
|
parser.add_argument(
|
||||||
default=pkg_resources.resource_filename(__name__, 'tests/test-badges.json'),
|
'--source-path',
|
||||||
help='the text to show on the left-hand-side of the badge')
|
default=pkg_resources.resource_filename(__name__,
|
||||||
|
'tests/test-badges.json'),
|
||||||
|
help='the text to show on the left-hand-side of the badge')
|
||||||
|
|
||||||
parser.add_argument('--destination-dir',
|
parser.add_argument(
|
||||||
default=pkg_resources.resource_filename(__name__, 'tests/golden-images'),
|
'--destination-dir',
|
||||||
help='the text to show on the left-hand-side of the badge')
|
default=pkg_resources.resource_filename(__name__,
|
||||||
|
'tests/golden-images'),
|
||||||
|
help='the text to show on the left-hand-side of the badge')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
generate_images(args.source_path, args.destination_dir)
|
generate_images(args.source_path, args.destination_dir)
|
||||||
|
|
||||||
|
28
noxfile.py
28
noxfile.py
@@ -11,20 +11,14 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Nox config for running lint and unit tests."""
|
"""Nox config for running lint and unit tests."""
|
||||||
|
|
||||||
import nox
|
import nox
|
||||||
|
|
||||||
|
|
||||||
def _run_tests(session):
|
def _run_tests(session):
|
||||||
session.run(
|
session.run('py.test', '--quiet', 'tests', 'server-example',
|
||||||
'py.test',
|
*session.posargs)
|
||||||
'--quiet',
|
|
||||||
'tests',
|
|
||||||
'server-example',
|
|
||||||
*session.posargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@nox.session
|
@nox.session
|
||||||
@@ -33,10 +27,8 @@ def lint(session):
|
|||||||
Returns a failure if flake8 finds linting errors or sufficiently
|
Returns a failure if flake8 finds linting errors or sufficiently
|
||||||
serious code quality issues.
|
serious code quality issues.
|
||||||
"""
|
"""
|
||||||
session.install('flake8')
|
session.install('yapf')
|
||||||
session.run('flake8', 'pybadges')
|
session.run('python3', '-m', 'yapf', '--diff', '-r', '.')
|
||||||
session.run('flake8', 'tests')
|
|
||||||
session.run('flake8', 'server-example')
|
|
||||||
|
|
||||||
|
|
||||||
@nox.session
|
@nox.session
|
||||||
@@ -48,8 +40,9 @@ def unit(session):
|
|||||||
|
|
||||||
|
|
||||||
@nox.session(python=['3.4', '3.5', '3.6', '3.7', '3.8'])
|
@nox.session(python=['3.4', '3.5', '3.6', '3.7', '3.8'])
|
||||||
@nox.parametrize('install',
|
@nox.parametrize(
|
||||||
['Jinja2==2.9.0', 'Pillow==5.0.0', 'requests==2.9.0', 'xmldiff==2.4'])
|
'install',
|
||||||
|
['Jinja2==2.9.0', 'Pillow==5.0.0', 'requests==2.9.0', 'xmldiff==2.4'])
|
||||||
def compatibility(session, install):
|
def compatibility(session, install):
|
||||||
"""Run the unit test suite with each support library and Python version."""
|
"""Run the unit test suite with each support library and Python version."""
|
||||||
|
|
||||||
@@ -64,8 +57,5 @@ def type_check(session):
|
|||||||
"""Run type checking using pytype."""
|
"""Run type checking using pytype."""
|
||||||
session.install('-e', '.[dev]')
|
session.install('-e', '.[dev]')
|
||||||
session.install('pytype')
|
session.install('pytype')
|
||||||
session.run(
|
session.run('pytype', '--python-version=3.6', '--disable=pyi-error',
|
||||||
'pytype',
|
'pybadges')
|
||||||
'--python-version=3.6',
|
|
||||||
'--disable=pyi-error',
|
|
||||||
'pybadges')
|
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Creates a github-style badge as a SVG image.
|
"""Creates a github-style badge as a SVG image.
|
||||||
|
|
||||||
This package seeks to generate semantically-identical output to the JavaScript
|
This package seeks to generate semantically-identical output to the JavaScript
|
||||||
@@ -44,7 +43,6 @@ from pybadges import text_measurer
|
|||||||
from pybadges import precalculated_text_measurer
|
from pybadges import precalculated_text_measurer
|
||||||
from pybadges.version import __version__
|
from pybadges.version import __version__
|
||||||
|
|
||||||
|
|
||||||
_JINJA2_ENVIRONMENT = jinja2.Environment(
|
_JINJA2_ENVIRONMENT = jinja2.Environment(
|
||||||
trim_blocks=True,
|
trim_blocks=True,
|
||||||
lstrip_blocks=True,
|
lstrip_blocks=True,
|
||||||
@@ -77,6 +75,7 @@ def _remove_blanks(node):
|
|||||||
elif x.nodeType == minidom.Node.ELEMENT_NODE:
|
elif x.nodeType == minidom.Node.ELEMENT_NODE:
|
||||||
_remove_blanks(x)
|
_remove_blanks(x)
|
||||||
|
|
||||||
|
|
||||||
def _embed_image(url: str) -> str:
|
def _embed_image(url: str) -> str:
|
||||||
parsed_url = urllib.parse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
|
|
||||||
@@ -90,8 +89,8 @@ def _embed_image(url: str) -> str:
|
|||||||
raise ValueError('no "Content-Type" header')
|
raise ValueError('no "Content-Type" header')
|
||||||
content_type, image_type = content_type.split('/')
|
content_type, image_type = content_type.split('/')
|
||||||
if content_type != 'image':
|
if content_type != 'image':
|
||||||
raise ValueError('expected an image, got "{0}"'.format(
|
raise ValueError(
|
||||||
content_type))
|
'expected an image, got "{0}"'.format(content_type))
|
||||||
image_data = r.content
|
image_data = r.content
|
||||||
elif parsed_url.scheme:
|
elif parsed_url.scheme:
|
||||||
raise ValueError('unsupported scheme "{0}"'.format(parsed_url.scheme))
|
raise ValueError('unsupported scheme "{0}"'.format(parsed_url.scheme))
|
||||||
@@ -113,16 +112,21 @@ def _embed_image(url: str) -> str:
|
|||||||
return 'data:image/{};base64,{}'.format(image_type, encoded_image)
|
return 'data:image/{};base64,{}'.format(image_type, encoded_image)
|
||||||
|
|
||||||
|
|
||||||
def badge(left_text: str, right_text: str, left_link: Optional[str] = None,
|
def badge(
|
||||||
right_link: Optional[str] = None,
|
left_text: str,
|
||||||
whole_link: Optional[str] = None, logo: Optional[str] = None,
|
right_text: str,
|
||||||
left_color: str = '#555', right_color: str = '#007ec6',
|
left_link: Optional[str] = None,
|
||||||
measurer: Optional[text_measurer.TextMeasurer] = None,
|
right_link: Optional[str] = None,
|
||||||
embed_logo: bool = False,
|
whole_link: Optional[str] = None,
|
||||||
whole_title: Optional[str] = None,
|
logo: Optional[str] = None,
|
||||||
left_title: Optional[str] = None,
|
left_color: str = '#555',
|
||||||
right_title: Optional[str] = None,
|
right_color: str = '#007ec6',
|
||||||
) -> str:
|
measurer: Optional[text_measurer.TextMeasurer] = None,
|
||||||
|
embed_logo: bool = False,
|
||||||
|
whole_title: Optional[str] = None,
|
||||||
|
left_title: Optional[str] = None,
|
||||||
|
right_title: Optional[str] = None,
|
||||||
|
) -> str:
|
||||||
"""Creates a github-style badge as an SVG image.
|
"""Creates a github-style badge as an SVG image.
|
||||||
|
|
||||||
>>> badge(left_text='coverage', right_text='23%', right_color='red')
|
>>> badge(left_text='coverage', right_text='23%', right_color='red')
|
||||||
@@ -172,8 +176,7 @@ def badge(left_text: str, right_text: str, left_link: Optional[str] = None,
|
|||||||
"""
|
"""
|
||||||
if measurer is None:
|
if measurer is None:
|
||||||
measurer = (
|
measurer = (
|
||||||
precalculated_text_measurer.PrecalculatedTextMeasurer
|
precalculated_text_measurer.PrecalculatedTextMeasurer.default())
|
||||||
.default())
|
|
||||||
|
|
||||||
if (left_link or right_link) and whole_link:
|
if (left_link or right_link) and whole_link:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Output a github-style badge as an SVG image given some text and colors.
|
"""Output a github-style badge as an SVG image given some text and colors.
|
||||||
|
|
||||||
For more information, run:
|
For more information, run:
|
||||||
@@ -40,20 +39,19 @@ def main():
|
|||||||
'--right-text',
|
'--right-text',
|
||||||
default='APACHE',
|
default='APACHE',
|
||||||
help='the text to show on the right-hand-side of the badge')
|
help='the text to show on the right-hand-side of the badge')
|
||||||
parser.add_argument(
|
parser.add_argument('--whole-link',
|
||||||
'--whole-link',
|
default=None,
|
||||||
default=None,
|
help='the url to redirect to when the badge is clicked')
|
||||||
help='the url to redirect to when the badge is clicked')
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--left-link',
|
'--left-link',
|
||||||
default=None,
|
default=None,
|
||||||
help='the url to redirect to when the left-hand of the badge is ' +
|
help='the url to redirect to when the left-hand of the badge is ' +
|
||||||
'clicked')
|
'clicked')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--right-link',
|
'--right-link',
|
||||||
default=None,
|
default=None,
|
||||||
help='the url to redirect to when the right-hand of the badge is ' +
|
help='the url to redirect to when the right-hand of the badge is ' +
|
||||||
'clicked')
|
'clicked')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--left-color',
|
'--left-color',
|
||||||
default='#555',
|
default='#555',
|
||||||
@@ -73,68 +71,68 @@ def main():
|
|||||||
const='yes',
|
const='yes',
|
||||||
default='no',
|
default='no',
|
||||||
help='if the logo is specified then include the image data directly in '
|
help='if the logo is specified then include the image data directly in '
|
||||||
'the badge (this will prevent a URL fetch and may work around the '
|
'the badge (this will prevent a URL fetch and may work around the '
|
||||||
'fact that some browsers do not fetch external image references); '
|
'fact that some browsers do not fetch external image references); '
|
||||||
'only works if --logo is a HTTP/HTTPS URI or a file path')
|
'only works if --logo is a HTTP/HTTPS URI or a file path')
|
||||||
parser.add_argument(
|
parser.add_argument('--browser',
|
||||||
'--browser',
|
action='store_true',
|
||||||
action='store_true',
|
default=False,
|
||||||
default=False,
|
help='display the badge in a browser tab')
|
||||||
help='display the badge in a browser tab')
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--use-pil-text-measurer',
|
'--use-pil-text-measurer',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
default=False,
|
default=False,
|
||||||
help='use the PilMeasurer to measure the length of text (kerning may '
|
help='use the PilMeasurer to measure the length of text (kerning may '
|
||||||
'be more precise for non-Western languages. ' +
|
'be more precise for non-Western languages. ' +
|
||||||
'--deja-vu-sans-path must also be set.')
|
'--deja-vu-sans-path must also be set.')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--deja-vu-sans-path',
|
'--deja-vu-sans-path',
|
||||||
default=None,
|
default=None,
|
||||||
help='the path to the ttf font file containing DejaVu Sans. If not ' +
|
help='the path to the ttf font file containing DejaVu Sans. If not ' +
|
||||||
'present on your system, you can download it from ' +
|
'present on your system, you can download it from ' +
|
||||||
'https://www.fontsquirrel.com/fonts/dejavu-sans')
|
'https://www.fontsquirrel.com/fonts/dejavu-sans')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--whole-title',
|
'--whole-title',
|
||||||
default=None,
|
default=None,
|
||||||
help='the title to associate with the entire badge. See '
|
help='the title to associate with the entire badge. See '
|
||||||
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--left-title',
|
'--left-title',
|
||||||
default=None,
|
default=None,
|
||||||
help='the title to associate with the left part of the badge. See '
|
help='the title to associate with the left part of the badge. See '
|
||||||
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--right-title',
|
'--right-title',
|
||||||
default=None,
|
default=None,
|
||||||
help='the title to associate with the right part of the badge. See '
|
help='the title to associate with the right part of the badge. See '
|
||||||
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
'https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-v', '--version',
|
'-v',
|
||||||
|
'--version',
|
||||||
action='version',
|
action='version',
|
||||||
version='%(prog)s {version}'.format(version=__version__))
|
version='%(prog)s {version}'.format(version=__version__))
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if (args.left_link or args.right_link) and args.whole_link:
|
if (args.left_link or args.right_link) and args.whole_link:
|
||||||
print(
|
print('argument --whole-link: cannot be set with ' +
|
||||||
'argument --whole-link: cannot be set with ' +
|
'--left-link or --right-link',
|
||||||
'--left-link or --right-link',
|
file=sys.stderr)
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
measurer = None
|
measurer = None
|
||||||
if args.use_pil_text_measurer:
|
if args.use_pil_text_measurer:
|
||||||
if args.deja_vu_sans_path is None:
|
if args.deja_vu_sans_path is None:
|
||||||
print(
|
print('argument --use-pil-text-measurer: must also set ' +
|
||||||
'argument --use-pil-text-measurer: must also set ' +
|
'--deja-vu-sans-path',
|
||||||
'--deja-vu-sans-path',
|
file=sys.stderr)
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
from pybadges import pil_text_measurer
|
from pybadges import pil_text_measurer
|
||||||
measurer = pil_text_measurer.PilMeasurer(args.deja_vu_sans_path)
|
measurer = pil_text_measurer.PilMeasurer(args.deja_vu_sans_path)
|
||||||
|
|
||||||
badge = pybadges.badge(left_text=args.left_text, right_text=args.right_text,
|
badge = pybadges.badge(left_text=args.left_text,
|
||||||
left_link=args.left_link, right_link=args.right_link,
|
right_text=args.right_text,
|
||||||
|
left_link=args.left_link,
|
||||||
|
right_link=args.right_link,
|
||||||
whole_link=args.whole_link,
|
whole_link=args.whole_link,
|
||||||
left_color=args.left_color,
|
left_color=args.left_color,
|
||||||
right_color=args.right_color,
|
right_color=args.right_color,
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
||||||
|
|
||||||
Uses a PIL/Pillow to determine the string length.
|
Uses a PIL/Pillow to determine the string length.
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Creates a JSON file that can be used by precalculated_text_measurer.py.
|
"""Creates a JSON file that can be used by precalculated_text_measurer.py.
|
||||||
|
|
||||||
Creates a JSON file that can be used by
|
Creates a JSON file that can be used by
|
||||||
@@ -106,8 +105,8 @@ def calculate_character_to_length_mapping(
|
|||||||
|
|
||||||
|
|
||||||
def calculate_pair_to_kern_mapping(
|
def calculate_pair_to_kern_mapping(
|
||||||
measurer: text_measurer.TextMeasurer,
|
measurer: text_measurer.TextMeasurer, char_to_length: Mapping[str,
|
||||||
char_to_length: Mapping[str, float],
|
float],
|
||||||
characters: Iterable[str]) -> Mapping[str, float]:
|
characters: Iterable[str]) -> Mapping[str, float]:
|
||||||
"""Returns a mapping between each *pair* of characters and their kerning.
|
"""Returns a mapping between each *pair* of characters and their kerning.
|
||||||
|
|
||||||
@@ -147,16 +146,20 @@ def write_json(f: TextIO, deja_vu_sans_path: str,
|
|||||||
generate_supported_characters(deja_vu_sans_path))
|
generate_supported_characters(deja_vu_sans_path))
|
||||||
kerning_characters = ''.join(
|
kerning_characters = ''.join(
|
||||||
generate_encodeable_characters(supported_characters, encodings))
|
generate_encodeable_characters(supported_characters, encodings))
|
||||||
char_to_length = calculate_character_to_length_mapping(measurer,
|
char_to_length = calculate_character_to_length_mapping(
|
||||||
supported_characters)
|
measurer, supported_characters)
|
||||||
pair_to_kerning = calculate_pair_to_kern_mapping(measurer, char_to_length,
|
pair_to_kerning = calculate_pair_to_kern_mapping(measurer, char_to_length,
|
||||||
kerning_characters)
|
kerning_characters)
|
||||||
json.dump(
|
json.dump(
|
||||||
{'mean-character-length': statistics.mean(char_to_length.values()),
|
{
|
||||||
'character-lengths': char_to_length,
|
'mean-character-length': statistics.mean(char_to_length.values()),
|
||||||
'kerning-characters': kerning_characters,
|
'character-lengths': char_to_length,
|
||||||
'kerning-pairs': pair_to_kerning},
|
'kerning-characters': kerning_characters,
|
||||||
f, sort_keys=True, indent=1)
|
'kerning-pairs': pair_to_kerning
|
||||||
|
},
|
||||||
|
f,
|
||||||
|
sort_keys=True,
|
||||||
|
indent=1)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -167,8 +170,8 @@ def main():
|
|||||||
'--deja-vu-sans-path',
|
'--deja-vu-sans-path',
|
||||||
required=True,
|
required=True,
|
||||||
help='the path to the ttf font file containing DejaVu Sans. If not ' +
|
help='the path to the ttf font file containing DejaVu Sans. If not ' +
|
||||||
'present on your system, you can download it from ' +
|
'present on your system, you can download it from ' +
|
||||||
'https://www.fontsquirrel.com/fonts/dejavu-sans')
|
'https://www.fontsquirrel.com/fonts/dejavu-sans')
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--kerning-pair-encodings',
|
'--kerning-pair-encodings',
|
||||||
@@ -178,11 +181,10 @@ def main():
|
|||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--output-json-file',
|
'--output-json-file',
|
||||||
default=os.path.join(os.path.dirname(__file__),
|
default=os.path.join(os.path.dirname(__file__), 'default-widths.json'),
|
||||||
'default-widths.json'),
|
|
||||||
help='the path where the generated JSON will be placed. If the ' +
|
help='the path where the generated JSON will be placed. If the ' +
|
||||||
'provided filename extension ends with .xz then the output' +
|
'provided filename extension ends with .xz then the output' +
|
||||||
'will be compressed using lzma.')
|
'will be compressed using lzma.')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -196,8 +198,8 @@ def main():
|
|||||||
return open(args.output_json_file, 'wt')
|
return open(args.output_json_file, 'wt')
|
||||||
|
|
||||||
with create_file() as f:
|
with create_file() as f:
|
||||||
write_json(
|
write_json(f, args.deja_vu_sans_path, measurer,
|
||||||
f, args.deja_vu_sans_path, measurer, args.kerning_pair_encodings)
|
args.kerning_pair_encodings)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
||||||
|
|
||||||
Uses a precalculated set of metrics to calculate the string length.
|
Uses a precalculated set of metrics to calculate the string length.
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
"""Measure the width, in pixels, of a string rendered using DejaVu Sans 110pt.
|
||||||
|
|
||||||
Contains only an abstract base class.
|
Contains only an abstract base class.
|
||||||
|
@@ -12,4 +12,4 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
__version__='2.2.1' # Also change in setup.py.
|
__version__ = '2.3.0' # Also change in setup.py.
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
""" Example CI server that serves badges."""
|
""" Example CI server that serves badges."""
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
@@ -23,10 +22,9 @@ app = Flask(__name__)
|
|||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def serveBadges():
|
def serveBadges():
|
||||||
badge = pybadges.badge(
|
badge = pybadges.badge(left_text='build',
|
||||||
left_text='build',
|
right_text='passing',
|
||||||
right_text='passing',
|
right_color='#008000')
|
||||||
right_color='#008000')
|
|
||||||
|
|
||||||
response = flask.make_response(badge)
|
response = flask.make_response(badge)
|
||||||
response.content_type = 'image/svg+xml'
|
response.content_type = 'image/svg+xml'
|
||||||
|
@@ -14,16 +14,17 @@
|
|||||||
|
|
||||||
"Tests for app"
|
"Tests for app"
|
||||||
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import app
|
import app
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def client():
|
def client():
|
||||||
with app.app.test_client() as client:
|
with app.app.test_client() as client:
|
||||||
yield client
|
yield client
|
||||||
|
|
||||||
|
|
||||||
def test_image(client):
|
def test_image(client):
|
||||||
rv = client.get("/")
|
rv = client.get("/")
|
||||||
assert b'build' in rv.data
|
assert b'build' in rv.data
|
||||||
|
18
setup.py
18
setup.py
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""A setup module for pybadges."""
|
"""A setup module for pybadges."""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
@@ -19,6 +18,7 @@ import re
|
|||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
|
|
||||||
def get_long_description():
|
def get_long_description():
|
||||||
"""Transform README.md into a usable long description.
|
"""Transform README.md into a usable long description.
|
||||||
|
|
||||||
@@ -34,13 +34,12 @@ def get_long_description():
|
|||||||
'%s?sanitize=true)' % svg_path)
|
'%s?sanitize=true)' % svg_path)
|
||||||
|
|
||||||
return re.sub(r'\(tests/golden-images/.*?\.svg\)',
|
return re.sub(r'\(tests/golden-images/.*?\.svg\)',
|
||||||
replace_relative_with_absolute,
|
replace_relative_with_absolute, read_me)
|
||||||
read_me)
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='pybadges',
|
name='pybadges',
|
||||||
version= '2.2.1', # Also change in version.py.
|
version='2.3.0', # Also change in version.py.
|
||||||
author='Brian Quinlan',
|
author='Brian Quinlan',
|
||||||
author_email='brian@sweetapp.com',
|
author_email='brian@sweetapp.com',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
@@ -57,13 +56,11 @@ setup(
|
|||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
],
|
],
|
||||||
description='A library and command-line tool for generating Github-style ' +
|
description='A library and command-line tool for generating Github-style ' +
|
||||||
'badges',
|
'badges',
|
||||||
keywords="github gh-badges badge shield status",
|
keywords="github gh-badges badge shield status",
|
||||||
package_data={
|
package_data={
|
||||||
'pybadges': [
|
'pybadges': [
|
||||||
'badge-template-full.svg',
|
'badge-template-full.svg', 'default-widths.json', 'py.typed'
|
||||||
'default-widths.json',
|
|
||||||
'py.typed'
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
long_description=get_long_description(),
|
long_description=get_long_description(),
|
||||||
@@ -72,8 +69,9 @@ setup(
|
|||||||
install_requires=['Jinja2>=2.9.0,<3', 'requests>=2.9.0,<3'],
|
install_requires=['Jinja2>=2.9.0,<3', 'requests>=2.9.0,<3'],
|
||||||
extras_require={
|
extras_require={
|
||||||
'pil-measurement': ['Pillow>=5,<6'],
|
'pil-measurement': ['Pillow>=5,<6'],
|
||||||
'dev': ['fonttools>=3.26', 'nox', 'Pillow>=5',
|
'dev': [
|
||||||
'pytest>=3.6', 'xmldiff>=2.4'],
|
'fonttools>=3.26', 'nox', 'Pillow>=5', 'pytest>=3.6', 'xmldiff>=2.4'
|
||||||
|
],
|
||||||
},
|
},
|
||||||
license='Apache-2.0',
|
license='Apache-2.0',
|
||||||
packages=["pybadges"],
|
packages=["pybadges"],
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Tests for PrecalculatedTextMeasurer."""
|
"""Tests for PrecalculatedTextMeasurer."""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
@@ -24,7 +23,10 @@ class TestPrecalculatedTextMeasurer(unittest.TestCase):
|
|||||||
def test_some_known_widths(self):
|
def test_some_known_widths(self):
|
||||||
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
||||||
default_character_width=5.1,
|
default_character_width=5.1,
|
||||||
char_to_width={'H': 1.2, 'l': 1.3},
|
char_to_width={
|
||||||
|
'H': 1.2,
|
||||||
|
'l': 1.3
|
||||||
|
},
|
||||||
pair_to_kern={})
|
pair_to_kern={})
|
||||||
|
|
||||||
text_width = measurer.text_width('Hello')
|
text_width = measurer.text_width('Hello')
|
||||||
@@ -32,32 +34,44 @@ class TestPrecalculatedTextMeasurer(unittest.TestCase):
|
|||||||
|
|
||||||
def test_kern_in_middle(self):
|
def test_kern_in_middle(self):
|
||||||
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
||||||
default_character_width=5, char_to_width={},
|
default_character_width=5,
|
||||||
pair_to_kern={'el': 3.3, 'll': 4.4, 'no': 5.5})
|
char_to_width={},
|
||||||
|
pair_to_kern={
|
||||||
|
'el': 3.3,
|
||||||
|
'll': 4.4,
|
||||||
|
'no': 5.5
|
||||||
|
})
|
||||||
|
|
||||||
text_width = measurer.text_width('Hello')
|
text_width = measurer.text_width('Hello')
|
||||||
self.assertAlmostEqual(text_width, 5 * 5 - 3.3 - 4.4)
|
self.assertAlmostEqual(text_width, 5 * 5 - 3.3 - 4.4)
|
||||||
|
|
||||||
def test_kern_at_start(self):
|
def test_kern_at_start(self):
|
||||||
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
||||||
default_character_width=5, char_to_width={},
|
default_character_width=5,
|
||||||
pair_to_kern={'He': 3.3, 'no': 4.4})
|
char_to_width={},
|
||||||
|
pair_to_kern={
|
||||||
|
'He': 3.3,
|
||||||
|
'no': 4.4
|
||||||
|
})
|
||||||
|
|
||||||
text_width = measurer.text_width('Hello')
|
text_width = measurer.text_width('Hello')
|
||||||
self.assertAlmostEqual(text_width, 5 * 5 - 3.3)
|
self.assertAlmostEqual(text_width, 5 * 5 - 3.3)
|
||||||
|
|
||||||
def test_kern_at_end(self):
|
def test_kern_at_end(self):
|
||||||
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
measurer = precalculated_text_measurer.PrecalculatedTextMeasurer(
|
||||||
default_character_width=5, char_to_width={},
|
default_character_width=5,
|
||||||
pair_to_kern={'lo': 3.3, 'no': 4.4})
|
char_to_width={},
|
||||||
|
pair_to_kern={
|
||||||
|
'lo': 3.3,
|
||||||
|
'no': 4.4
|
||||||
|
})
|
||||||
|
|
||||||
text_width = measurer.text_width('Hello')
|
text_width = measurer.text_width('Hello')
|
||||||
self.assertAlmostEqual(text_width, 5 * 5 - 3.3)
|
self.assertAlmostEqual(text_width, 5 * 5 - 3.3)
|
||||||
|
|
||||||
def test_default_usable(self):
|
def test_default_usable(self):
|
||||||
measurer = (
|
measurer = (
|
||||||
precalculated_text_measurer.PrecalculatedTextMeasurer
|
precalculated_text_measurer.PrecalculatedTextMeasurer.default())
|
||||||
.default())
|
|
||||||
measurer.text_width('This is a long string of text')
|
measurer.text_width('This is a long string of text')
|
||||||
|
|
||||||
|
|
||||||
|
@@ -11,7 +11,6 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
"""Tests for pybadges."""
|
"""Tests for pybadges."""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
@@ -42,7 +41,8 @@ class TestPybadgesBadge(unittest.TestCase):
|
|||||||
|
|
||||||
def test_whole_link_and_left_link(self):
|
def test_whole_link_and_left_link(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
pybadges.badge(left_text='foo', right_text='bar',
|
pybadges.badge(left_text='foo',
|
||||||
|
right_text='bar',
|
||||||
left_link='http://example.com/',
|
left_link='http://example.com/',
|
||||||
whole_link='http://example.com/')
|
whole_link='http://example.com/')
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@ class TestPybadgesBadge(unittest.TestCase):
|
|||||||
diff = xmldiff.main.diff_texts(golden_image, pybadge_image)
|
diff = xmldiff.main.diff_texts(golden_image, pybadge_image)
|
||||||
self.assertFalse(diff)
|
self.assertFalse(diff)
|
||||||
|
|
||||||
|
|
||||||
class TestEmbedImage(unittest.TestCase):
|
class TestEmbedImage(unittest.TestCase):
|
||||||
"""Tests for pybadges._embed_image."""
|
"""Tests for pybadges._embed_image."""
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user