<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Poof: List and uninstall/remove OS X packages
# Copyright (c) 2011-2016 <NAME> <<EMAIL>>
#

"""Poof is a command line utility to list and uninstall/remove OS X packages.

*NO WARRANTY* DON'T BLAME ME if you destroy your installation!
NEVER REMOVE com.apple.* packages unless you know what you are doing.

How it works:

It first removes all files and directories declared by the package and
then forget the metadata (the receipt data).

Usage:

List packages (but ignore all from Apple).

    $ ./poof.py | grep -v com.apple.pkg
    com.accessagility.wifiscanner
    com.adobe.pkg.FlashPlayer
    com.amazon.Kindle
    com.christiankienle.CoreDataEditor
    com.ea.realracing2.mac.bv
    com.google.pkg.GoogleVoiceAndVideo
    com.google.pkg.Keystone
    com.Growl.GrowlHelperApp
    com.lightheadsw.caffeine
    com.Logitech.Control Center.pkg
    ...

Remove FlashPlayer (com.adobe.pkg.FlashPlayer).

    $ sudo ./poof.py com.adobe.pkg.FlashPlayer
    ...
    Forgot package 'com.adobe.pkg.FlashPlayer' on '/'.
"""

from subprocess import Popen, PIPE
import sys, os

class Shell(object):
    def __getattribute__(self, attr):
        return Command(attr)

class Command(object):
    def __init__(self, command):
        self.command = command

    def __call__(self, params=None):
        args = [self.command]
        if params:
            args += params.split()
        return self.run(args)
    
    def run(self, args):
        p = Popen(args, stdout=PIPE, stderr=PIPE)
        out, err = p.communicate()
        if p.returncode == 0:
            return True, out.strip().split('\n')
        else:
            return False, err.strip().split('\n')

def package_list():
    sh = Shell()
    sts, out = sh.pkgutil('--pkgs')
    return out

def package_info(package_id):
    sh = Shell()
    ok, info = sh.pkgutil('--pkg-info ' + package_id)
    if ok == False:
        raise IOError, 'Unknown package or name mispelled'
    info = [x.split(': ') for x in info]
    return dict(info)

def package_files(package_id):
    sh = Shell()
    ok, files = sh.pkgutil('--files ' + package_id)
    ok, dirs = sh.pkgutil('--only-dirs --files ' + package_id)
    # Files minus directories
    files = list(set(files) - set(dirs))
    # Guess AppStore receipt
    for dir in dirs:
        if dir.endswith('.app'):
            dirs.append(dir + '/Contents/_MASReceipt')
            files.append(dir + '/Contents/_MASReceipt/receipt')
            break
    return files, dirs

def package_forget(package_id):
    sh = Shell()
    ok, msg = sh.pkgutil('--verbose --forget ' + package_id)
    return msg

def package_remove(package_id, force=True, verbose=False):
    info = package_info(package_id)
    prefix = info['volume']
    if info['location']:
        prefix += info['location'] + os.sep
    files, dirs = package_files(package_id)<commit_msg>Use pkgutil's --only-files to get files.<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Poof: List and uninstall/remove OS X packages
# Copyright (c) 2011-2016 <NAME> <<EMAIL>>
#

"""Poof is a command line utility to list and uninstall/remove OS X packages.

*NO WARRANTY* DON'T BLAME ME if you destroy your installation!
NEVER REMOVE com.apple.* packages unless you know what you are doing.

How it works:

It first removes all files and directories declared by the package and
then forget the metadata (the receipt data).

Usage:

List packages (but ignore all from Apple).

    $ ./poof.py | grep -v com.apple.pkg
    com.accessagility.wifiscanner
    com.adobe.pkg.FlashPlayer
    com.amazon.Kindle
    com.christiankienle.CoreDataEditor
    com.ea.realracing2.mac.bv
    com.google.pkg.GoogleVoiceAndVideo
    com.google.pkg.Keystone
    com.Growl.GrowlHelperApp
    com.lightheadsw.caffeine
    com.Logitech.Control Center.pkg
    ...

Remove FlashPlayer (com.adobe.pkg.FlashPlayer).

    $ sudo ./poof.py com.adobe.pkg.FlashPlayer
    ...
    Forgot package 'com.adobe.pkg.FlashPlayer' on '/'.
"""

from subprocess import Popen, PIPE
import sys, os

class Shell(object):
    def __getattribute__(self, attr):
        return Command(attr)

class Command(object):
    def __init__(self, command):
        self.command = command

    def __call__(self, params=None):
        args = [self.command]
        if params:
            args += params.split()
        return self.run(args)
    
    def run(self, args):
        p = Popen(args, stdout=PIPE, stderr=PIPE)
        out, err = p.communicate()
        if p.returncode == 0:
            return True, out.strip().split('\n')
        else:
            return False, err.strip().split('\n')

def package_list():
    sh = Shell()
    sts, out = sh.pkgutil('--pkgs')
    return out

def package_info(package_id):
    sh = Shell()
    ok, info = sh.pkgutil('--pkg-info ' + package_id)
    if ok == False:
        raise IOError, 'Unknown package or name mispelled'
    info = [x.split(': ') for x in info]
    return dict(info)

def package_files(package_id):
    sh = Shell()
    ok, files = sh.pkgutil('--only-files --files ' + package_id)
    ok, dirs = sh.pkgutil('--only-dirs --files ' + package_id)
    # Guess AppStore receipt
    for dir in dirs:
        if dir.endswith('.app'):
            dirs.append(dir + '/Contents/_MASReceipt')
            files.append(dir + '/Contents/_MASReceipt/receipt')
            break
    return files, dirs

def package_forget(package_id):
    sh = Shell()
    ok, msg = sh.pkgutil('--verbose --forget ' + package_id)
    return msg

def package_remove(package_id, force=True, verbose=False):
    info = package_info(package_id)
    prefix = info['volume']
    if info['location']:
        prefix += info['location'] + os.sep
    files, dirs = package_files(package_id)
{'fraction_non_alphanumeric': 0.12493501992722232, 'fraction_numerical': 0.003812164269623982, 'mean_word_length': 2.7142857142857144, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6279712', 'n_tokens_mistral': 1931, 'n_tokens_neox': 1861, 'n_words': 509}