mirror of
https://github.com/google/pebble.git
synced 2025-03-15 00:31:21 +00:00
237 lines
7.3 KiB
Python
237 lines
7.3 KiB
Python
# Copyright 2024 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import pbpack
|
|
import polib
|
|
import requests
|
|
import sys
|
|
import tempfile
|
|
|
|
|
|
logging.basicConfig()
|
|
logging.getLogger().setLevel(logging.DEBUG)
|
|
requests_log = logging.getLogger("requests.packages.urllib3")
|
|
requests_log.setLevel(logging.DEBUG)
|
|
requests_log.propagate = True
|
|
|
|
|
|
LP_URLS = {"staging": "https://lang-packs-staging.getpebble.com",
|
|
"production": "https://lp.getpebble.com"}
|
|
lp_url = None
|
|
|
|
if 'LP_HTTP_USERNAME' not in os.environ or 'LP_HTTP_PASSWORD' not in os.environ:
|
|
print """Missing HTTP username/password!
|
|
Please define LP_HTTP_USERNAME and LP_HTTP_PASSWORD in your environment"""
|
|
sys.exit(1)
|
|
|
|
lp_http_username = os.environ['LP_HTTP_USERNAME']
|
|
lp_http_password = os.environ['LP_HTTP_PASSWORD']
|
|
lp_auth = requests.auth.HTTPBasicAuth(lp_http_username, lp_http_password)
|
|
|
|
FIRMWARE_VERSION_TO_UPDATE = 4
|
|
|
|
|
|
def assert_ok(response):
|
|
if response.status_code != requests.codes.ok:
|
|
print response.status_code
|
|
print response.text
|
|
|
|
|
|
def find_existing_pack(hardware, lang):
|
|
# Look for an existing language pack. Use X.99.99 as the requesting version as the
|
|
# lp server will only return packs that are for the same major version and a smaller
|
|
# minor version, and we want the most recent pack with the highest minor version there is.
|
|
r = requests.get('{}/v1/languages'.format(lp_url),
|
|
params={'hardware': hardware,
|
|
'firmware': '{}.99.99'.format(FIRMWARE_VERSION_TO_UPDATE)},
|
|
auth=lp_auth)
|
|
assert_ok(r)
|
|
|
|
for l in r.json()['languages']:
|
|
if l['ISOLocal'] == lang:
|
|
return l
|
|
|
|
return None
|
|
|
|
|
|
def create_new_pack_json(hardware, name, fw_version, metadata):
|
|
return {
|
|
'name': name,
|
|
'localName': metadata['Name'],
|
|
'hardware': hardware,
|
|
'ISOLocal': metadata['Language'],
|
|
'firmware': fw_version,
|
|
'mobile': {
|
|
'name': 'ios',
|
|
'version': '2.6.0'
|
|
}
|
|
}
|
|
|
|
|
|
def pack_json_to_post_data(j):
|
|
# The POST data that the form wants looks like the following...
|
|
#
|
|
# pack[file]:https://language-packs-staging.s3.amazonaws.com/3TRBOAT-en_US.pbl
|
|
# pack[name]:English
|
|
# pack[localName]:English
|
|
# pack[hardware]:bb2
|
|
# pack[ISOLocal]:en_US
|
|
# pack[version]:1
|
|
# pack[firmware]:2.9.0
|
|
# pack[mobile][name]:ios
|
|
# pack[mobile][version]:2.6.0
|
|
#
|
|
# Convert our json into that form
|
|
|
|
fields = ('file', 'name', 'localName', 'hardware', 'ISOLocal', 'version', 'firmware')
|
|
d = {'pack[{}]'.format(f): j[f] for f in fields}
|
|
|
|
d['pack[mobile][name]'] = j['mobile']['name']
|
|
d['pack[mobile][version]'] = j['mobile']['version']
|
|
|
|
return d
|
|
|
|
|
|
def get_lang_metadata(lang_pack):
|
|
mo_filename = None
|
|
|
|
# Open up the lang_pack as a pbpack. The first entry is the STRINGS values, which is a mo
|
|
# file. Write this mo file out to a temporary file and use polib to parse out the metadata.
|
|
#
|
|
# The resulting dictionary will look something like the following...
|
|
#
|
|
# {u'Content-Transfer-Encoding': u'8bit',
|
|
# u'Content-Type': u'text/plain; charset=UTF-8',
|
|
# u'Language': u'fr_FR',
|
|
# u'MIME-Version': u'1.0',
|
|
# u'Name': u'Fran\xe7ais',
|
|
# u'POT-Creation-Date': u'2016-06-28 15:24-0400',
|
|
# u'Project-Id-Version': u'33.0',
|
|
# u'Report-Msgid-Bugs-To': u'',
|
|
# u'X-Generator': u'POEditor.com'}
|
|
try:
|
|
with open(lang_pack, 'rb') as f:
|
|
pack = pbpack.ResourcePack.deserialize(f, is_system=False)
|
|
with tempfile.NamedTemporaryFile(delete=False) as mo_file:
|
|
mo_filename = mo_file.name
|
|
|
|
# RESOURCE_ID_STRINGS is the 0th resource in the pb pack. Grab the data and write
|
|
# it to a file.
|
|
content_index = pack.table_entries[0].content_index
|
|
if len(pack.contents[content_index]) == 0:
|
|
# Assume this is an english pack
|
|
return {u'Language': u'en_US',
|
|
u'Name': u'English',
|
|
u'Project-Id-Version': u'1.0'}
|
|
|
|
mo_file.write(pack.contents[content_index])
|
|
|
|
mo_object = polib.mofile(mo_filename)
|
|
finally:
|
|
os.remove(mo_filename)
|
|
|
|
metadata = mo_object.metadata
|
|
|
|
# Validate the version field just to be sure
|
|
assert 'Project-Id-Version' in metadata
|
|
version_parts = metadata['Project-Id-Version'].split('.')
|
|
assert len(version_parts) == 2
|
|
int(version_parts[0]) # Just make sure it can be converted to a valid integer
|
|
|
|
return metadata
|
|
|
|
|
|
def upload_pack_to_s3(lang_pack):
|
|
r = requests.get('{}/admin/packs/sign'.format(lp_url),
|
|
params={'type': '', 'name': os.path.basename(lang_pack)},
|
|
auth=lp_auth)
|
|
assert_ok(r)
|
|
|
|
s3_upload_info = r.json()
|
|
|
|
with open(lang_pack, 'rb') as f:
|
|
r = requests.put(s3_upload_info['signed'], f)
|
|
assert_ok(r)
|
|
|
|
return s3_upload_info['url']
|
|
|
|
|
|
def post_edit_to_lp(pack_json):
|
|
post_data = pack_json_to_post_data(pack_json)
|
|
|
|
r = requests.post('{}/admin/packs/{}/edit'.format(lp_url, pack_json['id']),
|
|
data=post_data,
|
|
auth=lp_auth)
|
|
assert_ok(r)
|
|
|
|
|
|
def create_new_pack_on_lp(pack_json):
|
|
post_data = pack_json_to_post_data(pack_json)
|
|
|
|
r = requests.post('{}/admin/packs/add'.format(lp_url),
|
|
data=post_data,
|
|
auth=lp_auth)
|
|
assert_ok(r)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('hardware')
|
|
parser.add_argument('lang_pack')
|
|
parser.add_argument('--production', action='store_true')
|
|
parser.add_argument('--allow_new', action='store_true')
|
|
parser.add_argument('--name', default=None)
|
|
parser.add_argument('--fw_version', default='4.0.0')
|
|
|
|
args = parser.parse_args()
|
|
|
|
global lp_url
|
|
if args.production:
|
|
lp_url = LP_URLS["production"]
|
|
else:
|
|
lp_url = LP_URLS["staging"]
|
|
|
|
metadata = get_lang_metadata(args.lang_pack)
|
|
|
|
is_new = False
|
|
|
|
pack_json = find_existing_pack(args.hardware, metadata['Language'])
|
|
|
|
if pack_json is None:
|
|
if not args.allow_new:
|
|
print "No existing pack found"
|
|
return 1
|
|
|
|
if args.name is None:
|
|
print "Name is required for new packs"
|
|
return 1
|
|
|
|
pack_json = create_new_pack_json(args.hardware, args.name, args.fw_version, metadata)
|
|
is_new = True
|
|
|
|
# Update the pack with the new information
|
|
pack_json['version'] = metadata['Project-Id-Version'].split('.')[0]
|
|
pack_json['file'] = upload_pack_to_s3(args.lang_pack)
|
|
|
|
if is_new:
|
|
create_new_pack_on_lp(pack_json)
|
|
else:
|
|
post_edit_to_lp(pack_json)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|