Skip to content

Commit

Permalink
Added Area() class for constructing the <area> tag; Closes #6
Browse files Browse the repository at this point in the history
  • Loading branch information
bharadwajyarlagadda committed Aug 21, 2016
1 parent 5dae2d6 commit 37a4273
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 1 deletion.
167 changes: 166 additions & 1 deletion korona/html/construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
anchor_tag,
abbr_tag,
acronym_tag,
area_tag,
bold_tag,
base_tag
)
Expand Down Expand Up @@ -98,7 +99,7 @@ def get_coords(self, shape, coords):
"""Returns coordinates after a series of validations.
Args:
shape (str): Shape of a link (Ex. rect/circle/poly)
shape (str): Shape of a link (Ex. rect/circle/poly/etc.)
coords (mixed): A list/tuple/str of coordinate values.
Returns:
Expand Down Expand Up @@ -143,6 +144,9 @@ def pre_validate(self, href, attribute_name, value):
'href attribute is set.'
.format(attribute_name))

if not isinstance(value, str):
raise ValueError('<a>: {0} should be a string'.format(value))

def validate_values(self, href, attribute_name, value):
"""Validates whether the given attribute value is a valid value or not.
Some of the attributes have confined values. Even if we give some
Expand Down Expand Up @@ -199,6 +203,167 @@ def construct_tag(self):
return acronym_tag.render(self.values)


class Area(object):
"""Class for constructing area tag.
Args:
alt (str): Specifies an alternate text for the area. Required if the
href attribute is present.
coords (mixed): Specifies the coordinates of the area.
download (str): Specifies that the target will be downloaded when a
user clicks on the hyper link.
href (str): Specifies the hyperlink target for the area.
hreflang (str): Specifies the language of the target URL.
media (str): Specifies what media/device the target URL is optimized
for.
nohref(bool): Specifies that an area has no associated link.
rel (str): Specifies the relationship between the current document
and the target URL.
shape (str): Specifies the shape of the area.
target(str): Specifies where to open the target URL.
type (str): Specifies the media type of the target URL.
"""
def __init__(self,
alt=None,
coords=None,
download=None,
href=None,
hreflang=None,
media=None,
nohref=False,
rel=None,
shape=None,
target=None,
type=None):
self.tag = 'area'
self.validate_alt(href=href, attribute_name='alt', value=alt)
coordinates = self.get_coords(shape=shape, coords=coords)
self.pre_validate(href=href, attribute_name='download', value=download)
self.validate_string(value=href)
self.pre_validate(href=href, attribute_name='hreflang', value=hreflang)
self.pre_validate(href=href, attribute_name='media', value=media)
self.validate_values(href=href, attribute_name='rel', value=rel)
self.validate_values(href=href, attribute_name='shape', value=shape)
self.pre_validate(href=href, attribute_name='targte', value=target)
self.pre_validate(href=href, attribute_name='type', value=type)
self.values = {'alt': alt,
'coords': coordinates,
'download': download,
'href': href,
'hreflang': hreflang,
'media': media,
'nohref': nohref,
'rel': rel,
'shape': shape,
'target': target,
'type': type}

def construct_tag(self):
"""Returns the constructed area tag <area></area>."""
return area_tag.render(self.values)

def validate_string(self, value):
"""Validates whether the given value is a string or not."""
if not value:
return

# If the attribute value is not a string raise a ValueError.
if not isinstance(value, str):
raise ValueError('<area>: {0} should be a string'.format(value))

def validate_alt(self, href, attribute_name, value):
"""Validates area's alt attribute."""
if href and not value:
raise AttributeError('<area>: {0} attribute is required if the '
'href attribute is present.'
.format(attribute_name))

if not href and value:
raise AttributeError('<area>: {0} attribute is only used when '
'href attribute is set.'
.format(attribute_name))

if value and not isinstance(value, str):
raise ValueError('<area>: {0} should be a string'.format(value))

def pre_validate(self, href, attribute_name, value):
"""Validates whether an attribute is dependant on another attribute or
not. Some of the attributes requires href attribute to be set.
"""
if not value:
return

