Exemplo n.º 1
0
def _ParseKey(target_object, key):
    """Parses the key value according target object type.

  Args:
    target_object: the target object.
    key: string, the key of object.

  Returns:
    If object is dict, returns key itself. If object is list, returns int(key).

  Raises:
    ios_errors.PlistError: when object is list and key is not int, or object is
      not list/dict.
  """
    if isinstance(target_object, dict):
        return key
    if isinstance(target_object, list):
        try:
            return int(key)
        except ValueError:
            raise ios_errors.PlistError(
                'The key %s is invaild index of list(array) object %s.' %
                (key, target_object))
    raise ios_errors.PlistError('The object %s is not dict or list.' %
                                target_object)
Exemplo n.º 2
0
def _SetPlistFieldByPlistBuddy(plist_path, field, value):
    """Set field with provided value in .plist file.

  Args:
    plist_path: string, the path of plist file.
    field: string, the field consist of property key names delimited by
      colons. List(array) items are specified by a zero-based integer index.
      Examples
        :CFBundleShortVersionString
        :CFBundleDocumentTypes:2:CFBundleTypeExtensions
    value: a object, the value of the field to be added. It can be integer,
        bool, string, array, dict.

  Raises:
    ios_errors.PlistError: the field does not exist in the .plist file's dict.
  """
    command = [
        PLIST_BUDDY, '-c',
        'Set :"%s" "%s"' % (field, value), plist_path
    ]
    try:
        subprocess.check_output(command, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        raise ios_errors.PlistError('Failed to set field %s in plist %s: %s' %
                                    (field, plist_path, e.output))
Exemplo n.º 3
0
def _GetPlistFieldByPlistBuddy(plist_path, field):
    """View specific field in the .plist file by PlistBuddy tool.

  Args:
    plist_path: string, the path of plist file.
    field: string, the field consist of property key names delimited by
      colons. List(array) items are specified by a zero-based integer index.
      Examples
        :CFBundleShortVersionString
        :CFBundleDocumentTypes:2:CFBundleTypeExtensions

  Returns:
    the object of the plist's field.

  Raises:
    ios_errors.PlistError: the field does not exist in the plist dict.
  """
    command = [PLIST_BUDDY, '-c', 'Print :"%s"' % field, plist_path]
    try:
        return subprocess.check_output(command,
                                       stderr=subprocess.STDOUT,
                                       text=True).strip()
    except subprocess.CalledProcessError as e:
        raise ios_errors.PlistError('Failed to get field %s in plist %s: %s',
                                    field, plist_path, e.output)
Exemplo n.º 4
0
def _GetObjectWithField(target_object, field):
    """Gets sub object of the object with field.

  Args:
    target_object: the target object.
    field: string, the field consist of property key names delimited by
        colons. List(array) items are specified by a zero-based integer index.
        Examples
          :CFBundleShortVersionString
          :CFBundleDocumentTypes:2:CFBundleTypeExtensions

  Returns:
    a object of the target object's field. If field is empty, returns the
      target object itself.

  Raises:
    ios_errors.PlistError: the field does not exist in the object or the field
      is invaild.
  """
    if not field:
        return target_object
    current_object = target_object
    for key in field.split(':'):
        try:
            current_object = current_object[_ParseKey(current_object, key)]
        except ios_errors.PlistError as e:
            raise e
        except (KeyError, IndexError):
            raise ios_errors.PlistError(
                'The field %s can not be found in the target object. '
                'The object content is %s' % (field, current_object))
    return current_object
Exemplo n.º 5
0
    def DeletePlistField(self, field):
        """Delete field in .plist file.

    Args:
      field: string, the field consist of property key names delimited by
        colons. List(array) items are specified by a zero-based integer index.
        Examples
          :CFBundleShortVersionString
          :CFBundleDocumentTypes:2:CFBundleTypeExtensions

    Raises:
      ios_errors.PlistError: the field does not exist in the .plist file's dict.
    """
        with open(self._plist_file_path, 'rb') as plist_file:
            plist_root_object = plistlib.load(plist_file)
        keys_in_field = field.rsplit(':', 1)
        if len(keys_in_field) == 1:
            key = field
            target_object = plist_root_object
        else:
            key = keys_in_field[1]
            target_object = _GetObjectWithField(plist_root_object,
                                                keys_in_field[0])

        try:
            del target_object[_ParseKey(target_object, key)]
        except ios_errors.PlistError as e:
            raise e
        except (KeyError, IndexError):
            raise ios_errors.PlistError(
                'Failed to delete key %s from object %s.' %
                (key, target_object))

        with open(self._plist_file_path, 'wb') as plist_file:
            plistlib.dump(plist_root_object, plist_file)
Exemplo n.º 6
0
    def SetPlistField(self, field, value):
        """Set field with provided value in .plist file.

    Args:
      field: string, the field consist of property key names delimited by
        colons. List(array) items are specified by a zero-based integer index.
        Examples
          :CFBundleShortVersionString
          :CFBundleDocumentTypes:2:CFBundleTypeExtensions
      value: a object, the value of the field to be added. It can be integer,
          bool, string, array, dict.

    Raises:
      ios_errors.PlistError: the field does not exist in the .plist file's dict.
    """
        if self._plistlib_module is None:
            _SetPlistFieldByPlistBuddy(self._plist_file_path, field, value)
            return
        if not field:
            self._plistlib_module.writePlist(value, self._plist_file_path)
            return

        if os.path.exists(self._plist_file_path):
            plist_root_object = self._plistlib_module.readPlist(
                self._plist_file_path)
        else:
            plist_root_object = {}
        keys_in_field = field.rsplit(':', 1)
        if len(keys_in_field) == 1:
            key = field
            target_object = plist_root_object
        else:
            key = keys_in_field[1]
            target_object = _GetObjectWithField(plist_root_object,
                                                keys_in_field[0])
        try:
            target_object[_ParseKey(target_object, key)] = value
        except ios_errors.PlistError as e:
            raise e
        except (KeyError, IndexError):
            raise ios_errors.PlistError(
                'Failed to set key %s from object %s.' % (key, target_object))
        self._plistlib_module.writePlist(plist_root_object,
                                         self._plist_file_path)
Exemplo n.º 7
0
def _DeletePlistFieldByPlistBuddy(plist_path, field):
    """Delete field in .plist file.

  Args:
    plist_path: string, the path of plist file.
    field: string, the field consist of property key names delimited by
      colons. List(array) items are specified by a zero-based integer index.
      Examples
        :CFBundleShortVersionString
        :CFBundleDocumentTypes:2:CFBundleTypeExtensions

  Raises:
    ios_errors.PlistError: the field does not exist in the .plist file's dict.
  """
    command = [PLIST_BUDDY, '-c', 'Delete :"%s"' % field, plist_path]
    try:
        subprocess.check_output(command, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        raise ios_errors.PlistError(
            'Failed to delete field %s in plist %s: %s' %
            (field, plist_path, e.output))