import re
import json
import base64
import codecs
import os.path
import asyncio
import subprocess


_PREFIX = 'docker-credential-'


def read_config():
    path = os.path.expanduser('~/.docker/config.json')
    if not os.path.exists(path):
        return {}
    with codecs.open(path, encoding='utf-8') as f:
        json_data = f.read()
    return json.loads(json_data)


async def _read_creds(creds_store, server):
    if not re.match(r'^\w+$', creds_store, re.ASCII):
        raise ValueError('Invalid credsStore: {!r}'.format(creds_store))

    proc = await asyncio.create_subprocess_exec(
        _PREFIX + creds_store, 'get',
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate(server.encode('ascii'))
    if proc.returncode != 0:
        return None
    else:
        data = json.loads(stdout)
        return {
            'Username': data['Username'],
            'Password': data['Secret'],
            'ServerAddress': server,
        }


def _decode_auth(auth_data, server):
    auth_data_decoded = base64.b64decode(auth_data).decode('utf-8')
    username, _, password = auth_data_decoded.partition(':')
    return {
        'Username': username,
        'Password': password,
        'ServerAddress': server,
    }


async def resolve_auth(config, server):
    config_auths = config.get('auths')
    if config_auths is None:
        return None

    server_auth = config_auths.get(server)
    if server_auth is not None:
        auth_data = server_auth.get('auth')
        if auth_data is not None:
            return _decode_auth(auth_data, server)

    creds_store = config.get('credsStore')
    if creds_store is not None:
        return await _read_creds(creds_store, server)

    return None


def server_name(image_name):
    registry, _, name = image_name.partition('/')
    if not name:
        return 'docker.io'
    else:
        return registry


def encode_header(auth):
    json_data = json.dumps(auth)
    return base64.urlsafe_b64encode(json_data.encode('ascii'))

[((349, 370), 'json.loads', 'json.loads', (['json_data'], {}), '(json_data)\n', (359, 370), False, 'import json\n'), ((2004, 2020), 'json.dumps', 'json.dumps', (['auth'], {}), '(auth)\n', (2014, 2020), False, 'import json\n'), ((267, 302), 'codecs.open', 'codecs.open', (['path'], {'encoding': '"""utf-8"""'}), "(path, encoding='utf-8')\n", (278, 302), False, 'import codecs\n'), ((428, 469), 're.match', 're.match', (['"""^\\\\w+$"""', 'creds_store', 're.ASCII'], {}), "('^\\\\w+$', creds_store, re.ASCII)\n", (436, 469), False, 'import re\n'), ((562, 698), 'asyncio.create_subprocess_exec', 'asyncio.create_subprocess_exec', (['(_PREFIX + creds_store)', '"""get"""'], {'stdin': 'subprocess.PIPE', 'stdout': 'subprocess.PIPE', 'stderr': 'subprocess.PIPE'}), "(_PREFIX + creds_store, 'get', stdin=\n    subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n", (592, 698), False, 'import asyncio\n'), ((875, 893), 'json.loads', 'json.loads', (['stdout'], {}), '(stdout)\n', (885, 893), False, 'import json\n'), ((1103, 1130), 'base64.b64decode', 'base64.b64decode', (['auth_data'], {}), '(auth_data)\n', (1119, 1130), False, 'import base64\n')]