if not href:
raise AttributeError('<area>: {0} attribute is only used when '
'href attribute is set.'
.format(attribute_name))

if not isinstance(value, str):
raise ValueError('<area>: {0} should be a string'.format(value))

def get_coords(self, shape, coords):
"""Returns coordinates after a series of validations.
Args:
shape (str): Shape of a link (Ex. rect/circle/poly/etc.)
coords (mixed): A list/tuple/str of coordinate values.
Returns:
str: A string of coordinate values.
"""
if not coords:
return

if (coords and not shape) or (shape and not coords):
raise AttributeError('<area>: shape attribute should be present '
'when coords are specified.')

if isinstance(coords, str):
coords = coords.split(',')

if isinstance(coords, dict):
raise ValueError('<area>: {0} should be either list/tuple/str not '
'a dictionary'
.format(coords))

if shape == 'rect' and len(coords) != RECTANGLE_SHAPE_COORDINATES:
raise ValueError('<area>: {0} coordinates should be given for '
'rectangle shape'
.format(RECTANGLE_SHAPE_COORDINATES))

if shape == 'circle' and len(coords) != CIRCLE_SHAPE_COORDINATES:
raise ValueError('<area>: {0} coordinates should be given for '
'circle shape'
.format(CIRCLE_SHAPE_COORDINATES))

return ','.join(str(coord) for coord in coords)

def validate_values(self, href, attribute_name, value):
"""Validates whether the given attribute value is a valid value or not.
Some of the attributes have confined values. Even if we give some
other value, the html output would not be correct.
"""
if not value:
return

if attribute_name == 'rel' and not href:
raise AttributeError('<area>: {attribute_name} is only used when '
'href attribute is set.'
.format(attribute_name=attribute_name))

if not isinstance(value, str):
raise ValueError('<area>: {0} should be a string value.'
.format(attribute_name))

attribute_values = TAG_ATTRIBUTES[self.tag][attribute_name]['values']

if value not in attribute_values:
raise AttributeError('<area>: {attribute_name} attribute values '
'should be one of these: {values}'
.format(attribute_name=attribute_name,
values=','.join(attribute_values)))


class B(object):
"""Class for constructing bold tag.
Expand Down
1 change: 1 addition & 0 deletions korona/templates/html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
anchor_tag,
abbr_tag,
acronym_tag,
area_tag,
bold_tag,
base_tag
)
14 changes: 14 additions & 0 deletions korona/templates/html/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@
<acronym>{% if text -%} {{ text }} {% endif -%}</acronym>
""")

area_tag = env.from_string("""
<area {% if shape %} shape="{{ shape }}" {% endif -%}
{% if coords %} coords="{{ coords }}" {% endif -%}
{% if href %} href="{{ href }}" {% endif -%}
{% if type %} type="{{ type }}" {% endif -%}
{% if hreflang %} hreflang="{{ hreflang }}" {% endif -%}
{% if alt %} alt="{{ alt }}" {% endif -%}
{% if media %} media="{{ media }}" {% endif -%}
{% if rel %} rel="{{ rel }}" {% endif -%}
{% if nohref %} nohref {% endif -%}
{% if download %} download="{{ download }}" {% endif -%}>
{% if target %} target="{{ target }}" {% endif -%}
""")

bold_tag = env.from_string("""
<b>{% if text -%} {{ text }} {% endif -%}</b>
""")
Expand Down
102 changes: 102 additions & 0 deletions tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
A,
Abbr,
Acronym,
Area,
B,
Base
)
from korona.templates.html import (
anchor_tag,
abbr_tag,
acronym_tag,
area_tag,
bold_tag,
base_tag
)
Expand Down Expand Up @@ -79,6 +81,8 @@ def test_construct_anchor_tag_coords(attributes):

