diff options
author | Val Neekman <val@neekware.com> | 2014-08-16 22:02:32 -0400 |
---|---|---|
committer | Val Neekman <val@neekware.com> | 2014-08-16 22:02:32 -0400 |
commit | b86d17c3607aad237ace02710a6cae924c324116 (patch) | |
tree | 411918fa12c2e9e5070189e9c37a4885dc47736a | |
parent | 152827ae8f84e9b89db21bde18c052467bbaf293 (diff) | |
download | python-slugify-b86d17c3607aad237ace02710a6cae924c324116.tar.gz |
Added console, pypy and some reorg0.0.8
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | CHANGELOG.md | 12 | ||||
-rwxr-xr-x | pep8.sh | 15 | ||||
-rw-r--r-- | requirements.txt | 2 | ||||
-rwxr-xr-x | setup.py | 4 | ||||
-rw-r--r-- | slugify/__init__.py | 113 | ||||
-rw-r--r-- | slugify/slugify.py | 113 | ||||
-rw-r--r-- | test.py | 11 |
8 files changed, 150 insertions, 121 deletions
diff --git a/.travis.yml b/.travis.yml index c1c4d27..1566bd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "2.7" - "3.2" - "3.3" + - pypy install: - pip install -q -r requirements.txt --use-mirrors before_script: diff --git a/CHANGELOG.md b/CHANGELOG.md index 681de4f..f28bbb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,14 @@ +## 0.0.8 + +Enhancement: + + - Move logic out of __init__.py + - Added console_scripts (@ekamil) + - Updated pep8.sh + - Added pypy support + + ## 0.0.7 Enhancement: @@ -39,4 +49,4 @@ Features: Enhancement: - - A
\ No newline at end of file + - A @@ -1,5 +1,14 @@ #!/bin/bash -echo -e "\nRunning: (pep8 --show-source --show-pep8 --select=errors --testsuite=.)\n\n" -pep8 --show-source --show-pep8 --select=errors --testsuite=./ -echo -e "\n\n" +echo -e "\nRunning: pep8 ... \n" + +# Ignoring autogenerated files +# -- Migration directories +# Ignoring error codes +# -- E128 continuation line under-indented for visual indent +# -- E225 missing whitespace around operator +# -- E501 line too long + +pep8 --exclude=migrations --ignore=E128,E225,E501 slugify test.py setup.py + +echo -e "Done.\n" diff --git a/requirements.txt b/requirements.txt index d421466..656daab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -Unidecode>=0.04.12 +Unidecode>=0.04.16 @@ -10,12 +10,12 @@ import codecs name = 'python-slugify' package = 'slugify' -description = 'A Python slugify application that handles unicode' +description = 'A Python Slugify application that handles Unicode' url = 'https://github.com/un33k/python-slugify' author = 'Val Neekman' author_email = 'info@neekware.com' license = 'BSD' -install_requires = ['Unidecode>=0.04.12'] +install_requires = ['Unidecode>=0.04.16'] classifiers = [ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', diff --git a/slugify/__init__.py b/slugify/__init__.py index 0ff57f0..16dde8d 100644 --- a/slugify/__init__.py +++ b/slugify/__init__.py @@ -1,114 +1,5 @@ # -*- coding: utf-8 -*- -__version__ = '0.0.7' +__version__ = '0.0.8' -__all__ = ['slugify'] - -import re -import unicodedata -import types -import sys -from htmlentitydefs import name2codepoint -from unidecode import unidecode - -# character entity reference -CHAR_ENTITY_REXP = re.compile('&(%s);' % '|'.join(name2codepoint)) - -# decimal character reference -DECIMAL_REXP = re.compile('&#(\d+);') - -# hexadecimal character reference -HEX_REXP = re.compile('&#x([\da-fA-F]+);') - -REPLACE1_REXP = re.compile(r'[\']+') -REPLACE2_REXP = re.compile(r'[^-a-z0-9]+') -REMOVE_REXP = re.compile('-{2,}') - -def smart_truncate(string, max_length=0, word_boundaries=False, separator=' '): - """ Truncate a string """ - - string = string.strip(separator) - - if not max_length: - return string - - if len(string) < max_length: - return string - - if not word_boundaries: - return string[:max_length].strip(separator) - - if separator not in string: - return string[:max_length] - - truncated = '' - for word in string.split(separator): - if word: - next_len = len(truncated) + len(word) + len(separator) - if next_len <= max_length: - truncated += '{0}{1}'.format(word, separator) - if not truncated: - truncated = string[:max_length] - return truncated.strip(separator) - - -def slugify(text, entities=True, decimal=True, hexadecimal=True, max_length=0, word_boundary=False, separator='-'): - """ Make a slug from the given text """ - - # text to unicode - if type(text) != types.UnicodeType: - text = unicode(text, 'utf-8', 'ignore') - - # decode unicode ( 影師嗎 = Ying Shi Ma) - text = unidecode(text) - - # text back to unicode - if type(text) != types.UnicodeType: - text = unicode(text, 'utf-8', 'ignore') - - # character entity reference - if entities: - text = CHAR_ENTITY_REXP.sub(lambda m: unichr(name2codepoint[m.group(1)]), text) - - # decimal character reference - if decimal: - try: - text = DECIMAL_REXP.sub(lambda m: unichr(int(m.group(1))), text) - except: - pass - - # hexadecimal character reference - if hexadecimal: - try: - text = HEX_REXP.sub(lambda m: unichr(int(m.group(1), 16)), text) - except: - pass - - # translate - text = unicodedata.normalize('NFKD', text) - if sys.version_info < (3,): - text = text.encode('ascii', 'ignore') - - # replace unwanted characters - text = REPLACE1_REXP.sub('', text.lower()) # replace ' with nothing instead with - - text = REPLACE2_REXP.sub('-', text.lower()) - - # remove redundant - - text = REMOVE_REXP.sub('-', text).strip('-') - - # smart truncate if requested - if max_length > 0: - text = smart_truncate(text, max_length, word_boundary, '-') - - if separator != '-': - text = text.replace('-', separator) - - return text - - -def main(): - if len(sys.argv) < 2: - print "Usage %s TEXT TO SLUGIFY" % sys.argv[0] - return - text = ' '.join(sys.argv[1:]) - print slugify(text) +from slugify import * diff --git a/slugify/slugify.py b/slugify/slugify.py new file mode 100644 index 0000000..ba15274 --- /dev/null +++ b/slugify/slugify.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- + +__all__ = ['slugify'] + +import re +import unicodedata +import types +import sys +from htmlentitydefs import name2codepoint +from unidecode import unidecode + +# character entity reference +CHAR_ENTITY_REXP = re.compile('&(%s);' % '|'.join(name2codepoint)) + +# decimal character reference +DECIMAL_REXP = re.compile('&#(\d+);') + +# hexadecimal character reference +HEX_REXP = re.compile('&#x([\da-fA-F]+);') + +REPLACE1_REXP = re.compile(r'[\']+') +REPLACE2_REXP = re.compile(r'[^-a-z0-9]+') +REMOVE_REXP = re.compile('-{2,}') + + +def smart_truncate(string, max_length=0, word_boundaries=False, separator=' '): + """ Truncate a string """ + + string = string.strip(separator) + + if not max_length: + return string + + if len(string) < max_length: + return string + + if not word_boundaries: + return string[:max_length].strip(separator) + + if separator not in string: + return string[:max_length] + + truncated = '' + for word in string.split(separator): + if word: + next_len = len(truncated) + len(word) + len(separator) + if next_len <= max_length: + truncated += '{0}{1}'.format(word, separator) + if not truncated: + truncated = string[:max_length] + return truncated.strip(separator) + + +def slugify(text, entities=True, decimal=True, hexadecimal=True, max_length=0, word_boundary=False, separator='-'): + """ Make a slug from the given text """ + + # text to unicode + if not isinstance(text, types.UnicodeType): + text = unicode(text, 'utf-8', 'ignore') + + # decode unicode ( 影師嗎 = Ying Shi Ma) + text = unidecode(text) + + # text back to unicode + if not isinstance(text, types.UnicodeType): + text = unicode(text, 'utf-8', 'ignore') + + # character entity reference + if entities: + text = CHAR_ENTITY_REXP.sub(lambda m: unichr(name2codepoint[m.group(1)]), text) + + # decimal character reference + if decimal: + try: + text = DECIMAL_REXP.sub(lambda m: unichr(int(m.group(1))), text) + except: + pass + + # hexadecimal character reference + if hexadecimal: + try: + text = HEX_REXP.sub(lambda m: unichr(int(m.group(1), 16)), text) + except: + pass + + # translate + text = unicodedata.normalize('NFKD', text) + if sys.version_info < (3,): + text = text.encode('ascii', 'ignore') + + # replace unwanted characters + text = REPLACE1_REXP.sub('', text.lower()) # replace ' with nothing instead with - + text = REPLACE2_REXP.sub('-', text.lower()) + + # remove redundant - + text = REMOVE_REXP.sub('-', text).strip('-') + + # smart truncate if requested + if max_length > 0: + text = smart_truncate(text, max_length, word_boundary, '-') + + if separator != '-': + text = text.replace('-', separator) + + return text + + +def main(): + if len(sys.argv) < 2: + print "Usage %s TEXT TO SLUGIFY" % sys.argv[0] + return + text = ' '.join(sys.argv[1:]) + print slugify(text) @@ -3,18 +3,23 @@ import unittest from slugify import slugify + class TestSequenceFunctions(unittest.TestCase): def test_manager(self): - + txt = "This is a test ---" r = slugify(txt) self.assertEqual(r, "this-is-a-test") - + txt = "This -- is a ## test ---" r = slugify(txt) self.assertEqual(r, "this-is-a-test") - + + txt = '影師嗎' + r = slugify(txt) + self.assertEqual(r, "ying-shi-ma") + txt = 'C\'est déjà l\'été.' r = slugify(txt) self.assertEqual(r, "cest-deja-lete") |