We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Migration failing on version slugs
Running migrations on #1396, I hit the following error:

```
Traceback (most recent call last):
  File "/home/docs/bin/django-admin.py", line 5, in <module>
    management.execute_from_command_line()
  File "/home/docs/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 399, in execute_from_command_li
ne
    utility.execute()
  File "/home/docs/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/docs/local/lib/python2.7/site-packages/django/core/management/base.py", line 242, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/home/docs/local/lib/python2.7/site-packages/django/core/management/base.py", line 285, in execute
    output = self.handle(*args, **options)
  File "/home/docs/local/lib/python2.7/site-packages/south/management/commands/migrate.py", line 111, in handle
    ignore_ghosts = ignore_ghosts,
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/__init__.py", line 220, in migrate_app
    success = migrator.migrate_many(target, workplan, database)
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 256, in migrate_many
    result = migrator.__class__.migrate_many(migrator, target, migrations, database)
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 331, in migrate_many
    result = self.migrate(migration, database)
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 133, in migrate
    result = self.run(migration, database)
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 114, in run
    return self.run_migration(migration, database)
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 84, in run_migration
    migration_function()
  File "/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py", line 60, in <lambda>
    return (lambda: direction(orm))
  File "/home/docs/checkouts/readthedocs.org/readthedocs/builds/migrations/0024_fix_slugs_with_leading_placeholders.py", line
21, in forwards
    version.slug = slug_field.create_slug(version)
  File "/home/docs/checkouts/readthedocs.org/readthedocs/builds/version_slug.py", line 145, in create_slug
    'Invalid generated slug: {slug}'.format(slug=slug))
AssertionError: Invalid generated slug: v
```

