We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[PR #4609/4c4d6aa0 backport][3.28] Works around a sync-time performance regression on PG12
**This is a backport of PR #4609 as merged into main (4c4d6aa0745b4938e2aeee8ffc28a0b0392cc9ef).**

closes #4591

We still don't really "know":

* Why this only seems to happen on PG12
* Why the original query change (https://github.com/pulp/pulpcore/pull/4275/files) triggered this
* Why it only seems to happen on capsule syncs (this is most mysterious)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pulpcore/app/serializers/repository.py`
Content:
```
1 from gettext import gettext as _
2 
3 from rest_framework import serializers, fields
4 from rest_framework.validators import UniqueValidator
5 from rest_framework_nested.serializers import NestedHyperlinkedModelSerializer
6 
7 from pulpcore.app import models
8 from pulpcore.app.serializers import (
9     DetailIdentityField,
10     IdentityField,
11     NestedIdentityField,
12     NestedRelatedField,
13     LatestVersionField,
14     MasterModelSerializer,
15     ModelSerializer,
16 )
17 from pulpcore.app.serializers import validate_unknown_fields
18 
19 
20 class RepositorySerializer(ModelSerializer):
21     _href = IdentityField(
22         view_name='repositories-detail'
23     )
24     _versions_href = IdentityField(
25         view_name='versions-list',
26         lookup_url_kwarg='repository_pk',
27     )
28     _latest_version_href = LatestVersionField()
29     name = serializers.CharField(
30         help_text=_('A unique name for this repository.'),
31         validators=[UniqueValidator(queryset=models.Repository.objects.all())]
32     )
33     description = serializers.CharField(
34         help_text=_('An optional description.'),
35         required=False,
36         allow_blank=True
37     )
38 
39     class Meta:
40         model = models.Repository
41         fields = ModelSerializer.Meta.fields + ('_versions_href', '_latest_version_href', 'name',
42                                                 'description')
43 
44 
45 class RemoteSerializer(MasterModelSerializer):
46     """
47     Every remote defined by a plugin should have a Remote serializer that inherits from this
48     class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.
49     """
50     _href = DetailIdentityField()
51     name = serializers.CharField(
52         help_text=_('A unique name for this remote.'),
53         validators=[UniqueValidator(queryset=models.Remote.objects.all())],
54     )
55     url = serializers.CharField(
56         help_text='The URL of an external content source.',
57     )
58     validate = serializers.BooleanField(
59         help_text='If True, the plugin will validate imported artifacts.',
60         required=False,
61     )
62     ssl_ca_certificate = serializers.FileField(
63         help_text='A PEM encoded CA certificate used to validate the server '
64                   'certificate presented by the remote server.',
65         write_only=True,
66         required=False,
67     )
68     ssl_client_certificate = serializers.FileField(
69         help_text='A PEM encoded client certificate used for authentication.',
70         write_only=True,
71         required=False,
72     )
73     ssl_client_key = serializers.FileField(
74         help_text='A PEM encoded private key used for authentication.',
75         write_only=True,
76         required=False,
77     )
78     ssl_validation = serializers.BooleanField(
79         help_text='If True, SSL peer validation must be performed.',
80         required=False,
81     )
82     proxy_url = serializers.CharField(
83         help_text='The proxy URL. Format: scheme://user:password@host:port',
84         required=False,
85         allow_blank=True,
86     )
87     username = serializers.CharField(
88         help_text='The username to be used for authentication when syncing.',
89         write_only=True,
90         required=False,
91         allow_blank=True,
92     )
93     password = serializers.CharField(
94         help_text='The password to be used for authentication when syncing.',
95         write_only=True,
96         required=False,
97         allow_blank=True,
98     )
99     _last_updated = serializers.DateTimeField(
100         help_text='Timestamp of the most recent update of the remote.',
101         read_only=True
102     )
103     download_concurrency = serializers.IntegerField(
104         help_text='Total number of simultaneous connections.',
105         required=False,
106         min_value=1
107     )
108     policy = serializers.ChoiceField(
109         help_text="The policy to use when downloading content. The possible values include: "
110                   "'immediate', 'on_demand', and 'cache_only'. 'immediate' is the default.",
111         choices=models.Remote.POLICY_CHOICES,
112         default=models.Remote.IMMEDIATE
113     )
114 
115     class Meta:
116         abstract = True
117         model = models.Remote
118         fields = MasterModelSerializer.Meta.fields + (
119             'name', 'url', 'validate', 'ssl_ca_certificate', 'ssl_client_certificate',
120             'ssl_client_key', 'ssl_validation', 'proxy_url', 'username', 'password',
121             '_last_updated', 'download_concurrency', 'policy')
122 
123 
124 class RepositorySyncURLSerializer(serializers.Serializer):
125     repository = serializers.HyperlinkedRelatedField(
126         required=True,
127         help_text=_('A URI of the repository to be synchronized.'),
128         queryset=models.Repository.objects.all(),
129         view_name='repositories-detail',
130         label=_('Repository'),
131         error_messages={
132             'required': _('The repository URI must be specified.')
133         }
134     )
135 
136     mirror = fields.BooleanField(
137         required=False,
138         default=False,
139         help_text=_('The synchronization mode, True for "mirror" and False for "additive" mode.')
140     )
141 
142 
143 class PublisherSerializer(MasterModelSerializer):
144     """
145     Every publisher defined by a plugin should have an Publisher serializer that inherits from this
146     class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.
147     """
148     _href = DetailIdentityField()
149     name = serializers.CharField(
150         help_text=_('A unique name for this publisher.'),
151         validators=[UniqueValidator(queryset=models.Publisher.objects.all())]
152     )
153     _last_updated = serializers.DateTimeField(
154         help_text=_('Timestamp of the most recent update of the publisher configuration.'),
155         read_only=True
156     )
157     _distributions = serializers.HyperlinkedRelatedField(
158         many=True,
159         read_only=True,
160         view_name='distributions-detail',
161     )
162 
163     class Meta:
164         abstract = True
165         model = models.Publisher
166         fields = MasterModelSerializer.Meta.fields + (
167             'name', '_last_updated', '_distributions',
168         )
169 
170 
171 class RepositoryPublishURLSerializer(serializers.Serializer):
172 
173     repository = serializers.HyperlinkedRelatedField(
174         help_text=_('A URI of the repository to be synchronized.'),
175         required=False,
176         label=_('Repository'),
177         queryset=models.Repository.objects.all(),
178         view_name='repositories-detail',
179     )
180 
181     repository_version = NestedRelatedField(
182         help_text=_('A URI of the repository version to be published.'),
183         required=False,
184         label=_('Repository Version'),
185         queryset=models.RepositoryVersion.objects.all(),
186         view_name='versions-detail',
187         lookup_field='number',
188         parent_lookup_kwargs={'repository_pk': 'repository__pk'},
189     )
190 
191     def validate(self, data):
192         if hasattr(self, 'initial_data'):
193             validate_unknown_fields(self.initial_data, self.fields)
194 
195         repository = data.pop('repository', None)
196         repository_version = data.get('repository_version')
197         if not repository and not repository_version:
198             raise serializers.ValidationError(
199                 _("Either the 'repository' or 'repository_version' need to be specified"))
200         elif not repository and repository_version:
201             return data
202         elif repository and not repository_version:
203             version = models.RepositoryVersion.latest(repository)
204             if version:
205                 new_data = {'repository_version': version}
206                 new_data.update(data)
207                 return new_data
208             else:
209                 raise serializers.ValidationError(
210                     detail=_('Repository has no version available to publish'))
211         raise serializers.ValidationError(
212             _("Either the 'repository' or 'repository_version' need to be specified "
213               "but not both.")
214         )
215 
216 
217 class ExporterSerializer(MasterModelSerializer):
218     _href = DetailIdentityField()
219     name = serializers.CharField(
220         help_text=_('The exporter unique name.'),
221         validators=[UniqueValidator(queryset=models.Exporter.objects.all())]
222     )
223     _last_updated = serializers.DateTimeField(
224         help_text=_('Timestamp of the last update.'),
225         read_only=True
226     )
227     last_export = serializers.DateTimeField(
228         help_text=_('Timestamp of the last export.'),
229         read_only=True
230     )
231 
232     class Meta:
233         abstract = True
234         model = models.Exporter
235         fields = MasterModelSerializer.Meta.fields + (
236             'name',
237             '_last_updated',
238             'last_export',
239         )
240 
241 
242 class RepositoryVersionSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):
243     _href = NestedIdentityField(
244         view_name='versions-detail',
245         lookup_field='number', parent_lookup_kwargs={'repository_pk': 'repository__pk'},
246     )
247     number = serializers.IntegerField(
248         read_only=True
249     )
250     base_version = NestedRelatedField(
251         required=False,
252         help_text=_('A repository version whose content was used as the initial set of content '
253                     'for this repository version'),
254         queryset=models.RepositoryVersion.objects.all(),
255         view_name='versions-detail',
256         lookup_field='number',
257         parent_lookup_kwargs={'repository_pk': 'repository__pk'},
258     )
259     content_summary = serializers.SerializerMethodField(
260         help_text=_('Various count summaries of the content in the version and the HREF to view '
261                     'them.'),
262         read_only=True,
263     )
264 
265     def get_content_summary(self, obj):
266         """
267         The summary of contained content.
268 
269         Returns:
270             dict:    {'added': {<_type>: {'count': <count>, 'href': <href>},
271                       'removed': {<_type>: {'count': <count>, 'href': <href>},
272                       'present': {<_type>: {'count': <count>, 'href': <href>},
273                      }
274         """
275         to_return = {'added': {}, 'removed': {}, 'present': {}}
276         for count_detail in obj.counts.all():
277             count_type = count_detail.get_count_type_display()
278             item_dict = {'count': count_detail.count, 'href': count_detail.content_href}
279             to_return[count_type][count_detail.content_type] = item_dict
280         return to_return
281 
282     class Meta:
283         model = models.RepositoryVersion
284         fields = ModelSerializer.Meta.fields + (
285             '_href', 'number', 'base_version', 'content_summary',
286         )
287 
288 
289 class RepositoryVersionCreateSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):
290     add_content_units = serializers.ListField(
291         help_text=_('A list of content units to add to a new repository version'),
292         write_only=True
293     )
294     remove_content_units = serializers.ListField(
295         help_text=_('A list of content units to remove from the latest repository version'),
296         write_only=True
297     )
298     base_version = NestedRelatedField(
299         required=False,
300         help_text=_('A repository version whose content will be used as the initial set of content '
301                     'for the new repository version'),
302         queryset=models.RepositoryVersion.objects.all(),
303         view_name='versions-detail',
304         lookup_field='number',
305         parent_lookup_kwargs={'repository_pk': 'repository__pk'},
306     )
307 
308     class Meta:
309         model = models.RepositoryVersion
310         fields = ['add_content_units', 'remove_content_units', 'base_version']
311
```
--- 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/pulpcore/app/serializers/repository.py b/pulpcore/app/serializers/repository.py
--- a/pulpcore/app/serializers/repository.py
+++ b/pulpcore/app/serializers/repository.py
@@ -267,10 +267,14 @@
         The summary of contained content.
 
         Returns:
-            dict:    {'added': {<_type>: {'count': <count>, 'href': <href>},
-                      'removed': {<_type>: {'count': <count>, 'href': <href>},
-                      'present': {<_type>: {'count': <count>, 'href': <href>},
-                     }
+            dict: The dictionary has the following format.::
+
+                {
+                    'added': {<_type>: {'count': <count>, 'href': <href>},
+                    'removed': {<_type>: {'count': <count>, 'href': <href>},
+                    'present': {<_type>: {'count': <count>, 'href': <href>},
+                }
+
         """
         to_return = {'added': {}, 'removed': {}, 'present': {}}
         for count_detail in obj.counts.all():

{"golden_diff": "diff --git a/pulpcore/app/serializers/repository.py b/pulpcore/app/serializers/repository.py\n--- a/pulpcore/app/serializers/repository.py\n+++ b/pulpcore/app/serializers/repository.py\n@@ -267,10 +267,14 @@\n         The summary of contained content.\n \n         Returns:\n-            dict:    {'added': {<_type>: {'count': <count>, 'href': <href>},\n-                      'removed': {<_type>: {'count': <count>, 'href': <href>},\n-                      'present': {<_type>: {'count': <count>, 'href': <href>},\n-                     }\n+            dict: The dictionary has the following format.::\n+\n+                {\n+                    'added': {<_type>: {'count': <count>, 'href': <href>},\n+                    'removed': {<_type>: {'count': <count>, 'href': <href>},\n+                    'present': {<_type>: {'count': <count>, 'href': <href>},\n+                }\n+\n         \"\"\"\n         to_return = {'added': {}, 'removed': {}, 'present': {}}\n         for count_detail in obj.counts.all():\n", "issue": "[PR #4609/4c4d6aa0 backport][3.28] Works around a sync-time performance regression on PG12\n**This is a backport of PR #4609 as merged into main (4c4d6aa0745b4938e2aeee8ffc28a0b0392cc9ef).**\n\ncloses #4591\r\n\r\nWe still don't really \"know\":\r\n\r\n* Why this only seems to happen on PG12\r\n* Why the original query change (https://github.com/pulp/pulpcore/pull/4275/files) triggered this\r\n* Why it only seems to happen on capsule syncs (this is most mysterious)\n", "before_files": [{"content": "from gettext import gettext as _\n\nfrom rest_framework import serializers, fields\nfrom rest_framework.validators import UniqueValidator\nfrom rest_framework_nested.serializers import NestedHyperlinkedModelSerializer\n\nfrom pulpcore.app import models\nfrom pulpcore.app.serializers import (\n    DetailIdentityField,\n    IdentityField,\n    NestedIdentityField,\n    NestedRelatedField,\n    LatestVersionField,\n    MasterModelSerializer,\n    ModelSerializer,\n)\nfrom pulpcore.app.serializers import validate_unknown_fields\n\n\nclass RepositorySerializer(ModelSerializer):\n    _href = IdentityField(\n        view_name='repositories-detail'\n    )\n    _versions_href = IdentityField(\n        view_name='versions-list',\n        lookup_url_kwarg='repository_pk',\n    )\n    _latest_version_href = LatestVersionField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this repository.'),\n        validators=[UniqueValidator(queryset=models.Repository.objects.all())]\n    )\n    description = serializers.CharField(\n        help_text=_('An optional description.'),\n        required=False,\n        allow_blank=True\n    )\n\n    class Meta:\n        model = models.Repository\n        fields = ModelSerializer.Meta.fields + ('_versions_href', '_latest_version_href', 'name',\n                                                'description')\n\n\nclass RemoteSerializer(MasterModelSerializer):\n    \"\"\"\n    Every remote defined by a plugin should have a Remote serializer that inherits from this\n    class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.\n    \"\"\"\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this remote.'),\n        validators=[UniqueValidator(queryset=models.Remote.objects.all())],\n    )\n    url = serializers.CharField(\n        help_text='The URL of an external content source.',\n    )\n    validate = serializers.BooleanField(\n        help_text='If True, the plugin will validate imported artifacts.',\n        required=False,\n    )\n    ssl_ca_certificate = serializers.FileField(\n        help_text='A PEM encoded CA certificate used to validate the server '\n                  'certificate presented by the remote server.',\n        write_only=True,\n        required=False,\n    )\n    ssl_client_certificate = serializers.FileField(\n        help_text='A PEM encoded client certificate used for authentication.',\n        write_only=True,\n        required=False,\n    )\n    ssl_client_key = serializers.FileField(\n        help_text='A PEM encoded private key used for authentication.',\n        write_only=True,\n        required=False,\n    )\n    ssl_validation = serializers.BooleanField(\n        help_text='If True, SSL peer validation must be performed.',\n        required=False,\n    )\n    proxy_url = serializers.CharField(\n        help_text='The proxy URL. Format: scheme://user:password@host:port',\n        required=False,\n        allow_blank=True,\n    )\n    username = serializers.CharField(\n        help_text='The username to be used for authentication when syncing.',\n        write_only=True,\n        required=False,\n        allow_blank=True,\n    )\n    password = serializers.CharField(\n        help_text='The password to be used for authentication when syncing.',\n        write_only=True,\n        required=False,\n        allow_blank=True,\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text='Timestamp of the most recent update of the remote.',\n        read_only=True\n    )\n    download_concurrency = serializers.IntegerField(\n        help_text='Total number of simultaneous connections.',\n        required=False,\n        min_value=1\n    )\n    policy = serializers.ChoiceField(\n        help_text=\"The policy to use when downloading content. The possible values include: \"\n                  \"'immediate', 'on_demand', and 'cache_only'. 'immediate' is the default.\",\n        choices=models.Remote.POLICY_CHOICES,\n        default=models.Remote.IMMEDIATE\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Remote\n        fields = MasterModelSerializer.Meta.fields + (\n            'name', 'url', 'validate', 'ssl_ca_certificate', 'ssl_client_certificate',\n            'ssl_client_key', 'ssl_validation', 'proxy_url', 'username', 'password',\n            '_last_updated', 'download_concurrency', 'policy')\n\n\nclass RepositorySyncURLSerializer(serializers.Serializer):\n    repository = serializers.HyperlinkedRelatedField(\n        required=True,\n        help_text=_('A URI of the repository to be synchronized.'),\n        queryset=models.Repository.objects.all(),\n        view_name='repositories-detail',\n        label=_('Repository'),\n        error_messages={\n            'required': _('The repository URI must be specified.')\n        }\n    )\n\n    mirror = fields.BooleanField(\n        required=False,\n        default=False,\n        help_text=_('The synchronization mode, True for \"mirror\" and False for \"additive\" mode.')\n    )\n\n\nclass PublisherSerializer(MasterModelSerializer):\n    \"\"\"\n    Every publisher defined by a plugin should have an Publisher serializer that inherits from this\n    class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.\n    \"\"\"\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this publisher.'),\n        validators=[UniqueValidator(queryset=models.Publisher.objects.all())]\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text=_('Timestamp of the most recent update of the publisher configuration.'),\n        read_only=True\n    )\n    _distributions = serializers.HyperlinkedRelatedField(\n        many=True,\n        read_only=True,\n        view_name='distributions-detail',\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Publisher\n        fields = MasterModelSerializer.Meta.fields + (\n            'name', '_last_updated', '_distributions',\n        )\n\n\nclass RepositoryPublishURLSerializer(serializers.Serializer):\n\n    repository = serializers.HyperlinkedRelatedField(\n        help_text=_('A URI of the repository to be synchronized.'),\n        required=False,\n        label=_('Repository'),\n        queryset=models.Repository.objects.all(),\n        view_name='repositories-detail',\n    )\n\n    repository_version = NestedRelatedField(\n        help_text=_('A URI of the repository version to be published.'),\n        required=False,\n        label=_('Repository Version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n\n    def validate(self, data):\n        if hasattr(self, 'initial_data'):\n            validate_unknown_fields(self.initial_data, self.fields)\n\n        repository = data.pop('repository', None)\n        repository_version = data.get('repository_version')\n        if not repository and not repository_version:\n            raise serializers.ValidationError(\n                _(\"Either the 'repository' or 'repository_version' need to be specified\"))\n        elif not repository and repository_version:\n            return data\n        elif repository and not repository_version:\n            version = models.RepositoryVersion.latest(repository)\n            if version:\n                new_data = {'repository_version': version}\n                new_data.update(data)\n                return new_data\n            else:\n                raise serializers.ValidationError(\n                    detail=_('Repository has no version available to publish'))\n        raise serializers.ValidationError(\n            _(\"Either the 'repository' or 'repository_version' need to be specified \"\n              \"but not both.\")\n        )\n\n\nclass ExporterSerializer(MasterModelSerializer):\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('The exporter unique name.'),\n        validators=[UniqueValidator(queryset=models.Exporter.objects.all())]\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text=_('Timestamp of the last update.'),\n        read_only=True\n    )\n    last_export = serializers.DateTimeField(\n        help_text=_('Timestamp of the last export.'),\n        read_only=True\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Exporter\n        fields = MasterModelSerializer.Meta.fields + (\n            'name',\n            '_last_updated',\n            'last_export',\n        )\n\n\nclass RepositoryVersionSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):\n    _href = NestedIdentityField(\n        view_name='versions-detail',\n        lookup_field='number', parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n    number = serializers.IntegerField(\n        read_only=True\n    )\n    base_version = NestedRelatedField(\n        required=False,\n        help_text=_('A repository version whose content was used as the initial set of content '\n                    'for this repository version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n    content_summary = serializers.SerializerMethodField(\n        help_text=_('Various count summaries of the content in the version and the HREF to view '\n                    'them.'),\n        read_only=True,\n    )\n\n    def get_content_summary(self, obj):\n        \"\"\"\n        The summary of contained content.\n\n        Returns:\n            dict:    {'added': {<_type>: {'count': <count>, 'href': <href>},\n                      'removed': {<_type>: {'count': <count>, 'href': <href>},\n                      'present': {<_type>: {'count': <count>, 'href': <href>},\n                     }\n        \"\"\"\n        to_return = {'added': {}, 'removed': {}, 'present': {}}\n        for count_detail in obj.counts.all():\n            count_type = count_detail.get_count_type_display()\n            item_dict = {'count': count_detail.count, 'href': count_detail.content_href}\n            to_return[count_type][count_detail.content_type] = item_dict\n        return to_return\n\n    class Meta:\n        model = models.RepositoryVersion\n        fields = ModelSerializer.Meta.fields + (\n            '_href', 'number', 'base_version', 'content_summary',\n        )\n\n\nclass RepositoryVersionCreateSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):\n    add_content_units = serializers.ListField(\n        help_text=_('A list of content units to add to a new repository version'),\n        write_only=True\n    )\n    remove_content_units = serializers.ListField(\n        help_text=_('A list of content units to remove from the latest repository version'),\n        write_only=True\n    )\n    base_version = NestedRelatedField(\n        required=False,\n        help_text=_('A repository version whose content will be used as the initial set of content '\n                    'for the new repository version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n\n    class Meta:\n        model = models.RepositoryVersion\n        fields = ['add_content_units', 'remove_content_units', 'base_version']\n", "path": "pulpcore/app/serializers/repository.py"}], "after_files": [{"content": "from gettext import gettext as _\n\nfrom rest_framework import serializers, fields\nfrom rest_framework.validators import UniqueValidator\nfrom rest_framework_nested.serializers import NestedHyperlinkedModelSerializer\n\nfrom pulpcore.app import models\nfrom pulpcore.app.serializers import (\n    DetailIdentityField,\n    IdentityField,\n    NestedIdentityField,\n    NestedRelatedField,\n    LatestVersionField,\n    MasterModelSerializer,\n    ModelSerializer,\n)\nfrom pulpcore.app.serializers import validate_unknown_fields\n\n\nclass RepositorySerializer(ModelSerializer):\n    _href = IdentityField(\n        view_name='repositories-detail'\n    )\n    _versions_href = IdentityField(\n        view_name='versions-list',\n        lookup_url_kwarg='repository_pk',\n    )\n    _latest_version_href = LatestVersionField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this repository.'),\n        validators=[UniqueValidator(queryset=models.Repository.objects.all())]\n    )\n    description = serializers.CharField(\n        help_text=_('An optional description.'),\n        required=False,\n        allow_blank=True\n    )\n\n    class Meta:\n        model = models.Repository\n        fields = ModelSerializer.Meta.fields + ('_versions_href', '_latest_version_href', 'name',\n                                                'description')\n\n\nclass RemoteSerializer(MasterModelSerializer):\n    \"\"\"\n    Every remote defined by a plugin should have a Remote serializer that inherits from this\n    class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.\n    \"\"\"\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this remote.'),\n        validators=[UniqueValidator(queryset=models.Remote.objects.all())],\n    )\n    url = serializers.CharField(\n        help_text='The URL of an external content source.',\n    )\n    validate = serializers.BooleanField(\n        help_text='If True, the plugin will validate imported artifacts.',\n        required=False,\n    )\n    ssl_ca_certificate = serializers.FileField(\n        help_text='A PEM encoded CA certificate used to validate the server '\n                  'certificate presented by the remote server.',\n        write_only=True,\n        required=False,\n    )\n    ssl_client_certificate = serializers.FileField(\n        help_text='A PEM encoded client certificate used for authentication.',\n        write_only=True,\n        required=False,\n    )\n    ssl_client_key = serializers.FileField(\n        help_text='A PEM encoded private key used for authentication.',\n        write_only=True,\n        required=False,\n    )\n    ssl_validation = serializers.BooleanField(\n        help_text='If True, SSL peer validation must be performed.',\n        required=False,\n    )\n    proxy_url = serializers.CharField(\n        help_text='The proxy URL. Format: scheme://user:password@host:port',\n        required=False,\n        allow_blank=True,\n    )\n    username = serializers.CharField(\n        help_text='The username to be used for authentication when syncing.',\n        write_only=True,\n        required=False,\n        allow_blank=True,\n    )\n    password = serializers.CharField(\n        help_text='The password to be used for authentication when syncing.',\n        write_only=True,\n        required=False,\n        allow_blank=True,\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text='Timestamp of the most recent update of the remote.',\n        read_only=True\n    )\n    download_concurrency = serializers.IntegerField(\n        help_text='Total number of simultaneous connections.',\n        required=False,\n        min_value=1\n    )\n    policy = serializers.ChoiceField(\n        help_text=\"The policy to use when downloading content. The possible values include: \"\n                  \"'immediate', 'on_demand', and 'cache_only'. 'immediate' is the default.\",\n        choices=models.Remote.POLICY_CHOICES,\n        default=models.Remote.IMMEDIATE\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Remote\n        fields = MasterModelSerializer.Meta.fields + (\n            'name', 'url', 'validate', 'ssl_ca_certificate', 'ssl_client_certificate',\n            'ssl_client_key', 'ssl_validation', 'proxy_url', 'username', 'password',\n            '_last_updated', 'download_concurrency', 'policy')\n\n\nclass RepositorySyncURLSerializer(serializers.Serializer):\n    repository = serializers.HyperlinkedRelatedField(\n        required=True,\n        help_text=_('A URI of the repository to be synchronized.'),\n        queryset=models.Repository.objects.all(),\n        view_name='repositories-detail',\n        label=_('Repository'),\n        error_messages={\n            'required': _('The repository URI must be specified.')\n        }\n    )\n\n    mirror = fields.BooleanField(\n        required=False,\n        default=False,\n        help_text=_('The synchronization mode, True for \"mirror\" and False for \"additive\" mode.')\n    )\n\n\nclass PublisherSerializer(MasterModelSerializer):\n    \"\"\"\n    Every publisher defined by a plugin should have an Publisher serializer that inherits from this\n    class. Please import from `pulpcore.plugin.serializers` rather than from this module directly.\n    \"\"\"\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('A unique name for this publisher.'),\n        validators=[UniqueValidator(queryset=models.Publisher.objects.all())]\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text=_('Timestamp of the most recent update of the publisher configuration.'),\n        read_only=True\n    )\n    _distributions = serializers.HyperlinkedRelatedField(\n        many=True,\n        read_only=True,\n        view_name='distributions-detail',\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Publisher\n        fields = MasterModelSerializer.Meta.fields + (\n            'name', '_last_updated', '_distributions',\n        )\n\n\nclass RepositoryPublishURLSerializer(serializers.Serializer):\n\n    repository = serializers.HyperlinkedRelatedField(\n        help_text=_('A URI of the repository to be synchronized.'),\n        required=False,\n        label=_('Repository'),\n        queryset=models.Repository.objects.all(),\n        view_name='repositories-detail',\n    )\n\n    repository_version = NestedRelatedField(\n        help_text=_('A URI of the repository version to be published.'),\n        required=False,\n        label=_('Repository Version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n\n    def validate(self, data):\n        if hasattr(self, 'initial_data'):\n            validate_unknown_fields(self.initial_data, self.fields)\n\n        repository = data.pop('repository', None)\n        repository_version = data.get('repository_version')\n        if not repository and not repository_version:\n            raise serializers.ValidationError(\n                _(\"Either the 'repository' or 'repository_version' need to be specified\"))\n        elif not repository and repository_version:\n            return data\n        elif repository and not repository_version:\n            version = models.RepositoryVersion.latest(repository)\n            if version:\n                new_data = {'repository_version': version}\n                new_data.update(data)\n                return new_data\n            else:\n                raise serializers.ValidationError(\n                    detail=_('Repository has no version available to publish'))\n        raise serializers.ValidationError(\n            _(\"Either the 'repository' or 'repository_version' need to be specified \"\n              \"but not both.\")\n        )\n\n\nclass ExporterSerializer(MasterModelSerializer):\n    _href = DetailIdentityField()\n    name = serializers.CharField(\n        help_text=_('The exporter unique name.'),\n        validators=[UniqueValidator(queryset=models.Exporter.objects.all())]\n    )\n    _last_updated = serializers.DateTimeField(\n        help_text=_('Timestamp of the last update.'),\n        read_only=True\n    )\n    last_export = serializers.DateTimeField(\n        help_text=_('Timestamp of the last export.'),\n        read_only=True\n    )\n\n    class Meta:\n        abstract = True\n        model = models.Exporter\n        fields = MasterModelSerializer.Meta.fields + (\n            'name',\n            '_last_updated',\n            'last_export',\n        )\n\n\nclass RepositoryVersionSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):\n    _href = NestedIdentityField(\n        view_name='versions-detail',\n        lookup_field='number', parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n    number = serializers.IntegerField(\n        read_only=True\n    )\n    base_version = NestedRelatedField(\n        required=False,\n        help_text=_('A repository version whose content was used as the initial set of content '\n                    'for this repository version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n    content_summary = serializers.SerializerMethodField(\n        help_text=_('Various count summaries of the content in the version and the HREF to view '\n                    'them.'),\n        read_only=True,\n    )\n\n    def get_content_summary(self, obj):\n        \"\"\"\n        The summary of contained content.\n\n        Returns:\n            dict: The dictionary has the following format.::\n\n                {\n                    'added': {<_type>: {'count': <count>, 'href': <href>},\n                    'removed': {<_type>: {'count': <count>, 'href': <href>},\n                    'present': {<_type>: {'count': <count>, 'href': <href>},\n                }\n\n        \"\"\"\n        to_return = {'added': {}, 'removed': {}, 'present': {}}\n        for count_detail in obj.counts.all():\n            count_type = count_detail.get_count_type_display()\n            item_dict = {'count': count_detail.count, 'href': count_detail.content_href}\n            to_return[count_type][count_detail.content_type] = item_dict\n        return to_return\n\n    class Meta:\n        model = models.RepositoryVersion\n        fields = ModelSerializer.Meta.fields + (\n            '_href', 'number', 'base_version', 'content_summary',\n        )\n\n\nclass RepositoryVersionCreateSerializer(ModelSerializer, NestedHyperlinkedModelSerializer):\n    add_content_units = serializers.ListField(\n        help_text=_('A list of content units to add to a new repository version'),\n        write_only=True\n    )\n    remove_content_units = serializers.ListField(\n        help_text=_('A list of content units to remove from the latest repository version'),\n        write_only=True\n    )\n    base_version = NestedRelatedField(\n        required=False,\n        help_text=_('A repository version whose content will be used as the initial set of content '\n                    'for the new repository version'),\n        queryset=models.RepositoryVersion.objects.all(),\n        view_name='versions-detail',\n        lookup_field='number',\n        parent_lookup_kwargs={'repository_pk': 'repository__pk'},\n    )\n\n    class Meta:\n        model = models.RepositoryVersion\n        fields = ['add_content_units', 'remove_content_units', 'base_version']\n", "path": "pulpcore/app/serializers/repository.py"}]}