Repository: ansible/awx
File: awx/main/models/events.py (Python)

Code before:
        default='',
        editable=False,
    )
    parent_uuid = models.CharField(
        max_length=1024,
        default='',
        editable=False,
    )
    job_created = models.DateTimeField(null=True, editable=False)

    def get_absolute_url(self, request=None):
        return reverse('api:job_event_detail', kwargs={'pk': self.pk}, request=request)

    def __str__(self):
        return u'%s @ %s' % (self.get_event_display2(), self.created.isoformat())

    def _hostnames(self):
        hostnames = set()
        try:
            for stat in ('changed', 'dark', 'failures', 'ok', 'processed', 'skipped'):
                hostnames.update(self.event_data.get(stat, {}).keys())
        except AttributeError:  # In case event_data or v isn't a dict.
            pass
        return hostnames

    def _update_host_summary_from_stats(self, hostnames, bulk_update_hosts_sorted_by_id):
        with ignore_inventory_computed_fields():
            try:
                if not self.job or not self.job.inventory:
                    logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
                    return
            except ObjectDoesNotExist:
                logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
                return
            job = self.job

            from awx.main.models import Host, JobHostSummary  # circular import

            if self.job.inventory.kind == 'constructed':
                all_hosts = Host.objects.filter(id__in=self.job.inventory.hosts.values_list(Cast('instance_id', output_field=models.IntegerField()))).only(
                    'id', 'name'
                )
                constructed_host_map = self.host_map
                host_map = {host.name: host.id for host in all_hosts}
            else:
                all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name')
                constructed_host_map = {}
                host_map = self.host_map

            existing_host_ids = set(h.id for h in all_hosts)


Review comment (refactor):
It looks like `bulk_update_hosts_sorted_by_id` is your utility method. It would make more sense to import that method as opposed to taking it as an argument.

Guessing, but you might have had problems with circular imports. The thought process should be to keep a mental model or "order" of models. Utility functions should have the fewest (ideally no) internal dependencies, so I would point to my other comment that the module with the utility method shouldn't do `from awx.main.models.inventory import Host` and this should address any circularity you had importing that method from _this_ module.

Code after:
        max_length=1024,
        default='',
        editable=False,
    )
    parent_uuid = models.CharField(
        max_length=1024,
        default='',
        editable=False,
    )
    job_created = models.DateTimeField(null=True, editable=False)

    def get_absolute_url(self, request=None):
        return reverse('api:job_event_detail', kwargs={'pk': self.pk}, request=request)

    def __str__(self):
        return u'%s @ %s' % (self.get_event_display2(), self.created.isoformat())

    def _hostnames(self):
        hostnames = set()
        try:
            for stat in ('changed', 'dark', 'failures', 'ok', 'processed', 'skipped'):
                hostnames.update(self.event_data.get(stat, {}).keys())
        except AttributeError:  # In case event_data or v isn't a dict.
            pass
        return hostnames

    def _update_host_summary_from_stats(self, hostnames):
        with ignore_inventory_computed_fields():
            try:
                if not self.job or not self.job.inventory:
                    logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
                    return
            except ObjectDoesNotExist:
                logger.info('Event {} missing job or inventory, host summaries not updated'.format(self.pk))
                return
            job = self.job

            from awx.main.models import Host, JobHostSummary  # circular import

            if self.job.inventory.kind == 'constructed':
                all_hosts = Host.objects.filter(id__in=self.job.inventory.hosts.values_list(Cast('instance_id', output_field=models.IntegerField()))).only(
                    'id', 'name'
                )
                constructed_host_map = self.host_map
                host_map = {host.name: host.id for host in all_hosts}
            else:
                all_hosts = Host.objects.filter(pk__in=self.host_map.values()).only('id', 'name')
                constructed_host_map = {}
                host_map = self.host_map

            existing_host_ids = set(h.id for h in all_hosts)