def __init__(self, path, budget, device=None):
        """
        Load YNAB budget from the specified path.

        Parameters
        ----------
        path : str
            Path to the budget root, e.g. ~/Documents/YNAB for local budgets or ~/Dropbox/YNAB
            for cloud-synced budgets.
        budget : str
            Budget name.
        device : str (optional)
            Device name -- this corresponds to the .ydevice files in the "devices" folder.
            Can be either A, B, C, ... or a full device name (hostname for desktops). The
            full name can be found in .ydevice files in the "devices" folder. If this
            parameter is not specified, the device with the latest modification time of
            the budget file will be selected.
        """
        root = os.path.abspath(os.path.expanduser(path))
        pattern = re.compile('^' + re.escape(budget) + r'~[A-F0-9]{8}\.ynab4$')
        folders = list(filter(pattern.match, os.listdir(root)))
        if not folders:
            raise RuntimeError('Budget {!r} not found at: {}'.format(budget, path))
        if len(folders) > 1:
            raise RuntimeError('Multiple budgets {!r} found at: {}'.format(budget, path))
        budget_folder = os.path.join(root, folders.pop())
        meta = os.path.join(budget_folder, 'Budget.ymeta')
        with open(meta, 'r') as f:
            data_folder = os.path.join(budget_folder, json.load(f)['relativeDataFolderName'])
        devices_folder = os.path.join(data_folder, 'devices')
        device_files = filter(re.compile(r'^[A-Z]\.ydevice$').match, os.listdir(devices_folder))
        devices = []
        for device_file in device_files:
            with open(os.path.join(devices_folder, device_file), 'r') as f:
                device_data = Device(json.load(f), strict=False)
            guid = device_data.deviceGUID
            budget_file = os.path.join(data_folder, guid, 'Budget.yfull')
            if os.path.isfile(budget_file):
                devices.append({
                    'id': device_data.shortDeviceId,
                    'name': device_data.friendlyName,
                    'file': budget_file,
                    'mtime': os.stat(budget_file).st_mtime,
                    'full': device_data.hasFullKnowledge
                })
        if not devices:
            raise RuntimeError('No valid devices found for {!r} at: {}'.format(budget, path))
        if device is None:
            devices = [d for d in devices if d['full']]
            if not devices:
                raise RuntimeError('No devices with full knowledge found')
            device = max(devices, key=lambda d: d['mtime'])
        else:
            try:
                if device in string.ascii_uppercase:
                    device = [d for d in devices if d['id'] == device].pop()
                else:
                    device = [d for d in devices if d['name'] == device].pop()
                if not device['full']:
                    warnings.warn('Device {!r} does not have full knowledge'.format(d['name']))
            except __HOLE__:
                raise RuntimeError('No device {!r} for {!r} at: {}'.format(device, budget, path))
        self._path = device['file']
        self._device = device['name']
        with open(self._path, 'r') as f:
            self._init_data(json.load(f))
dataset/ETHPy150Open aldanor/pynab/ynab/ynab.py/YNAB.__init__