summaryrefslogtreecommitdiff
path: root/scripts/upload-old-releases-as-zip.py
blob: 38cfcd55448f129cc2791ad1692d01e2246f0187 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# declare and require dependencies
__requires__ = [
    'twine',
]; __import__('pkg_resources')

import errno
import glob
import hashlib
import json
import os
import shutil
import tarfile
import codecs
import urllib.request
import urllib.parse
import urllib.error
from distutils.version import LooseVersion

from twine.commands import upload


OK = '\033[92m'
FAIL = '\033[91m'
END = '\033[0m'
DISTRIBUTION = "setuptools"


class SetuptoolsOldReleasesWithoutZip:
    """docstring for SetuptoolsOldReleases"""

    def __init__(self):
        self.dirpath = './dist'
        os.makedirs(self.dirpath, exist_ok=True)
        print("Downloading %s releases..." % DISTRIBUTION)
        print("All releases will be downloaded to %s" % self.dirpath)
        self.data_json_setuptools = self.get_json_data(DISTRIBUTION)
        self.valid_releases_numbers = sorted([
            release
            for release in self.data_json_setuptools['releases']
            # This condition is motivated by 13.0 release, which
            # comes as "13.0": [], in the json
            if self.data_json_setuptools['releases'][release]
        ], key=LooseVersion)
        self.total_downloaded_ok = 0

    def get_json_data(self, package_name):
        """
        "releases": {
            "0.7.2": [
                {
                    "has_sig": false,
                    "upload_time": "2013-06-09T16:10:00",
                    "comment_text": "",
                    "python_version": "source",
                    "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.2.tar.gz",  # NOQA
                    "md5_digest": "de44cd90f8a1c713d6c2bff67bbca65d",
                    "downloads": 159014,
                    "filename": "setuptools-0.7.2.tar.gz",
                    "packagetype": "sdist",
                    "size": 633077
                }
            ],
            "0.7.3": [
                {
                    "has_sig": false,
                    "upload_time": "2013-06-18T21:08:56",
                    "comment_text": "",
                    "python_version": "source",
                    "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.3.tar.gz",  # NOQA
                    "md5_digest": "c854adacbf9067d330a847f06f7a8eba",
                    "downloads": 30594,
                    "filename": "setuptools-0.7.3.tar.gz",
                    "packagetype": "sdist",
                    "size": 751152
                }
            ],
            "12.3": [
                {
                    "has_sig": false,
                    "upload_time": "2015-02-26T19:15:51",
                    "comment_text": "",
                    "python_version": "3.4",
                    "url": "https://pypi.python.org/packages/3.4/s/setuptools/setuptools-12.3-py2.py3-none-any.whl",  # NOQA
                    "md5_digest": "31f51a38497a70efadf5ce8d4c2211ab",
                    "downloads": 288451,
                    "filename": "setuptools-12.3-py2.py3-none-any.whl",
                    "packagetype": "bdist_wheel",
                    "size": 501904
                },
                {
                    "has_sig": false,
                    "upload_time": "2015-02-26T19:15:43",
                    "comment_text": "",
                    "python_version": "source",
                    "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.tar.gz",  # NOQA
                    "md5_digest": "67614b6d560fa4f240e99cd553ec7f32",
                    "downloads": 110109,
                    "filename": "setuptools-12.3.tar.gz",
                    "packagetype": "sdist",
                    "size": 635025
                },
                {
                    "has_sig": false,
                    "upload_time": "2015-02-26T19:15:47",
                    "comment_text": "",
                    "python_version": "source",
                    "url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.zip",  # NOQA
                    "md5_digest": "abc799e7db6e7281535bf342bfc41a12",
                    "downloads": 67539,
                    "filename": "setuptools-12.3.zip",
                    "packagetype": "sdist",
                    "size": 678783
                }
            ],
        """
        url = "https://pypi.python.org/pypi/%s/json" % (package_name,)
        resp = urllib.request.urlopen(urllib.request.Request(url))
        charset = resp.info().get_content_charset()
        reader = codecs.getreader(charset)(resp)
        data = json.load(reader)

        # Mainly for debug.
        json_filename = "%s/%s.json" % (self.dirpath, DISTRIBUTION)
        with open(json_filename, 'w') as outfile:
            json.dump(
                data,
                outfile,
                sort_keys=True,
                indent=4,
                separators=(',', ': '),
            )

        return data

    def get_setuptools_releases_without_zip_counterpart(self):
        # Get set(all_valid_releases) - set(releases_with_zip), so now we have
        # the releases without zip.
        return set(self.valid_releases_numbers) - set([
            release
            for release in self.valid_releases_numbers
                for same_version_release_dict in self.data_json_setuptools['releases'][release]  # NOQA
                if 'zip' in same_version_release_dict['filename']
       ])

    def download_setuptools_releases_without_zip_counterpart(self):
        try:
            releases_without_zip = self.get_setuptools_releases_without_zip_counterpart()  # NOQA
            failed_md5_releases = []
            # This is a "strange" loop, going through all releases and
            # testing only the release I need to download, but I thought it
            # would be mouch more readable than trying to iterate through
            # releases I need and get into traverse hell values inside dicts
            # inside dicts of the json to get the distribution's url to
            # download.
            for release in self.valid_releases_numbers:
                if release in releases_without_zip:
                    for same_version_release_dict in self.data_json_setuptools['releases'][release]:  # NOQA
                        if 'tar.gz' in same_version_release_dict['filename']:
                            print("Downloading %s..." % release)
                            local_file = '%s/%s' % (
                                self.dirpath,
                                same_version_release_dict["filename"]
                            )
                            urllib.request.urlretrieve(
                                same_version_release_dict["url"],
                                local_file
                            )
                            targz = open(local_file, 'rb').read()
                            hexdigest = hashlib.md5(targz).hexdigest()
                            if (hexdigest != same_version_release_dict['md5_digest']):  # NOQA
                                print(FAIL + "FAIL: md5 for %s didn't match!" % release + END)  # NOQA
                                failed_md5_releases.append(release)
                            else:
                                self.total_downloaded_ok += 1
            print('Total releases without zip: %s' % len(releases_without_zip))
            print('Total downloaded: %s' % self.total_downloaded_ok)
            if failed_md5_releases:
                msg = FAIL + (
                    "FAIL: these releases %s failed the md5 check!" %
                    ','.join(failed_md5_releases)
                ) + END
                raise Exception(msg)
            elif self.total_downloaded_ok != len(releases_without_zip):
                msg = FAIL + (
                    "FAIL: Unknown error occured. Please check the logs."
                ) + END
                raise Exception(msg)
            else:
                print(OK + "All releases downloaded and md5 checked." + END)

        except OSError as e:
            if e.errno != errno.EEXIST:
                raise e

    def convert_targz_to_zip(self):
        print("Converting the tar.gz to zip...")
        files = glob.glob('%s/*.tar.gz' % self.dirpath)
        total_converted = 0
        for targz in sorted(files, key=LooseVersion):
            # Extract and remove tar.
            tar = tarfile.open(targz)
            tar.extractall(path=self.dirpath)
            tar.close()
            os.remove(targz)

            # Zip the extracted tar.
            setuptools_folder_path = targz.replace('.tar.gz', '')
            setuptools_folder_name = setuptools_folder_path.split("/")[-1]
            print(setuptools_folder_name)
            shutil.make_archive(
                setuptools_folder_path,
                'zip',
                self.dirpath,
                setuptools_folder_name
            )
            # Exclude extracted tar folder.
            shutil.rmtree(setuptools_folder_path.replace('.zip', ''))
            total_converted += 1
        print('Total converted: %s' % total_converted)
        if self.total_downloaded_ok != total_converted:
            msg = FAIL + (
                "FAIL: Total number of downloaded releases is different"
                " from converted ones. Please check the logs."
            ) + END
            raise Exception(msg)
        print("Done with the tar.gz->zip. Check folder %s." % main.dirpath)

    def upload_zips_to_pypi(self):
        print('Uploading to pypi...')
        zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion)
        print("simulated upload of", zips); return
        upload.upload(dists=zips)


if __name__ == '__main__':
    main = SetuptoolsOldReleasesWithoutZip()
    main.download_setuptools_releases_without_zip_counterpart()
    main.convert_targz_to_zip()
    main.upload_zips_to_pypi()