Enforce yapf for lint.

This commit is contained in:
Brian Quinlan
2020-06-29 16:29:34 -07:00
parent ee438686b4
commit ede8329ff9
17 changed files with 148 additions and 125 deletions

6
.yapfignore Normal file
View File

@@ -0,0 +1,6 @@
# Virtual environments
venv
**/venv
# Automatically generated nox files
.nox

View File

@@ -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

View File

@@ -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)

View File

@@ -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')

View File

@@ -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(

View File

@@ -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,

View File

@@ -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.

View File

@@ -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__':

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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'

View File

@@ -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

2
setup.cfg Normal file
View File

@@ -0,0 +1,2 @@
[yapf]
based_on_style = google

View File

@@ -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"],

View File

@@ -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')

View File

@@ -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."""