We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
test_docs_for_ad randomly spuriously fails
We occasionally see this failure:
 ======================================================================
FAIL: test_docs_for_ad (ietf.doc.tests.SearchTests.test_docs_for_ad)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/__w/datatracker/datatracker/ietf/doc/tests.py", line 301, in test_docs_for_ad
    self.assertEqual(r.status_code, 200)
AssertionError: 404 != 200

It's clearly a test-harness randomly generated data data mismatch with the view being tested. Investigation is needed to see if this is a real (but obscure corner) bug, or just insufficient constraints on the generated data issue. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ietf/person/factories.py`
Content:
```
1 # Copyright The IETF Trust 2015-2020, All Rights Reserved
2 # -*- coding: utf-8 -*-
3 
4 
5 import factory
6 from factory.fuzzy import FuzzyChoice
7 import faker 
8 import faker.config
9 import os
10 import random
11 import shutil
12 
13 from unidecode import unidecode
14 
15 from django.conf import settings
16 from django.contrib.auth.models import User
17 from django.utils.text import slugify
18 from django.utils.encoding import force_text
19 
20 import debug                            # pyflakes:ignore
21 
22 from ietf.person.models import Person, Alias, Email, PersonalApiKey, PersonApiKeyEvent, PERSON_API_KEY_ENDPOINTS
23 from ietf.person.name import normalize_name, unidecode_name
24 
25 
26 fake = faker.Factory.create()
27 
28 def setup():
29     global acceptable_fakers
30     # The transliteration of some arabic and devanagari names introduces
31     # non-alphabetic characgters that don't work with the draft author
32     # extraction code, and also don't seem to match the way people with arabic
33     # names romanize arabic names.  Exlude those locales from name generation
34     # in order to avoid test failures.
35     locales = set( [ l for l in faker.config.AVAILABLE_LOCALES if not (l.startswith('ar_') or l.startswith('sg_') or l=='fr_QC') ] )
36     acceptable_fakers = [faker.Faker(locale) for locale in locales]
37 setup()
38 
39 def random_faker():
40     global acceptable_fakers
41     return random.sample(acceptable_fakers, 1)[0]
42 
43 class UserFactory(factory.django.DjangoModelFactory):
44     class Meta:
45         model = User
46         django_get_or_create = ('username',)
47         exclude = ['faker', ]
48 
49     faker = factory.LazyFunction(random_faker)
50     first_name = factory.LazyAttribute(lambda o: o.faker.first_name())
51     last_name = factory.LazyAttribute(lambda o: o.faker.last_name())
52     email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),
53                                                 slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore
54     username = factory.LazyAttribute(lambda u: u.email)
55 
56     @factory.post_generation
57     def set_password(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
58         obj.set_password( '%s+password' % obj.username ) # pylint: disable=no-value-for-parameter
59 
60 class PersonFactory(factory.django.DjangoModelFactory):
61     class Meta:
62         model = Person
63 
64     user = factory.SubFactory(UserFactory)
65     name = factory.LazyAttribute(lambda p: normalize_name('%s %s'%(p.user.first_name, p.user.last_name)))
66     ascii = factory.LazyAttribute(lambda p: force_text(unidecode_name(p.name)))
67 
68     class Params:
69         with_bio = factory.Trait(biography = "\n\n".join(fake.paragraphs())) # type: ignore
70 
71     @factory.post_generation
72     def default_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
73         make_alias = getattr(AliasFactory, 'create' if create else 'build')
74         make_alias(person=obj,name=obj.name)
75         make_alias(person=obj,name=obj.ascii)
76         if obj.name != obj.plain_name():
77             make_alias(person=obj,name=obj.plain_name())
78         if obj.ascii != obj.plain_ascii():
79             make_alias(person=obj,name=obj.plain_ascii())
80 
81     @factory.post_generation
82     def default_emails(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
83         if extracted is None:
84             extracted = True
85         if create and extracted:
86             make_email = getattr(EmailFactory, 'create' if create else 'build')
87             make_email(person=obj, address=obj.user.email)
88 
89     @factory.post_generation
90     def default_photo(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
91         import atexit
92         if obj.biography:
93             photo_name = obj.photo_name()
94             media_name = "%s/%s.jpg" % (settings.PHOTOS_DIRNAME, photo_name)
95             obj.photo = media_name
96             obj.photo_thumb = media_name
97             photosrc = os.path.join(settings.TEST_DATA_DIR, "profile-default.jpg")
98             photodst = os.path.join(settings.PHOTOS_DIR,  photo_name + '.jpg')
99             if not os.path.exists(photodst):
100                 shutil.copy(photosrc, photodst)
101             def delete_file(file):
102                 os.unlink(file)
103             atexit.register(delete_file, photodst)
104 
105 class AliasFactory(factory.django.DjangoModelFactory):
106     class Meta:
107         model = Alias
108 
109     @classmethod
110     def _create(cls, model_class, *args, **kwargs):
111         person = kwargs['person']
112         name = kwargs['name']
113         existing_aliases = set(model_class.objects.filter(person=person).values_list('name', flat=True))
114         if not name in existing_aliases:
115             obj = model_class(*args, **kwargs)
116             obj.save()
117             return obj
118 
119     name = factory.Faker('name')
120 
121 def fake_email_address(n):
122     address_field = [ f for f in Email._meta.fields if f.name == 'address'][0]
123     count = 0
124     while True:
125         address = '%s.%s_%d@%s' % (
126             slugify(unidecode(fake.first_name())),
127             slugify(unidecode(fake.last_name())),
128             n, fake.domain_name()
129         )
130         count += 1
131         if len(address) <= address_field.max_length:
132             break
133         if count >= 10:
134             raise RuntimeError("Failed generating a fake email address to fit in Email.address(max_length=%s)"%address_field.max_lenth)
135     return address
136 
137 class EmailFactory(factory.django.DjangoModelFactory):
138     class Meta:
139         model = Email
140         django_get_or_create = ('address',)
141 
142     address = factory.Sequence(fake_email_address)
143     person = factory.SubFactory(PersonFactory)
144 
145     active = True
146     primary = False
147     origin = factory.LazyAttribute(lambda obj: obj.person.user.username if obj.person.user else '')
148 
149 
150 class PersonalApiKeyFactory(factory.django.DjangoModelFactory):
151     person = factory.SubFactory(PersonFactory)
152     endpoint = FuzzyChoice(PERSON_API_KEY_ENDPOINTS)
153 
154     class Meta:
155         model = PersonalApiKey
156 
157 class PersonApiKeyEventFactory(factory.django.DjangoModelFactory):
158     key = factory.SubFactory(PersonalApiKeyFactory)
159     person = factory.LazyAttribute(lambda o: o.key.person)
160     type = 'apikey_login'
161     desc = factory.Faker('sentence', nb_words=6)
162 
163     class Meta:
164         model = PersonApiKeyEvent
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/ietf/person/factories.py b/ietf/person/factories.py
--- a/ietf/person/factories.py
+++ b/ietf/person/factories.py
@@ -11,6 +11,7 @@
 import shutil
 
 from unidecode import unidecode
+from unicodedata import normalize
 
 from django.conf import settings
 from django.contrib.auth.models import User
@@ -47,8 +48,9 @@
         exclude = ['faker', ]
 
     faker = factory.LazyFunction(random_faker)
-    first_name = factory.LazyAttribute(lambda o: o.faker.first_name())
-    last_name = factory.LazyAttribute(lambda o: o.faker.last_name())
+    # normalize these i18n Unicode strings in the same way the database does
+    first_name = factory.LazyAttribute(lambda o: normalize("NFKC", o.faker.first_name()))
+    last_name = factory.LazyAttribute(lambda o: normalize("NFKC", o.faker.last_name()))
     email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),
                                                 slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore
     username = factory.LazyAttribute(lambda u: u.email)

{"golden_diff": "diff --git a/ietf/person/factories.py b/ietf/person/factories.py\n--- a/ietf/person/factories.py\n+++ b/ietf/person/factories.py\n@@ -11,6 +11,7 @@\n import shutil\n \n from unidecode import unidecode\n+from unicodedata import normalize\n \n from django.conf import settings\n from django.contrib.auth.models import User\n@@ -47,8 +48,9 @@\n         exclude = ['faker', ]\n \n     faker = factory.LazyFunction(random_faker)\n-    first_name = factory.LazyAttribute(lambda o: o.faker.first_name())\n-    last_name = factory.LazyAttribute(lambda o: o.faker.last_name())\n+    # normalize these i18n Unicode strings in the same way the database does\n+    first_name = factory.LazyAttribute(lambda o: normalize(\"NFKC\", o.faker.first_name()))\n+    last_name = factory.LazyAttribute(lambda o: normalize(\"NFKC\", o.faker.last_name()))\n     email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),\n                                                 slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore\n     username = factory.LazyAttribute(lambda u: u.email)\n", "issue": "test_docs_for_ad randomly spuriously fails\nWe occasionally see this failure:\r\n ======================================================================\r\nFAIL: test_docs_for_ad (ietf.doc.tests.SearchTests.test_docs_for_ad)\r\n----------------------------------------------------------------------\r\nTraceback (most recent call last):\r\n  File \"/__w/datatracker/datatracker/ietf/doc/tests.py\", line 301, in test_docs_for_ad\r\n    self.assertEqual(r.status_code, 200)\r\nAssertionError: 404 != 200\r\n\r\nIt's clearly a test-harness randomly generated data data mismatch with the view being tested. Investigation is needed to see if this is a real (but obscure corner) bug, or just insufficient constraints on the generated data issue. \n", "before_files": [{"content": "# Copyright The IETF Trust 2015-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nimport factory\nfrom factory.fuzzy import FuzzyChoice\nimport faker \nimport faker.config\nimport os\nimport random\nimport shutil\n\nfrom unidecode import unidecode\n\nfrom django.conf import settings\nfrom django.contrib.auth.models import User\nfrom django.utils.text import slugify\nfrom django.utils.encoding import force_text\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.person.models import Person, Alias, Email, PersonalApiKey, PersonApiKeyEvent, PERSON_API_KEY_ENDPOINTS\nfrom ietf.person.name import normalize_name, unidecode_name\n\n\nfake = faker.Factory.create()\n\ndef setup():\n    global acceptable_fakers\n    # The transliteration of some arabic and devanagari names introduces\n    # non-alphabetic characgters that don't work with the draft author\n    # extraction code, and also don't seem to match the way people with arabic\n    # names romanize arabic names.  Exlude those locales from name generation\n    # in order to avoid test failures.\n    locales = set( [ l for l in faker.config.AVAILABLE_LOCALES if not (l.startswith('ar_') or l.startswith('sg_') or l=='fr_QC') ] )\n    acceptable_fakers = [faker.Faker(locale) for locale in locales]\nsetup()\n\ndef random_faker():\n    global acceptable_fakers\n    return random.sample(acceptable_fakers, 1)[0]\n\nclass UserFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = User\n        django_get_or_create = ('username',)\n        exclude = ['faker', ]\n\n    faker = factory.LazyFunction(random_faker)\n    first_name = factory.LazyAttribute(lambda o: o.faker.first_name())\n    last_name = factory.LazyAttribute(lambda o: o.faker.last_name())\n    email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),\n                                                slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore\n    username = factory.LazyAttribute(lambda u: u.email)\n\n    @factory.post_generation\n    def set_password(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        obj.set_password( '%s+password' % obj.username ) # pylint: disable=no-value-for-parameter\n\nclass PersonFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Person\n\n    user = factory.SubFactory(UserFactory)\n    name = factory.LazyAttribute(lambda p: normalize_name('%s %s'%(p.user.first_name, p.user.last_name)))\n    ascii = factory.LazyAttribute(lambda p: force_text(unidecode_name(p.name)))\n\n    class Params:\n        with_bio = factory.Trait(biography = \"\\n\\n\".join(fake.paragraphs())) # type: ignore\n\n    @factory.post_generation\n    def default_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        make_alias = getattr(AliasFactory, 'create' if create else 'build')\n        make_alias(person=obj,name=obj.name)\n        make_alias(person=obj,name=obj.ascii)\n        if obj.name != obj.plain_name():\n            make_alias(person=obj,name=obj.plain_name())\n        if obj.ascii != obj.plain_ascii():\n            make_alias(person=obj,name=obj.plain_ascii())\n\n    @factory.post_generation\n    def default_emails(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        if extracted is None:\n            extracted = True\n        if create and extracted:\n            make_email = getattr(EmailFactory, 'create' if create else 'build')\n            make_email(person=obj, address=obj.user.email)\n\n    @factory.post_generation\n    def default_photo(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        import atexit\n        if obj.biography:\n            photo_name = obj.photo_name()\n            media_name = \"%s/%s.jpg\" % (settings.PHOTOS_DIRNAME, photo_name)\n            obj.photo = media_name\n            obj.photo_thumb = media_name\n            photosrc = os.path.join(settings.TEST_DATA_DIR, \"profile-default.jpg\")\n            photodst = os.path.join(settings.PHOTOS_DIR,  photo_name + '.jpg')\n            if not os.path.exists(photodst):\n                shutil.copy(photosrc, photodst)\n            def delete_file(file):\n                os.unlink(file)\n            atexit.register(delete_file, photodst)\n\nclass AliasFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Alias\n\n    @classmethod\n    def _create(cls, model_class, *args, **kwargs):\n        person = kwargs['person']\n        name = kwargs['name']\n        existing_aliases = set(model_class.objects.filter(person=person).values_list('name', flat=True))\n        if not name in existing_aliases:\n            obj = model_class(*args, **kwargs)\n            obj.save()\n            return obj\n\n    name = factory.Faker('name')\n\ndef fake_email_address(n):\n    address_field = [ f for f in Email._meta.fields if f.name == 'address'][0]\n    count = 0\n    while True:\n        address = '%s.%s_%d@%s' % (\n            slugify(unidecode(fake.first_name())),\n            slugify(unidecode(fake.last_name())),\n            n, fake.domain_name()\n        )\n        count += 1\n        if len(address) <= address_field.max_length:\n            break\n        if count >= 10:\n            raise RuntimeError(\"Failed generating a fake email address to fit in Email.address(max_length=%s)\"%address_field.max_lenth)\n    return address\n\nclass EmailFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Email\n        django_get_or_create = ('address',)\n\n    address = factory.Sequence(fake_email_address)\n    person = factory.SubFactory(PersonFactory)\n\n    active = True\n    primary = False\n    origin = factory.LazyAttribute(lambda obj: obj.person.user.username if obj.person.user else '')\n\n\nclass PersonalApiKeyFactory(factory.django.DjangoModelFactory):\n    person = factory.SubFactory(PersonFactory)\n    endpoint = FuzzyChoice(PERSON_API_KEY_ENDPOINTS)\n\n    class Meta:\n        model = PersonalApiKey\n\nclass PersonApiKeyEventFactory(factory.django.DjangoModelFactory):\n    key = factory.SubFactory(PersonalApiKeyFactory)\n    person = factory.LazyAttribute(lambda o: o.key.person)\n    type = 'apikey_login'\n    desc = factory.Faker('sentence', nb_words=6)\n\n    class Meta:\n        model = PersonApiKeyEvent\n", "path": "ietf/person/factories.py"}], "after_files": [{"content": "# Copyright The IETF Trust 2015-2020, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n\nimport factory\nfrom factory.fuzzy import FuzzyChoice\nimport faker \nimport faker.config\nimport os\nimport random\nimport shutil\n\nfrom unidecode import unidecode\nfrom unicodedata import normalize\n\nfrom django.conf import settings\nfrom django.contrib.auth.models import User\nfrom django.utils.text import slugify\nfrom django.utils.encoding import force_text\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.person.models import Person, Alias, Email, PersonalApiKey, PersonApiKeyEvent, PERSON_API_KEY_ENDPOINTS\nfrom ietf.person.name import normalize_name, unidecode_name\n\n\nfake = faker.Factory.create()\n\ndef setup():\n    global acceptable_fakers\n    # The transliteration of some arabic and devanagari names introduces\n    # non-alphabetic characgters that don't work with the draft author\n    # extraction code, and also don't seem to match the way people with arabic\n    # names romanize arabic names.  Exlude those locales from name generation\n    # in order to avoid test failures.\n    locales = set( [ l for l in faker.config.AVAILABLE_LOCALES if not (l.startswith('ar_') or l.startswith('sg_') or l=='fr_QC') ] )\n    acceptable_fakers = [faker.Faker(locale) for locale in locales]\nsetup()\n\ndef random_faker():\n    global acceptable_fakers\n    return random.sample(acceptable_fakers, 1)[0]\n\nclass UserFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = User\n        django_get_or_create = ('username',)\n        exclude = ['faker', ]\n\n    faker = factory.LazyFunction(random_faker)\n    # normalize these i18n Unicode strings in the same way the database does\n    first_name = factory.LazyAttribute(lambda o: normalize(\"NFKC\", o.faker.first_name()))\n    last_name = factory.LazyAttribute(lambda o: normalize(\"NFKC\", o.faker.last_name()))\n    email = factory.LazyAttributeSequence(lambda u, n: '%s.%s_%d@%s'%( slugify(unidecode(u.first_name)),\n                                                slugify(unidecode(u.last_name)), n, fake.domain_name())) # type: ignore\n    username = factory.LazyAttribute(lambda u: u.email)\n\n    @factory.post_generation\n    def set_password(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        obj.set_password( '%s+password' % obj.username ) # pylint: disable=no-value-for-parameter\n\nclass PersonFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Person\n\n    user = factory.SubFactory(UserFactory)\n    name = factory.LazyAttribute(lambda p: normalize_name('%s %s'%(p.user.first_name, p.user.last_name)))\n    ascii = factory.LazyAttribute(lambda p: force_text(unidecode_name(p.name)))\n\n    class Params:\n        with_bio = factory.Trait(biography = \"\\n\\n\".join(fake.paragraphs())) # type: ignore\n\n    @factory.post_generation\n    def default_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        make_alias = getattr(AliasFactory, 'create' if create else 'build')\n        make_alias(person=obj,name=obj.name)\n        make_alias(person=obj,name=obj.ascii)\n        if obj.name != obj.plain_name():\n            make_alias(person=obj,name=obj.plain_name())\n        if obj.ascii != obj.plain_ascii():\n            make_alias(person=obj,name=obj.plain_ascii())\n\n    @factory.post_generation\n    def default_emails(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        if extracted is None:\n            extracted = True\n        if create and extracted:\n            make_email = getattr(EmailFactory, 'create' if create else 'build')\n            make_email(person=obj, address=obj.user.email)\n\n    @factory.post_generation\n    def default_photo(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument\n        import atexit\n        if obj.biography:\n            photo_name = obj.photo_name()\n            media_name = \"%s/%s.jpg\" % (settings.PHOTOS_DIRNAME, photo_name)\n            obj.photo = media_name\n            obj.photo_thumb = media_name\n            photosrc = os.path.join(settings.TEST_DATA_DIR, \"profile-default.jpg\")\n            photodst = os.path.join(settings.PHOTOS_DIR,  photo_name + '.jpg')\n            if not os.path.exists(photodst):\n                shutil.copy(photosrc, photodst)\n            def delete_file(file):\n                os.unlink(file)\n            atexit.register(delete_file, photodst)\n\nclass AliasFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Alias\n\n    @classmethod\n    def _create(cls, model_class, *args, **kwargs):\n        person = kwargs['person']\n        name = kwargs['name']\n        existing_aliases = set(model_class.objects.filter(person=person).values_list('name', flat=True))\n        if not name in existing_aliases:\n            obj = model_class(*args, **kwargs)\n            obj.save()\n            return obj\n\n    name = factory.Faker('name')\n\ndef fake_email_address(n):\n    address_field = [ f for f in Email._meta.fields if f.name == 'address'][0]\n    count = 0\n    while True:\n        address = '%s.%s_%d@%s' % (\n            slugify(unidecode(fake.first_name())),\n            slugify(unidecode(fake.last_name())),\n            n, fake.domain_name()\n        )\n        count += 1\n        if len(address) <= address_field.max_length:\n            break\n        if count >= 10:\n            raise RuntimeError(\"Failed generating a fake email address to fit in Email.address(max_length=%s)\"%address_field.max_lenth)\n    return address\n\nclass EmailFactory(factory.django.DjangoModelFactory):\n    class Meta:\n        model = Email\n        django_get_or_create = ('address',)\n\n    address = factory.Sequence(fake_email_address)\n    person = factory.SubFactory(PersonFactory)\n\n    active = True\n    primary = False\n    origin = factory.LazyAttribute(lambda obj: obj.person.user.username if obj.person.user else '')\n\n\nclass PersonalApiKeyFactory(factory.django.DjangoModelFactory):\n    person = factory.SubFactory(PersonFactory)\n    endpoint = FuzzyChoice(PERSON_API_KEY_ENDPOINTS)\n\n    class Meta:\n        model = PersonalApiKey\n\nclass PersonApiKeyEventFactory(factory.django.DjangoModelFactory):\n    key = factory.SubFactory(PersonalApiKeyFactory)\n    person = factory.LazyAttribute(lambda o: o.key.person)\n    type = 'apikey_login'\n    desc = factory.Faker('sentence', nb_words=6)\n\n    class Meta:\n        model = PersonApiKeyEvent\n", "path": "ietf/person/factories.py"}]}