We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Conflicts rendering Category pages when category is not defined in consistent case
I was testing a jinja macro that dealt with creating links for categories.

I noted that if you define a category in one article as `Category: Something` and in another article as `Category: something` that these are treated as separate categories, however, when your category page is rendered, there is only the lowecase url, e.g. `category/something.html`. This will only associate with the articles with meta data defined as `Category: something` and not anywhere where it is defined with uppercase since there is no `category/Something.html`.

I am not sure if making this case insensitive would break code. Certainly, it would be unclear when printing the category name which case to use. From an intelligent template process, you would set you case using CSS style attribute to be sure it was the way you want, and it could always render categories in lower case.

Otherwise, it might just be sufficient to put this into the documentation. I always tend to capitalize by categories, but some people might not notice and wonder why some articles are missing. I have not yet tested this, but I would imagine the same issue exists for tags.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pelican/urlwrappers.py`
Content:
```
1 import os
2 import functools
3 import logging
4 
5 import six
6 
7 from pelican.utils import (slugify, python_2_unicode_compatible)
8 
9 logger = logging.getLogger(__name__)
10 
11 
12 @python_2_unicode_compatible
13 @functools.total_ordering
14 class URLWrapper(object):
15     def __init__(self, name, settings):
16         self.name = name
17         self.slug = slugify(self.name)
18         self.settings = settings
19 
20     def as_dict(self):
21         return self.__dict__
22 
23     def __hash__(self):
24         return hash(self.name)
25 
26     def _key(self):
27         return self.name
28 
29     def _normalize_key(self, key):
30         return six.text_type(key)
31 
32     def __eq__(self, other):
33         return self._key() == self._normalize_key(other)
34 
35     def __ne__(self, other):
36         return self._key() != self._normalize_key(other)
37 
38     def __lt__(self, other):
39         return self._key() < self._normalize_key(other)
40 
41     def __str__(self):
42         return self.name
43 
44     def __repr__(self):
45         return '<{} {}>'.format(type(self).__name__, str(self))
46 
47     def _from_settings(self, key, get_page_name=False):
48         """Returns URL information as defined in settings.
49 
50         When get_page_name=True returns URL without anything after {slug} e.g.
51         if in settings: CATEGORY_URL="cat/{slug}.html" this returns
52         "cat/{slug}" Useful for pagination.
53 
54         """
55         setting = "%s_%s" % (self.__class__.__name__.upper(), key)
56         value = self.settings[setting]
57         if not isinstance(value, six.string_types):
58             logger.warning('%s is set to %s' % (setting, value))
59             return value
60         else:
61             if get_page_name:
62                 return os.path.splitext(value)[0].format(**self.as_dict())
63             else:
64                 return value.format(**self.as_dict())
65 
66     page_name = property(functools.partial(_from_settings, key='URL',
67                          get_page_name=True))
68     url = property(functools.partial(_from_settings, key='URL'))
69     save_as = property(functools.partial(_from_settings, key='SAVE_AS'))
70 
71 
72 class Category(URLWrapper):
73     pass
74 
75 
76 class Tag(URLWrapper):
77     def __init__(self, name, *args, **kwargs):
78         super(Tag, self).__init__(name.strip(), *args, **kwargs)
79 
80 
81 class Author(URLWrapper):
82     pass
83
```
--- 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/pelican/urlwrappers.py b/pelican/urlwrappers.py
--- a/pelican/urlwrappers.py
+++ b/pelican/urlwrappers.py
@@ -13,21 +13,35 @@
 @functools.total_ordering
 class URLWrapper(object):
     def __init__(self, name, settings):
+        # next 2 lines are redundant with the setter of the name property
+        # but are here for clarity
+        self._name = name
+        self.slug = slugify(name)
         self.name = name
-        self.slug = slugify(self.name)
         self.settings = settings
 
+    @property
+    def name(self):
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        self._name = name
+        self.slug = slugify(name)
+
     def as_dict(self):
-        return self.__dict__
+        d = self.__dict__
+        d['name'] = self.name
+        return d
 
     def __hash__(self):
-        return hash(self.name)
+        return hash(self.slug)
 
     def _key(self):
-        return self.name
+        return self.slug
 
     def _normalize_key(self, key):
-        return six.text_type(key)
+        return six.text_type(slugify(key))
 
     def __eq__(self, other):
         return self._key() == self._normalize_key(other)

{"golden_diff": "diff --git a/pelican/urlwrappers.py b/pelican/urlwrappers.py\n--- a/pelican/urlwrappers.py\n+++ b/pelican/urlwrappers.py\n@@ -13,21 +13,35 @@\n @functools.total_ordering\n class URLWrapper(object):\n     def __init__(self, name, settings):\n+        # next 2 lines are redundant with the setter of the name property\n+        # but are here for clarity\n+        self._name = name\n+        self.slug = slugify(name)\n         self.name = name\n-        self.slug = slugify(self.name)\n         self.settings = settings\n \n+    @property\n+    def name(self):\n+        return self._name\n+\n+    @name.setter\n+    def name(self, name):\n+        self._name = name\n+        self.slug = slugify(name)\n+\n     def as_dict(self):\n-        return self.__dict__\n+        d = self.__dict__\n+        d['name'] = self.name\n+        return d\n \n     def __hash__(self):\n-        return hash(self.name)\n+        return hash(self.slug)\n \n     def _key(self):\n-        return self.name\n+        return self.slug\n \n     def _normalize_key(self, key):\n-        return six.text_type(key)\n+        return six.text_type(slugify(key))\n \n     def __eq__(self, other):\n         return self._key() == self._normalize_key(other)\n", "issue": "Conflicts rendering Category pages when category is not defined in consistent case\nI was testing a jinja macro that dealt with creating links for categories.\n\nI noted that if you define a category in one article as `Category: Something` and in another article as `Category: something` that these are treated as separate categories, however, when your category page is rendered, there is only the lowecase url, e.g. `category/something.html`. This will only associate with the articles with meta data defined as `Category: something` and not anywhere where it is defined with uppercase since there is no `category/Something.html`.\n\nI am not sure if making this case insensitive would break code. Certainly, it would be unclear when printing the category name which case to use. From an intelligent template process, you would set you case using CSS style attribute to be sure it was the way you want, and it could always render categories in lower case.\n\nOtherwise, it might just be sufficient to put this into the documentation. I always tend to capitalize by categories, but some people might not notice and wonder why some articles are missing. I have not yet tested this, but I would imagine the same issue exists for tags.\n\n", "before_files": [{"content": "import os\nimport functools\nimport logging\n\nimport six\n\nfrom pelican.utils import (slugify, python_2_unicode_compatible)\n\nlogger = logging.getLogger(__name__)\n\n\n@python_2_unicode_compatible\n@functools.total_ordering\nclass URLWrapper(object):\n    def __init__(self, name, settings):\n        self.name = name\n        self.slug = slugify(self.name)\n        self.settings = settings\n\n    def as_dict(self):\n        return self.__dict__\n\n    def __hash__(self):\n        return hash(self.name)\n\n    def _key(self):\n        return self.name\n\n    def _normalize_key(self, key):\n        return six.text_type(key)\n\n    def __eq__(self, other):\n        return self._key() == self._normalize_key(other)\n\n    def __ne__(self, other):\n        return self._key() != self._normalize_key(other)\n\n    def __lt__(self, other):\n        return self._key() < self._normalize_key(other)\n\n    def __str__(self):\n        return self.name\n\n    def __repr__(self):\n        return '<{} {}>'.format(type(self).__name__, str(self))\n\n    def _from_settings(self, key, get_page_name=False):\n        \"\"\"Returns URL information as defined in settings.\n\n        When get_page_name=True returns URL without anything after {slug} e.g.\n        if in settings: CATEGORY_URL=\"cat/{slug}.html\" this returns\n        \"cat/{slug}\" Useful for pagination.\n\n        \"\"\"\n        setting = \"%s_%s\" % (self.__class__.__name__.upper(), key)\n        value = self.settings[setting]\n        if not isinstance(value, six.string_types):\n            logger.warning('%s is set to %s' % (setting, value))\n            return value\n        else:\n            if get_page_name:\n                return os.path.splitext(value)[0].format(**self.as_dict())\n            else:\n                return value.format(**self.as_dict())\n\n    page_name = property(functools.partial(_from_settings, key='URL',\n                         get_page_name=True))\n    url = property(functools.partial(_from_settings, key='URL'))\n    save_as = property(functools.partial(_from_settings, key='SAVE_AS'))\n\n\nclass Category(URLWrapper):\n    pass\n\n\nclass Tag(URLWrapper):\n    def __init__(self, name, *args, **kwargs):\n        super(Tag, self).__init__(name.strip(), *args, **kwargs)\n\n\nclass Author(URLWrapper):\n    pass\n", "path": "pelican/urlwrappers.py"}], "after_files": [{"content": "import os\nimport functools\nimport logging\n\nimport six\n\nfrom pelican.utils import (slugify, python_2_unicode_compatible)\n\nlogger = logging.getLogger(__name__)\n\n\n@python_2_unicode_compatible\n@functools.total_ordering\nclass URLWrapper(object):\n    def __init__(self, name, settings):\n        # next 2 lines are redundant with the setter of the name property\n        # but are here for clarity\n        self._name = name\n        self.slug = slugify(name)\n        self.name = name\n        self.settings = settings\n\n    @property\n    def name(self):\n        return self._name\n\n    @name.setter\n    def name(self, name):\n        self._name = name\n        self.slug = slugify(name)\n\n    def as_dict(self):\n        d = self.__dict__\n        d['name'] = self.name\n        return d\n\n    def __hash__(self):\n        return hash(self.slug)\n\n    def _key(self):\n        return self.slug\n\n    def _normalize_key(self, key):\n        return six.text_type(slugify(key))\n\n    def __eq__(self, other):\n        return self._key() == self._normalize_key(other)\n\n    def __ne__(self, other):\n        return self._key() != self._normalize_key(other)\n\n    def __lt__(self, other):\n        return self._key() < self._normalize_key(other)\n\n    def __str__(self):\n        return self.name\n\n    def __repr__(self):\n        return '<{} {}>'.format(type(self).__name__, str(self))\n\n    def _from_settings(self, key, get_page_name=False):\n        \"\"\"Returns URL information as defined in settings.\n\n        When get_page_name=True returns URL without anything after {slug} e.g.\n        if in settings: CATEGORY_URL=\"cat/{slug}.html\" this returns\n        \"cat/{slug}\" Useful for pagination.\n\n        \"\"\"\n        setting = \"%s_%s\" % (self.__class__.__name__.upper(), key)\n        value = self.settings[setting]\n        if not isinstance(value, six.string_types):\n            logger.warning('%s is set to %s' % (setting, value))\n            return value\n        else:\n            if get_page_name:\n                return os.path.splitext(value)[0].format(**self.as_dict())\n            else:\n                return value.format(**self.as_dict())\n\n    page_name = property(functools.partial(_from_settings, key='URL',\n                         get_page_name=True))\n    url = property(functools.partial(_from_settings, key='URL'))\n    save_as = property(functools.partial(_from_settings, key='SAVE_AS'))\n\n\nclass Category(URLWrapper):\n    pass\n\n\nclass Tag(URLWrapper):\n    def __init__(self, name, *args, **kwargs):\n        super(Tag, self).__init__(name.strip(), *args, **kwargs)\n\n\nclass Author(URLWrapper):\n    pass\n", "path": "pelican/urlwrappers.py"}]}