@task(max_retries=4, iterations=0)
def sync_with_changelog():
    """Syncronize with pypi changelog.

    Right now we only listen for `new-release`, `remove`, `rename`,
    and `create` as we do not store any metadata information.

    Following actions can be issued according to pypi source code:
        new release			- Creates a new Release
        remove				- Removes a Package from the Shop
        rename from %(old)s		- Rename a package
        add %(pyversion)s %(filename)s  - Add a new file to a version
        remove file %(filename)s        - Remove a file
        docupdate                       - Notify for documentation update
        create				- Create a new package
        update %(type)s                 - Update some detailed classifiers
    """
    next_last_sync = timezone.now()

    state, created = SyncState.objects.get_or_create(type=SyncState.CHANGELOG)

    epoch = int(time.mktime(state.last_sync.timetuple()))

    client = CheeseShop()

    try:
        log = client.get_changelog(epoch, True)
    except socket.error as exc:
        if current.iterations == current.max_retries:
            SyncState.objects.filter(type=SyncState.CHANGELOG) \
                             .update(state=SyncState.STATE_DOWN)
            logger.warning('No sync with PyPi, it\'s not reachable.')
            return
        else:
            current.iterations += 1
            current.retry(countdown=0, exc=exc)
    else:
        projects = set()
        for package, version, stamp, action in log:
            if action == 'new release':
                try:
                    pkg = Package.objects.get(name=package)
                except Package.DoesNotExist:
                    pkg = Package.create_with_provider_url(package)

                dt = datetime.datetime.fromtimestamp(stamp)
                release_date = timezone.make_aware(dt, pytz.UTC)
                exists = PackageVersion.objects.filter(package=pkg,
                                                       version=version).exists()
                if not exists:
                    update = PackageVersion(version=version,
                                            release_date=release_date)
                    pkg.versions.add(update)
                    ProjectDependency.objects.filter(package=pkg) \
                                             .update(update=update)

                projects.update(Project.objects.filter(dependencies__package=pkg)
                                               .values_list('id', flat=True))

            elif action == 'remove':
                # We only clear versions and set the recent updated version
                # on every project dependency to NULL. This way we can ensure
                # stability on ProjectDependency.
                try:
                    pkg = Package.objects.get(name=package)
                    ProjectDependency.objects.filter(package=pkg) \
                                             .update(update=None)

                    if version is None:
                        pkg.versions.all().delete()

                    log_affected_projects(pkg, action='remove_package',
                                          type='package', package=pkg)
                except Package.DoesNotExist:
                    pass

            elif action == 'create':
                if not Package.objects.filter(name=package).exists():
                    Package.create_with_provider_url(package)

        for project in projects:
            sync_project.apply(args=(project,))

        SyncState.objects.filter(type=SyncState.CHANGELOG) \
                         .update(last_sync=next_last_sync,
                                 state=SyncState.STATE_RUNNING)
dataset/ETHPy150Open rocketDuck/folivora/folivora/tasks.py/sync_with_changelog/original