[Python-modules-commits] [python-slugify] 01/03: Import python-slugify_1.2.0.orig.tar.gz
Hugo Lefeuvre
hle at moszumanska.debian.org
Tue Jun 21 18:37:03 UTC 2016
This is an automated email from the git hooks/post-receive script.
hle pushed a commit to branch master
in repository python-slugify.
commit 3fcb1943b88da4690a3d7eda4380007725437a0e
Author: Hugo Lefeuvre <hle at debian.org>
Date: Tue Jun 21 20:29:07 2016 +0200
Import python-slugify_1.2.0.orig.tar.gz
---
.gitignore | 57 ++++++++++++++++
.travis.yml | 25 +++++++
CHANGELOG.md | 125 +++++++++++++++++++++++++++++++++++
LICENSE.md | 28 ++++++++
README.md | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++
pep8.sh | 14 ++++
requirements.txt | 1 +
setup.py | 88 +++++++++++++++++++++++++
slugify/__init__.py | 6 ++
slugify/slugify.py | 160 +++++++++++++++++++++++++++++++++++++++++++++
test.py | 171 ++++++++++++++++++++++++++++++++++++++++++++++++
11 files changed, 858 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ba74660
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,57 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..863cc24
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,25 @@
+sudo: false
+language: python
+
+python:
+ - "2.6"
+ - "2.7"
+ - "3.3"
+ - "3.4"
+ - pypy
+
+install:
+ - pip install -q -r requirements.txt --use-mirrors
+ - pip install -e .
+ - pip install pep8
+ - pip install coveralls
+ - pip install https://github.com/un33k/pyflakes/tarball/master
+
+before_script:
+ - "pep8 --exclude=migrations --ignore=E501,E225,E128 ."
+ - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pyflakes -x W slugify; fi
+
+script: coverage run --source=slugify test.py
+
+after_success:
+ coveralls
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..af16f3d
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,125 @@
+## 1.2.0
+
+Backward incompatible change: (@fabiocaccamo)
+
+ - In version < 1.2.0 all single quotes ( ' ) were removed, and
+ moving forward, >= 1.2.0, they will be replaced with ( - ).
+ Example:
+ < 1.2.0 -- ('C\'est déjà l\'été.' -> "cest-deja-lete")
+ >= 1.2.0 -- ('C\'est déjà l\'été.' -> "c-est-deja-l-ete")
+
+## 1.1.4
+
+Bugfix:
+
+ - Add more test cases, dropped `official` support for python 3.2
+
+
+## 1.1.3
+
+Bugfix:
+
+ - Handle unichar in python 3.x
+
+
+## 1.1.2
+
+Enhancement:
+
+ - Ability to remove `stopwords` from string
+
+
+## 1.0.2
+
+Enhancement:
+
+ - A new PyPI release
+
+
+## 1.0.1
+
+Enhancement:
+
+ - Promoting to production grade
+
+
+## 0.1.1
+
+Enhancement:
+
+ - Added option to save word order
+ - Removed 2to3 dependency
+ - Added more tests
+
+
+## 0.1.0
+
+Enhancement:
+
+ - Added more test
+ - Added test for python 3.4
+
+
+## 0.0.9
+
+Enhancement:
+
+ - Enable console_scripts
+
+
+## 0.0.8
+
+Enhancement:
+
+ - Move logic out of __init__.py
+ - Added console_scripts (@ekamil)
+ - Updated pep8.sh
+ - Added pypy support
+
+
+## 0.0.7
+
+Enhancement:
+
+ - Handle encoding in setup file
+ - Update ReadME, ChangeLog, License files
+
+
+## 0.0.6
+
+Enhancement:
+
+ - Update for smart_truncate
+
+
+## 0.0.5
+
+Features:
+
+ - Added Python 3.2 and 3.3 support (work by: arthurdarcet at github)
+
+
+## 0.0.4
+
+Features:
+
+ - Added option to choose non-dash separators (request by: danilodimoia at github)
+
+
+## 0.0.3
+
+Features:
+
+ - Added the ability to truncate slugs (request by: juanriaza at github)
+
+
+## 0.0.2
+
+Enhancement:
+
+ - Incremental update
+
+
+## 0.0.1
+
+ - Initial version
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..f48fab2
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,28 @@
+Copyright © Val Neekman ([Neekware Inc.](http://neekware.com)) [ info at neekware.com, [@vneekman](https://twitter.com/vneekman) ]
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of this project nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fb4ca24
--- /dev/null
+++ b/README.md
@@ -0,0 +1,183 @@
+Python Slugify
+===============
+
+**A Python slugify application that handles unicode**
+
+[![status-image]][status-link]
+[![version-image]][version-link]
+[![coverage-image]][coverage-link]
+[![download-image]][download-link]
+
+
+Overview
+========
+
+A Python **slugify** application that handles **unicode**.
+
+
+How to install
+==============
+
+ 1. easy_install python-slugify
+ 2. pip install python-slugify
+ 3. git clone http://github.com/un33k/python-slugify
+ a. cd python-slugify
+ b. run python setup.py
+ 4. wget https://github.com/un33k/python-slugify/zipball/master
+ a. unzip the downloaded file
+ b. cd into python-slugify-* directory
+ c. run python setup.py
+
+
+How to use
+===========
+
+ ```python
+ from slugify import slugify
+
+ 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 = "___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")
+
+ txt = 'Nín hǎo. Wǒ shì zhōng guó rén'
+ r = slugify(txt)
+ self.assertEqual(r, "nin-hao-wo-shi-zhong-guo-ren")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ txt = 'Компьютер'
+ r = slugify(txt)
+ self.assertEqual(r, "kompiuter")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=9)
+ self.assertEqual(r, "jaja-lol")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=15)
+ self.assertEqual(r, "jaja-lol-mememe")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=50)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=15, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-a")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=17, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=18, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=19, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=20, word_boundary=True, separator=".")
+ self.assertEqual(r, "jaja.lol.mememeoo.a")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=20, word_boundary=True, separator="ZZZZZZ")
+ self.assertEqual(r, "jajaZZZZZZlolZZZZZZmememeooZZZZZZa")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=13, word_boundary=True, save_order=True)
+ self.assertEqual(r, "one-two-three")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=13, word_boundary=True, save_order=False)
+ self.assertEqual(r, "one-two-three")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=12, word_boundary=True, save_order=False)
+ self.assertEqual(r, "one-two-four")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=12, word_boundary=True, save_order=True)
+ self.assertEqual(r, "one-two")
+
+ txt = 'this has a stopword'
+ r = slugify(txt, stopwords=['stopword'])
+ self.assertEqual(r, 'this-has-a')
+
+ txt = 'the quick brown fox jumps over the lazy dog'
+ r = slugify(txt, stopwords=['the'])
+ self.assertEqual(r, 'quick-brown-fox-jumps-over-lazy-dog')
+
+ txt = 'Foo A FOO B foo C'
+ r = slugify(txt, stopwords=['foo'])
+ self.assertEqual(r, 'a-b-c')
+
+ txt = 'Foo A FOO B foo C'
+ r = slugify(txt, stopwords=['FOO'])
+ self.assertEqual(r, 'a-b-c')
+
+ txt = 'the quick brown fox jumps over the lazy dog in a hurry'
+ r = slugify(txt, stopwords=['the', 'in', 'a', 'hurry'])
+ self.assertEqual(r, 'quick-brown-fox-jumps-over-lazy-dog')
+
+ txt = 'foo & bar'
+ r = slugify(txt)
+ self.assertEqual(r, 'foo-bar')
+ ```
+
+Running the tests
+=================
+
+To run the tests against the current environment:
+
+ python test.py
+
+
+License
+====================
+
+Released under a ([BSD](LICENSE.md)) license.
+
+
+Version
+====================
+X.Y.Z Version
+
+ `MAJOR` version -- when you make incompatible API changes,
+ `MINOR` version -- when you add functionality in a backwards-compatible manner, and
+ `PATCH` version -- when you make backwards-compatible bug fixes.
+
+[status-image]: https://secure.travis-ci.org/un33k/python-slugify.png?branch=master
+[status-link]: http://travis-ci.org/un33k/python-slugify?branch=master
+
+[version-image]: https://img.shields.io/pypi/v/python-slugify.svg
+[version-link]: https://pypi.python.org/pypi/python-slugify
+
+[coverage-image]: https://coveralls.io/repos/un33k/python-slugify/badge.svg
+[coverage-link]: https://coveralls.io/r/un33k/python-slugify
+
+[download-image]: https://img.shields.io/pypi/dm/python-slugify.svg
+[download-link]: https://pypi.python.org/pypi/python-slugify
diff --git a/pep8.sh b/pep8.sh
new file mode 100755
index 0000000..f48f800
--- /dev/null
+++ b/pep8.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+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 --ignore=E128,E225,E501 slugify test.py setup.py
+
+echo -e "Done.\n"
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..656daab
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+Unidecode>=0.04.16
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..46e7d68
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+# -*- coding: utf-8 -*-
+from setuptools import setup
+import re
+import os
+import sys
+import codecs
+
+
+name = 'python-slugify'
+package = 'slugify'
+description = 'A Python Slugify application that handles Unicode'
+url = 'https://github.com/un33k/python-slugify'
+author = 'Val Neekman'
+author_email = 'info at neekware.com'
+license = 'BSD'
+install_requires = ['Unidecode>=0.04.16']
+classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: BSD License',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: 3.4',
+]
+
+
+def get_version(package):
+ """
+ Return package version as listed in `__version__` in `init.py`.
+ """
+ init_py = codecs.open(os.path.join(package, '__init__.py'), encoding='utf-8').read()
+ return re.search("^__version__ = ['\"]([^'\"]+)['\"]", init_py, re.MULTILINE).group(1)
+
+
+def get_packages(package):
+ """
+ Return root package and all sub-packages.
+ """
+ return [dirpath
+ for dirpath, dirnames, filenames in os.walk(package)
+ if os.path.exists(os.path.join(dirpath, '__init__.py'))]
+
+
+def get_package_data(package):
+ """
+ Return all files under the root package, that are not in a
+ package themselves.
+ """
+ walk = [(dirpath.replace(package + os.sep, '', 1), filenames)
+ for dirpath, dirnames, filenames in os.walk(package)
+ if not os.path.exists(os.path.join(dirpath, '__init__.py'))]
+
+ filepaths = []
+ for base, filenames in walk:
+ filepaths.extend([os.path.join(base, filename)
+ for filename in filenames])
+ return {package: filepaths}
+
+
+if sys.argv[-1] == 'publish':
+ os.system("python setup.py sdist upload")
+ args = {'version': get_version(package)}
+ print("You probably want to also tag the version now:")
+ print(" git tag -a %(version)s -m 'version %(version)s' && git push --tags" % args)
+ sys.exit()
+
+
+setup(
+ name=name,
+ version=get_version(package),
+ url=url,
+ license=license,
+ description=description,
+ author=author,
+ author_email=author_email,
+ packages=get_packages(package),
+ package_data=get_package_data(package),
+ install_requires=install_requires,
+ classifiers=classifiers,
+ entry_points={'console_scripts': ['slugify=slugify.slugify:main']},
+)
diff --git a/slugify/__init__.py b/slugify/__init__.py
new file mode 100644
index 0000000..8b20b5f
--- /dev/null
+++ b/slugify/__init__.py
@@ -0,0 +1,6 @@
+from .slugify import *
+
+
+__author__ = 'Val Neekman @ Neekware Inc. [@vneekman]'
+__description__ = 'A Python slugify application that also handles Unicode'
+__version__ = '1.2.0'
diff --git a/slugify/slugify.py b/slugify/slugify.py
new file mode 100644
index 0000000..113afdd
--- /dev/null
+++ b/slugify/slugify.py
@@ -0,0 +1,160 @@
+import re
+import unicodedata
+import types
+import sys
+
+try:
+ from htmlentitydefs import name2codepoint
+ _unicode = unicode
+ _unicode_type = types.UnicodeType
+except ImportError:
+ from html.entities import name2codepoint
+ _unicode = str
+ _unicode_type = str
+ unichr = chr
+
+import unidecode
+
+
+__all__ = ['slugify']
+
+
+CHAR_ENTITY_PATTERN = re.compile('&(%s);' % '|'.join(name2codepoint))
+DECIMAL_PATTERN = re.compile('&#(\d+);')
+HEX_PATTERN = re.compile('&#x([\da-fA-F]+);')
+QUOTE_PATTERN = re.compile(r'[\']+')
+ALLOWED_CHARS_PATTERN = re.compile(r'[^-a-z0-9]+')
+DUPLICATE_DASH_PATTERN = re.compile('-{2,}')
+NUMBERS_PATTERN = re.compile('(?<=\d),(?=\d)')
+
+
+def smart_truncate(string, max_length=0, word_boundaries=False, separator=' ', save_order=False):
+ """
+ Truncate a string.
+ :param string (str): string for modification
+ :param max_length (int): output string length
+ :param word_boundaries (bool):
+ :param save_order (bool): if True then word order of output string is like input string
+ :param separator (str): separator between words
+ :return:
+ """
+
+ 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)
+ if next_len < max_length:
+ truncated += '{0}{1}'.format(word, separator)
+ elif next_len == max_length:
+ truncated += '{0}'.format(word)
+ break
+ else:
+ if save_order:
+ break
+ 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='-', save_order=False, stopwords=()):
+ """
+ Make a slug from the given text.
+ :param text (str): initial text
+ :param entities (bool):
+ :param decimal (bool):
+ :param hexadecimal (bool):
+ :param max_length (int): output string length
+ :param word_boundary (bool):
+ :param save_order (bool): if parameter is True and max_length > 0 return whole words in the initial order
+ :param separator (str): separator between words
+ :param stopwords (iterable): words to discount
+ :return (str):
+ """
+
+ # ensure text is unicode
+ if not isinstance(text, _unicode_type):
+ text = _unicode(text, 'utf-8', 'ignore')
+
+ # replace quotes with dashes - pre-process
+ text = QUOTE_PATTERN.sub('-', text)
+
+ # decode unicode
+ text = unidecode.unidecode(text)
+
+ # ensure text is still in unicode
+ if not isinstance(text, _unicode_type):
+ text = _unicode(text, 'utf-8', 'ignore')
+
+ # character entity reference
+ if entities:
+ text = CHAR_ENTITY_PATTERN.sub(lambda m: unichr(name2codepoint[m.group(1)]), text)
+
+ # decimal character reference
+ if decimal:
+ try:
+ text = DECIMAL_PATTERN.sub(lambda m: unichr(int(m.group(1))), text)
+ except:
+ pass
+
+ # hexadecimal character reference
+ if hexadecimal:
+ try:
+ text = HEX_PATTERN.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')
+
+ # make the text lowercase
+ text = text.lower()
+
+ # remove generated quotes -- post-process
+ text = QUOTE_PATTERN.sub('', text)
+
+ # replace unwanted characters
+ text = NUMBERS_PATTERN.sub('', text)
+ text = ALLOWED_CHARS_PATTERN.sub('-', text)
+
+ # remove redundant -
+ text = DUPLICATE_DASH_PATTERN.sub('-', text).strip('-')
+
+ # remove stopwords
+ if stopwords:
+ stopwords_lower = [s.lower() for s in stopwords]
+ words = [w for w in text.split('-') if w not in stopwords_lower]
+ text = '-'.join(words)
+
+ # smart truncate if requested
+ if max_length > 0:
+ text = smart_truncate(text, max_length, word_boundary, '-', save_order)
+
+ if separator != '-':
+ text = text.replace('-', separator)
+
+ return text
+
+
+def main():
+ if len(sys.argv) < 2:
+ print("Usage %s TEXT TO SLUGIFY" % sys.argv[0])
+ else:
+ text = ' '.join(sys.argv[1:])
+ print(slugify(text))
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..5bad955
--- /dev/null
+++ b/test.py
@@ -0,0 +1,171 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+from slugify import slugify
+
+
+class TestSlugification(unittest.TestCase):
+
+ def test_extraneous_seperators(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 = "___This is a test___"
+ r = slugify(txt)
+ self.assertEqual(r, "this-is-a-test")
+
+ def test_non_word_characters(self):
+ txt = "This -- is a ## test ---"
+ r = slugify(txt)
+ self.assertEqual(r, "this-is-a-test")
+
+ def test_phonetic_conversion_of_eastern_scripts(self):
+ txt = '影師嗎'
+ r = slugify(txt)
+ self.assertEqual(r, "ying-shi-ma")
+
+ def test_accented_text(self):
+ txt = 'C\'est déjà l\'été.'
+ r = slugify(txt)
+ self.assertEqual(r, "c-est-deja-l-ete")
+
+ txt = 'Nín hǎo. Wǒ shì zhōng guó rén'
+ r = slugify(txt)
+ self.assertEqual(r, "nin-hao-wo-shi-zhong-guo-ren")
+
+ def test_accented_text_with_non_word_characters(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ def test_cyrillic_text(self):
+ txt = 'Компьютер'
+ r = slugify(txt)
+ self.assertEqual(r, "kompiuter")
+
+ def test_max_length(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=9)
+ self.assertEqual(r, "jaja-lol")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=15)
+ self.assertEqual(r, "jaja-lol-mememe")
+
+ def test_max_length_cutoff_not_required(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=50)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ def test_word_boundary(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=15, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-a")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=17, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=18, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo")
+
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=19, word_boundary=True)
+ self.assertEqual(r, "jaja-lol-mememeoo-a")
+
+ def test_custom_separator(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=20, word_boundary=True, separator=".")
+ self.assertEqual(r, "jaja.lol.mememeoo.a")
+
+ def test_multi_character_separator(self):
+ txt = 'jaja---lol-méméméoo--a'
+ r = slugify(txt, max_length=20, word_boundary=True, separator="ZZZZZZ")
+ self.assertEqual(r, "jajaZZZZZZlolZZZZZZmememeooZZZZZZa")
+
+ def test_save_order(self):
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=13, word_boundary=True, save_order=True)
+ self.assertEqual(r, "one-two-three")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=13, word_boundary=True, save_order=False)
+ self.assertEqual(r, "one-two-three")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=12, word_boundary=True, save_order=False)
+ self.assertEqual(r, "one-two-four")
+
+ txt = 'one two three four five'
+ r = slugify(txt, max_length=12, word_boundary=True, save_order=True)
+ self.assertEqual(r, "one-two")
+
+ def test_stopword_removal(self):
+ txt = 'this has a stopword'
+ r = slugify(txt, stopwords=['stopword'])
+ self.assertEqual(r, 'this-has-a')
+
+ def test_multiple_stopword_occurances(self):
+ txt = 'the quick brown fox jumps over the lazy dog'
+ r = slugify(txt, stopwords=['the'])
+ self.assertEqual(r, 'quick-brown-fox-jumps-over-lazy-dog')
+
+ def test_differently_cased_stopword_match(self):
+ txt = 'Foo A FOO B foo C'
+ r = slugify(txt, stopwords=['foo'])
+ self.assertEqual(r, 'a-b-c')
+
+ txt = 'Foo A FOO B foo C'
+ r = slugify(txt, stopwords=['FOO'])
+ self.assertEqual(r, 'a-b-c')
+
+ def test_multiple_stopwords(self):
+ txt = 'the quick brown fox jumps over the lazy dog in a hurry'
+ r = slugify(txt, stopwords=['the', 'in', 'a', 'hurry'])
+ self.assertEqual(r, 'quick-brown-fox-jumps-over-lazy-dog')
+
+ def test_stopwords_with_different_separator(self):
+ txt = 'the quick brown fox jumps over the lazy dog'
+ r = slugify(txt, stopwords=['the'], separator=' ')
+ self.assertEqual(r, 'quick brown fox jumps over lazy dog')
+
+ def test_html_entities(self):
+ txt = 'foo & bar'
+ r = slugify(txt)
+ self.assertEqual(r, 'foo-bar')
+
+ def test_starts_with_number(self):
+ txt = '10 amazing secrets'
+ r = slugify(txt)
+ self.assertEqual(r, '10-amazing-secrets')
+
+ def test_contains_numbers(self):
+ txt = 'buildings with 1000 windows'
+ r = slugify(txt)
+ self.assertEqual(r, 'buildings-with-1000-windows')
+
+ def test_ends_with_number(self):
+ txt = 'recipe number 3'
+ r = slugify(txt)
+ self.assertEqual(r, 'recipe-number-3')
+
+ def test_numbers_only(self):
+ txt = '404'
+ r = slugify(txt)
+ self.assertEqual(r, '404')
+
+ def test_numbers_and_symbols(self):
+ txt = '1,000 reasons you are #1'
+ r = slugify(txt)
+ self.assertEqual(r, '1000-reasons-you-are-1')
+
+
+if __name__ == '__main__':
+ unittest.main()
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-slugify.git
More information about the Python-modules-commits
mailing list