def generate_tag(key, value=None):
<EOL>if not isinstance(key, six.string_types):<EOL><INDENT>raise ValueError('<STR_LIT>' % key)<EOL><DEDENT>if not isinstance(value, six.string_types + (NONE_TYPE,)):<EOL><INDENT>raise ValueError('<STR_LIT>' % value)<EOL><DEDENT>key = BAD_TAG_CHAR_REGEXP.sub('<STR_LIT:_>', key).strip()<EOL>if value is None or not value.strip():<EOL><INDENT>tag = key<EOL><DEDENT>else:<EOL><INDENT>value = BAD_TAG_CHAR_REGEXP.sub('<STR_LIT:_>', value).strip()<EOL>tag = '<STR_LIT>' % (key, value)<EOL><DEDENT>if tag and not tag[<NUM_LIT:0>].isalpha():<EOL><INDENT>tag = '<STR_LIT:a>' + tag<EOL><DEDENT>tag = tag.lower()[:<NUM_LIT:200>]<EOL>if tag in ['<STR_LIT>', '<STR_LIT:host>', '<STR_LIT:source>']:<EOL><INDENT>tag = tag + '<STR_LIT:_>'<EOL><DEDENT>return tag<EOL>
Generate a tag for use with the tag backends.

    The key and value (if there is one) are sanitized according to the
    following rules:

    1. after the first character, all characters must be alphanumeric,
       underscore, minus, period, or slash--invalid characters are converted
       to "_"
    2. lowercase

    If a value is provided, the final tag is `key:value`.

    The final tag must start with a letter. If it doesn't, an "a" is prepended.

    The final tag is truncated to 200 characters.

    If the final tag is "device", "host", or "source", then a "_" will be
    appended the end.

    :arg str key: the key to use
    :arg str value: the value (if any)

    :returns: the final tag

    Examples:

    >>> generate_tag('yellow')
    'yellow'
    >>> generate_tag('rule', 'is_yellow')
    'rule:is_yellow'

    Example with ``incr``:

    >>> import markus
    >>> mymetrics = markus.get_metrics(__name__)

    >>> mymetrics.incr('somekey', value=1,
    ...                tags=[generate_tag('rule', 'is_yellow')])