cc @gregmuellegger 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `readthedocs/builds/version_slug.py`
Content:
```
1 """Contains logic for handling version slugs.
2 
3 Handling slugs for versions is not too straightforward. We need to allow some
4 characters which are uncommon in usual slugs. They are dots and underscores.
5 Usually we want the slug to be the name of the tag or branch corresponding VCS
6 version. However we need to strip url-destroying characters like slashes.
7 
8 So the syntax for version slugs should be:
9 
10 * Start with a lowercase ascii char or a digit.
11 * All other characters must be lowercase ascii chars, digits or dots.
12 
13 If uniqueness is not met for a slug in a project, we append a dash and a letter
14 starting with ``a``. We keep increasing that letter until we have a unique
15 slug. This is used since using numbers in tags is too common and appending
16 another number would be confusing.
17 """
18 
19 import math
20 import re
21 import string
22 from operator import truediv
23 from django.db import models
24 from django.utils.encoding import force_text
25 
26 
27 # Regex breakdown:
28 #   [a-z0-9] -- start with alphanumeric value
29 #   [-._a-z0-9] -- allow dash, dot, underscore, digit, lowercase ascii
30 #   +? -- allow multiple of those, but be not greedy about the matching
31 #   (?: ... ) -- wrap everything so that the pattern cannot escape when used in
32 #                regexes.
33 VERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]+?)'
34 
35 
36 class VersionSlugField(models.CharField):
37     """
38     Implementation inspired by ``django_extensions.db.fields.AutoSlugField``.
39     """
40 
41     invalid_chars_re = re.compile('[^-._a-z0-9]')
42     leading_punctuation_re = re.compile('^[-._]+')
43     placeholder = '-'
44     fallback_slug = 'unknown'
45     test_pattern = re.compile('^{pattern}$'.format(pattern=VERSION_SLUG_REGEX))
46 
47     def __init__(self, *args, **kwargs):
48         kwargs.setdefault('db_index', True)
49 
50         populate_from = kwargs.pop('populate_from', None)
51         if populate_from is None:
52             raise ValueError("missing 'populate_from' argument")
53         else:
54             self._populate_from = populate_from
55         super(VersionSlugField, self).__init__(*args, **kwargs)
56 
57     def get_queryset(self, model_cls, slug_field):
58         for field, model in model_cls._meta.get_fields_with_model():
59             if model and field == slug_field:
60                 return model._default_manager.all()
61         return model_cls._default_manager.all()
62 
63     def slugify(self, content):
64         if not content:
65             return ''
66 
67         slugified = content.lower()
68         slugified = self.invalid_chars_re.sub(self.placeholder, slugified)
69         slugified = self.leading_punctuation_re.sub('', slugified)
70 
71         if not slugified:
72             return self.fallback_slug
73         return slugified
74 
75     def uniquifying_suffix(self, iteration):
76         """
77         This creates a suffix based on the number given as ``iteration``. It
78         will return a value encoded as lowercase ascii letter. So we have an
79         alphabet of 26 letters. The returned suffix will be for example ``_yh``
80         where ``yh`` is the encoding of ``iteration``. The length of it will be
81         ``math.log(iteration, 26)``.
82 
83         Examples::
84 
85             uniquifying_suffix(0) == '_a'
86             uniquifying_suffix(25) == '_z'
87             uniquifying_suffix(26) == '_ba'
88             uniquifying_suffix(52) == '_ca'
89         """
90         alphabet = string.lowercase
91         length = len(alphabet)
92         if iteration == 0:
93             power = 0
94         else:
95             power = int(math.log(iteration, length))
96         current = iteration
97         suffix = ''
98         for exp in reversed(range(0, power + 1)):
99             digit = int(truediv(current, length ** exp))
100             suffix += alphabet[digit]
101             current = current % length ** exp
102         return '_{suffix}'.format(suffix=suffix)
103 
104     def create_slug(self, model_instance):
105         # get fields to populate from and slug field to set
106         slug_field = model_instance._meta.get_field(self.attname)
107 
108         slug = self.slugify(getattr(model_instance, self._populate_from))
109         next = 0
110 
111         # strip slug depending on max_length attribute of the slug field
112         # and clean-up
113         slug_len = slug_field.max_length
114         if slug_len:
115             slug = slug[:slug_len]
116         original_slug = slug
117 
118         # exclude the current model instance from the queryset used in finding
119         # the next valid slug
120         queryset = self.get_queryset(model_instance.__class__, slug_field)
121         if model_instance.pk:
122             queryset = queryset.exclude(pk=model_instance.pk)
123 
124         # form a kwarg dict used to impliment any unique_together contraints
125         kwargs = {}
126         for params in model_instance._meta.unique_together:
127             if self.attname in params:
128                 for param in params:
129                     kwargs[param] = getattr(model_instance, param, None)
130         kwargs[self.attname] = slug
131 
132         # increases the number while searching for the next valid slug
133         # depending on the given slug, clean-up
134         while not slug or queryset.filter(**kwargs):
135             slug = original_slug
136             end = self.uniquifying_suffix(next)
137             end_len = len(end)
138             if slug_len and len(slug) + end_len > slug_len:
139                 slug = slug[:slug_len - end_len]
140             slug = slug + end
141             kwargs[self.attname] = slug
142             next += 1
143 
144         assert self.test_pattern.match(slug), (
145             'Invalid generated slug: {slug}'.format(slug=slug))
146         return slug
147 
148     def pre_save(self, model_instance, add):
149         value = getattr(model_instance, self.attname)
150         # We only create a new slug if none was set yet.
151         if not value and add:
152             value = force_text(self.create_slug(model_instance))
153             setattr(model_instance, self.attname, value)
154         return value
155 
156     def south_field_triple(self):
157         "Returns a suitable description of this field for South."
158         from south.modelsinspector import introspector
159         field_class = '%s.VersionSlugField' % self.__module__
160         args, kwargs = introspector(self)
161         kwargs.update({
162             'populate_from': repr(self._populate_from),
163         })
164         return (field_class, args, kwargs)
165
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/readthedocs/builds/version_slug.py b/readthedocs/builds/version_slug.py
--- a/readthedocs/builds/version_slug.py
+++ b/readthedocs/builds/version_slug.py
@@ -27,10 +27,10 @@
 # Regex breakdown:
 #   [a-z0-9] -- start with alphanumeric value
 #   [-._a-z0-9] -- allow dash, dot, underscore, digit, lowercase ascii
-#   +? -- allow multiple of those, but be not greedy about the matching
+#   *? -- allow multiple of those, but be not greedy about the matching
 #   (?: ... ) -- wrap everything so that the pattern cannot escape when used in
 #                regexes.
-VERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]+?)'
+VERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]*?)'
 
 
 class VersionSlugField(models.CharField):

{"golden_diff": "diff --git a/readthedocs/builds/version_slug.py b/readthedocs/builds/version_slug.py\n--- a/readthedocs/builds/version_slug.py\n+++ b/readthedocs/builds/version_slug.py\n@@ -27,10 +27,10 @@\n # Regex breakdown:\n #   [a-z0-9] -- start with alphanumeric value\n #   [-._a-z0-9] -- allow dash, dot, underscore, digit, lowercase ascii\n-#   +? -- allow multiple of those, but be not greedy about the matching\n+#   *? -- allow multiple of those, but be not greedy about the matching\n #   (?: ... ) -- wrap everything so that the pattern cannot escape when used in\n #                regexes.\n-VERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]+?)'\n+VERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]*?)'\n \n \n class VersionSlugField(models.CharField):\n", "issue": "Migration failing on version slugs\nRunning migrations on #1396, I hit the following error:\n\n```\nTraceback (most recent call last):\n  File \"/home/docs/bin/django-admin.py\", line 5, in <module>\n    management.execute_from_command_line()\n  File \"/home/docs/local/lib/python2.7/site-packages/django/core/management/__init__.py\", line 399, in execute_from_command_li\nne\n    utility.execute()\n  File \"/home/docs/local/lib/python2.7/site-packages/django/core/management/__init__.py\", line 392, in execute\n    self.fetch_command(subcommand).run_from_argv(self.argv)\n  File \"/home/docs/local/lib/python2.7/site-packages/django/core/management/base.py\", line 242, in run_from_argv\n    self.execute(*args, **options.__dict__)\n  File \"/home/docs/local/lib/python2.7/site-packages/django/core/management/base.py\", line 285, in execute\n    output = self.handle(*args, **options)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/management/commands/migrate.py\", line 111, in handle\n    ignore_ghosts = ignore_ghosts,\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/__init__.py\", line 220, in migrate_app\n    success = migrator.migrate_many(target, workplan, database)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 256, in migrate_many\n    result = migrator.__class__.migrate_many(migrator, target, migrations, database)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 331, in migrate_many\n    result = self.migrate(migration, database)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 133, in migrate\n    result = self.run(migration, database)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 114, in run\n    return self.run_migration(migration, database)\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 84, in run_migration\n    migration_function()\n  File \"/home/docs/local/lib/python2.7/site-packages/south/migration/migrators.py\", line 60, in <lambda>\n    return (lambda: direction(orm))\n  File \"/home/docs/checkouts/readthedocs.org/readthedocs/builds/migrations/0024_fix_slugs_with_leading_placeholders.py\", line\n21, in forwards\n    version.slug = slug_field.create_slug(version)\n  File \"/home/docs/checkouts/readthedocs.org/readthedocs/builds/version_slug.py\", line 145, in create_slug\n    'Invalid generated slug: {slug}'.format(slug=slug))\nAssertionError: Invalid generated slug: v\n```\n\ncc @gregmuellegger \n\n", "before_files": [{"content": "\"\"\"Contains logic for handling version slugs.\n\nHandling slugs for versions is not too straightforward. We need to allow some\ncharacters which are uncommon in usual slugs. They are dots and underscores.\nUsually we want the slug to be the name of the tag or branch corresponding VCS\nversion. However we need to strip url-destroying characters like slashes.\n\nSo the syntax for version slugs should be:\n\n* Start with a lowercase ascii char or a digit.\n* All other characters must be lowercase ascii chars, digits or dots.\n\nIf uniqueness is not met for a slug in a project, we append a dash and a letter\nstarting with ``a``. We keep increasing that letter until we have a unique\nslug. This is used since using numbers in tags is too common and appending\nanother number would be confusing.\n\"\"\"\n\nimport math\nimport re\nimport string\nfrom operator import truediv\nfrom django.db import models\nfrom django.utils.encoding import force_text\n\n\n# Regex breakdown:\n#   [a-z0-9] -- start with alphanumeric value\n#   [-._a-z0-9] -- allow dash, dot, underscore, digit, lowercase ascii\n#   +? -- allow multiple of those, but be not greedy about the matching\n#   (?: ... ) -- wrap everything so that the pattern cannot escape when used in\n#                regexes.\nVERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]+?)'\n\n\nclass VersionSlugField(models.CharField):\n    \"\"\"\n    Implementation inspired by ``django_extensions.db.fields.AutoSlugField``.\n    \"\"\"\n\n    invalid_chars_re = re.compile('[^-._a-z0-9]')\n    leading_punctuation_re = re.compile('^[-._]+')\n    placeholder = '-'\n    fallback_slug = 'unknown'\n    test_pattern = re.compile('^{pattern}$'.format(pattern=VERSION_SLUG_REGEX))\n\n    def __init__(self, *args, **kwargs):\n        kwargs.setdefault('db_index', True)\n\n        populate_from = kwargs.pop('populate_from', None)\n        if populate_from is None:\n            raise ValueError(\"missing 'populate_from' argument\")\n        else:\n            self._populate_from = populate_from\n        super(VersionSlugField, self).__init__(*args, **kwargs)\n\n    def get_queryset(self, model_cls, slug_field):\n        for field, model in model_cls._meta.get_fields_with_model():\n            if model and field == slug_field:\n                return model._default_manager.all()\n        return model_cls._default_manager.all()\n\n    def slugify(self, content):\n        if not content:\n            return ''\n\n        slugified = content.lower()\n        slugified = self.invalid_chars_re.sub(self.placeholder, slugified)\n        slugified = self.leading_punctuation_re.sub('', slugified)\n\n        if not slugified:\n            return self.fallback_slug\n        return slugified\n\n    def uniquifying_suffix(self, iteration):\n        \"\"\"\n        This creates a suffix based on the number given as ``iteration``. It\n        will return a value encoded as lowercase ascii letter. So we have an\n        alphabet of 26 letters. The returned suffix will be for example ``_yh``\n        where ``yh`` is the encoding of ``iteration``. The length of it will be\n        ``math.log(iteration, 26)``.\n\n        Examples::\n\n            uniquifying_suffix(0) == '_a'\n            uniquifying_suffix(25) == '_z'\n            uniquifying_suffix(26) == '_ba'\n            uniquifying_suffix(52) == '_ca'\n        \"\"\"\n        alphabet = string.lowercase\n        length = len(alphabet)\n        if iteration == 0:\n            power = 0\n        else:\n            power = int(math.log(iteration, length))\n        current = iteration\n        suffix = ''\n        for exp in reversed(range(0, power + 1)):\n            digit = int(truediv(current, length ** exp))\n            suffix += alphabet[digit]\n            current = current % length ** exp\n        return '_{suffix}'.format(suffix=suffix)\n\n    def create_slug(self, model_instance):\n        # get fields to populate from and slug field to set\n        slug_field = model_instance._meta.get_field(self.attname)\n\n        slug = self.slugify(getattr(model_instance, self._populate_from))\n        next = 0\n\n        # strip slug depending on max_length attribute of the slug field\n        # and clean-up\n        slug_len = slug_field.max_length\n        if slug_len:\n            slug = slug[:slug_len]\n        original_slug = slug\n\n        # exclude the current model instance from the queryset used in finding\n        # the next valid slug\n        queryset = self.get_queryset(model_instance.__class__, slug_field)\n        if model_instance.pk:\n            queryset = queryset.exclude(pk=model_instance.pk)\n\n        # form a kwarg dict used to impliment any unique_together contraints\n        kwargs = {}\n        for params in model_instance._meta.unique_together:\n            if self.attname in params:\n                for param in params:\n                    kwargs[param] = getattr(model_instance, param, None)\n        kwargs[self.attname] = slug\n\n        # increases the number while searching for the next valid slug\n        # depending on the given slug, clean-up\n        while not slug or queryset.filter(**kwargs):\n            slug = original_slug\n            end = self.uniquifying_suffix(next)\n            end_len = len(end)\n            if slug_len and len(slug) + end_len > slug_len:\n                slug = slug[:slug_len - end_len]\n            slug = slug + end\n            kwargs[self.attname] = slug\n            next += 1\n\n        assert self.test_pattern.match(slug), (\n            'Invalid generated slug: {slug}'.format(slug=slug))\n        return slug\n\n    def pre_save(self, model_instance, add):\n        value = getattr(model_instance, self.attname)\n        # We only create a new slug if none was set yet.\n        if not value and add:\n            value = force_text(self.create_slug(model_instance))\n            setattr(model_instance, self.attname, value)\n        return value\n\n    def south_field_triple(self):\n        \"Returns a suitable description of this field for South.\"\n        from south.modelsinspector import introspector\n        field_class = '%s.VersionSlugField' % self.__module__\n        args, kwargs = introspector(self)\n        kwargs.update({\n            'populate_from': repr(self._populate_from),\n        })\n        return (field_class, args, kwargs)\n", "path": "readthedocs/builds/version_slug.py"}], "after_files": [{"content": "\"\"\"Contains logic for handling version slugs.\n\nHandling slugs for versions is not too straightforward. We need to allow some\ncharacters which are uncommon in usual slugs. They are dots and underscores.\nUsually we want the slug to be the name of the tag or branch corresponding VCS\nversion. However we need to strip url-destroying characters like slashes.\n\nSo the syntax for version slugs should be:\n\n* Start with a lowercase ascii char or a digit.\n* All other characters must be lowercase ascii chars, digits or dots.\n\nIf uniqueness is not met for a slug in a project, we append a dash and a letter\nstarting with ``a``. We keep increasing that letter until we have a unique\nslug. This is used since using numbers in tags is too common and appending\nanother number would be confusing.\n\"\"\"\n\nimport math\nimport re\nimport string\nfrom operator import truediv\nfrom django.db import models\nfrom django.utils.encoding import force_text\n\n\n# Regex breakdown:\n#   [a-z0-9] -- start with alphanumeric value\n#   [-._a-z0-9] -- allow dash, dot, underscore, digit, lowercase ascii\n#   *? -- allow multiple of those, but be not greedy about the matching\n#   (?: ... ) -- wrap everything so that the pattern cannot escape when used in\n#                regexes.\nVERSION_SLUG_REGEX = '(?:[a-z0-9][-._a-z0-9]*?)'\n\n\nclass VersionSlugField(models.CharField):\n    \"\"\"\n    Implementation inspired by ``django_extensions.db.fields.AutoSlugField``.\n    \"\"\"\n\n    invalid_chars_re = re.compile('[^-._a-z0-9]')\n    leading_punctuation_re = re.compile('^[-._]+')\n    placeholder = '-'\n    fallback_slug = 'unknown'\n    test_pattern = re.compile('^{pattern}$'.format(pattern=VERSION_SLUG_REGEX))\n\n    def __init__(self, *args, **kwargs):\n        kwargs.setdefault('db_index', True)\n\n        populate_from = kwargs.pop('populate_from', None)\n        if populate_from is None:\n            raise ValueError(\"missing 'populate_from' argument\")\n        else:\n            self._populate_from = populate_from\n        super(VersionSlugField, self).__init__(*args, **kwargs)\n\n    def get_queryset(self, model_cls, slug_field):\n        for field, model in model_cls._meta.get_fields_with_model():\n            if model and field == slug_field:\n                return model._default_manager.all()\n        return model_cls._default_manager.all()\n\n    def slugify(self, content):\n        if not content:\n            return ''\n\n        slugified = content.lower()\n        slugified = self.invalid_chars_re.sub(self.placeholder, slugified)\n        slugified = self.leading_punctuation_re.sub('', slugified)\n\n        if not slugified:\n            return self.fallback_slug\n        return slugified\n\n    def uniquifying_suffix(self, iteration):\n        \"\"\"\n        This creates a suffix based on the number given as ``iteration``. It\n        will return a value encoded as lowercase ascii letter. So we have an\n        alphabet of 26 letters. The returned suffix will be for example ``_yh``\n        where ``yh`` is the encoding of ``iteration``. The length of it will be\n        ``math.log(iteration, 26)``.\n\n        Examples::\n\n            uniquifying_suffix(0) == '_a'\n            uniquifying_suffix(25) == '_z'\n            uniquifying_suffix(26) == '_ba'\n            uniquifying_suffix(52) == '_ca'\n        \"\"\"\n        alphabet = string.lowercase\n        length = len(alphabet)\n        if iteration == 0:\n            power = 0\n        else:\n            power = int(math.log(iteration, length))\n        current = iteration\n        suffix = ''\n        for exp in reversed(range(0, power + 1)):\n            digit = int(truediv(current, length ** exp))\n            suffix += alphabet[digit]\n            current = current % length ** exp\n        return '_{suffix}'.format(suffix=suffix)\n\n    def create_slug(self, model_instance):\n        # get fields to populate from and slug field to set\n        slug_field = model_instance._meta.get_field(self.attname)\n\n        slug = self.slugify(getattr(model_instance, self._populate_from))\n        next = 0\n\n        # strip slug depending on max_length attribute of the slug field\n        # and clean-up\n        slug_len = slug_field.max_length\n        if slug_len:\n            slug = slug[:slug_len]\n        original_slug = slug\n\n        # exclude the current model instance from the queryset used in finding\n        # the next valid slug\n        queryset = self.get_queryset(model_instance.__class__, slug_field)\n        if model_instance.pk:\n            queryset = queryset.exclude(pk=model_instance.pk)\n\n        # form a kwarg dict used to impliment any unique_together contraints\n        kwargs = {}\n        for params in model_instance._meta.unique_together:\n            if self.attname in params:\n                for param in params:\n                    kwargs[param] = getattr(model_instance, param, None)\n        kwargs[self.attname] = slug\n\n        # increases the number while searching for the next valid slug\n        # depending on the given slug, clean-up\n        while not slug or queryset.filter(**kwargs):\n            slug = original_slug\n            end = self.uniquifying_suffix(next)\n            end_len = len(end)\n            if slug_len and len(slug) + end_len > slug_len:\n                slug = slug[:slug_len - end_len]\n            slug = slug + end\n            kwargs[self.attname] = slug\n            next += 1\n\n        assert self.test_pattern.match(slug), (\n            'Invalid generated slug: {slug}'.format(slug=slug))\n        return slug\n\n    def pre_save(self, model_instance, add):\n        value = getattr(model_instance, self.attname)\n        # We only create a new slug if none was set yet.\n        if not value and add:\n            value = force_text(self.create_slug(model_instance))\n            setattr(model_instance, self.attname, value)\n        return value\n\n    def south_field_triple(self):\n        \"Returns a suitable description of this field for South.\"\n        from south.modelsinspector import introspector\n        field_class = '%s.VersionSlugField' % self.__module__\n        args, kwargs = introspector(self)\n        kwargs.update({\n            'populate_from': repr(self._populate_from),\n        })\n        return (field_class, args, kwargs)\n", "path": "readthedocs/builds/version_slug.py"}]}