@parametrize('attributes,exception,error_msg', [
({'rel': 1}, AttributeError, 'only used when href attribute is set.'),
({'type': 1}, AttributeError, 'only used when href attribute is set.'),
({'href': 'abc', 'type': 1}, ValueError, 'should be a string'),
({'charset': 1}, ValueError, 'should be a string'),
({'rel': 1, 'href': 'www.google.com'}, ValueError, 'should be a string'),
({'shape': 'circle', 'coords': [1, 2, 3, 4]},
Expand Down Expand Up @@ -144,6 +148,104 @@ def test_construct_acronym_tag(attributes):
assert acronym.construct_tag() == acronym_tag.render(attributes)


@parametrize('attributes', [
({'href': 'www.google.com', 'alt': 'abc'}),
({'href': 'www.google.com', 'alt': 'abc', 'rel': 'nofollow'}),
({'download': 'abc',
'href': 'www.google.com',
'hreflang': 'en',
'rel': 'nofollow',
'target': '_blank',
'type': 'text/html',
'alt': 'abc'}),
({'href': 'www.google.com', 'alt': 'abc'})
])
def test_construct_area_tag(attributes):
"""Test for validating whether the area tag is constructed correctly or
not.
"""
area = Area(**attributes)
assert area.construct_tag() == area_tag.render(attributes)


@parametrize('attributes', [
({'shape': 'rect', 'coords': [1, 2, 3, 4]}),
({'shape': 'circle', 'coords': [1, 2, 3]}),
({'shape': 'poly', 'coords': [1, 2, 3, 4, 5, 6]}),
({'shape': 'rect', 'coords': (1, 2, 3, 4)}),
({'shape': 'circle', 'coords': (1, 2, 3)}),
({'shape': 'poly', 'coords': (1, 2, 3, 4, 5, 6)}),
({'shape': 'rect', 'coords': '1,2,3,4'}),
({'shape': 'circle', 'coords': '1,2,3'}),
({'shape': 'poly', 'coords': '1,2,3,4,5,6'}),
])
def test_construct_area_tag_coords(attributes):
"""Test for validating the shape and coordinate attributes given."""
area = Area(**attributes)

if not isinstance(attributes['coords'], str):
attributes['coords'] = (','.join(str(coord)
for coord in attributes['coords']))

assert area.construct_tag() == area_tag.render(attributes)


@parametrize('attributes,exception,error_msg', [
({'rel': 1}, AttributeError, 'only used when href attribute is set.'),
({'rel': 1, 'href': 'www.google.com', 'alt': 'abc'},
ValueError,
'should be a string'),
({'shape': 'circle', 'coords': [1, 2, 3, 4]},
ValueError,
'coordinates should be given for circle shape'),
({'shape': 'rect', 'coords': [1, 2, 3, 4, 5]},
ValueError,
'coordinates should be given for rectangle shape'),
({'shape': 'circle', 'coords': [1, 2]},
ValueError,
'coordinates should be given for circle shape'),
({'shape': 'rect', 'coords': [1, 2, 3]},
ValueError,
'coordinates should be given for rectangle shape'),
({'shape': 'rect', 'coords': {'x': 1, 'y': 2}},
ValueError,
'should be either list/tuple/str not a dictionary'),
({'coords': [1, 2, 3]},
AttributeError,
'shape attribute should be present when coords are specified'),
({'download': 'abc'},
AttributeError,
'only used when href attribute is set.'),
({'href': 'abc', 'alt': 'abc', 'download': 123},
ValueError,
'should be a string'),
({'href': 123, 'alt': 'abc'},
ValueError,
'should be a string'),
({'href': 'www.google.com', 'alt': 'abc', 'rel': 'abc'},
AttributeError,
'attribute values should be one of these'),
({'shape': 'abc'},
AttributeError,
'attribute values should be one of these'),
({'alt': 'abc'},
AttributeError,
'attribute is only used when href attribute is set.'),
({'href': 'abc'},
AttributeError,
'attribute is required if the href attribute is present'),
({'href': 'www.google.com', 'alt': 123},
ValueError,
'should be a string')
])
def test_construct_area_tag_error(attributes, exception, error_msg):
"""Test for validating area tag's attributes."""
with pytest.raises(exception) as exc:
Area(**attributes)

assert error_msg in str(exc)


@parametrize('attributes', [
({'text': 'abc'}),
({'text': None})
Expand Down

0 comments on commit 37a4273

Please sign in to comment.