@task
def sync_project(project_pk):
    """Syncronize all dependencies of a project.

    This syncronizes all package versions and creates proper
    log entries on updates as well as starts the notification
    routing.
    """
    project = Project.objects.get(pk=project_pk)

    log_entries = []
    for dependency in project.dependencies.all():
        package = dependency.package
        package.sync_versions()
        versions = list(package.versions.values_list('version', flat=True))

        if versions:
            # We use LooseVersion since at least pytz fails with StrictVersion
            # TODO: tests
            versions.sort(key=LooseVersion)

            if LooseVersion(dependency.version) >= LooseVersion(versions[-1]):
                ProjectDependency.objects.filter(pk=dependency.pk) \
                                         .update(update=None)
                continue  # The dependency is up2date, nothing to do

            pv = PackageVersion.objects.get(package=package,
                                            version=versions[-1])

            if pv.pk == dependency.update_id:
                continue

            dependency.update = pv
            dependency.save()
            tz = timezone.utc
            since = str(timezone.make_naive(pv.release_date, tz))
            log_entries.append(Log(type='project_dependency',
                                   action='update_available',
                                   project=project, package=package,
                                   data={'version': versions[-1],
                                         'since': since}))
    if log_entries:
        Log.objects.bulk_create(log_entries)
        send_notifications(project, log_entries)
dataset/ETHPy150Open rocketDuck/folivora/folivora/tasks.py/sync_project/original