# This file was automatically generated by SWIG (http://www.swig.org).
# Version 2.0.7
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.



from sys import version_info
if version_info >= (2,6,0):
    def swig_import_helper():
        from os.path import dirname
        import imp
        fp = None
        try:
            fp, pathname, description = imp.find_module('_capng', [dirname(__file__)])
        except ImportError:
            import _capng
            return _capng
        if fp is not None:
            try:
                _mod = imp.load_module('_capng', fp, pathname, description)
            finally:
                fp.close()
            return _mod
    _capng = swig_import_helper()
    del swig_import_helper
else:
    import _capng
del version_info
try:
    _swig_property = property
except NameError:
    pass # Python < 2.2 doesn't have 'property'.
def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
    if (name == "thisown"): return self.this.own(value)
    if (name == "this"):
        if type(value).__name__ == 'SwigPyObject':
            self.__dict__[name] = value
            return
    method = class_type.__swig_setmethods__.get(name,None)
    if method: return method(self,value)
    if (not static):
        self.__dict__[name] = value
    else:
        raise AttributeError("You cannot add attributes to %s" % self)

def _swig_setattr(self,class_type,name,value):
    return _swig_setattr_nondynamic(self,class_type,name,value,0)

def _swig_getattr(self,class_type,name):
    if (name == "thisown"): return self.this.own()
    method = class_type.__swig_getmethods__.get(name,None)
    if method: return method(self)
    raise AttributeError(name)

def _swig_repr(self):
    try: strthis = "proxy of " + self.this.__repr__()
    except: strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)

try:
    _object = object
    _newclass = 1
except AttributeError:
    class _object : pass
    _newclass = 0


CAP_CHOWN = _capng.CAP_CHOWN
CAP_DAC_OVERRIDE = _capng.CAP_DAC_OVERRIDE
CAP_DAC_READ_SEARCH = _capng.CAP_DAC_READ_SEARCH
CAP_FOWNER = _capng.CAP_FOWNER
CAP_FSETID = _capng.CAP_FSETID
CAP_KILL = _capng.CAP_KILL
CAP_SETGID = _capng.CAP_SETGID
CAP_SETUID = _capng.CAP_SETUID
CAP_SETPCAP = _capng.CAP_SETPCAP
CAP_LINUX_IMMUTABLE = _capng.CAP_LINUX_IMMUTABLE
CAP_NET_BIND_SERVICE = _capng.CAP_NET_BIND_SERVICE
CAP_NET_BROADCAST = _capng.CAP_NET_BROADCAST
CAP_NET_ADMIN = _capng.CAP_NET_ADMIN
CAP_NET_RAW = _capng.CAP_NET_RAW
CAP_IPC_LOCK = _capng.CAP_IPC_LOCK
CAP_IPC_OWNER = _capng.CAP_IPC_OWNER
CAP_SYS_MODULE = _capng.CAP_SYS_MODULE
CAP_SYS_RAWIO = _capng.CAP_SYS_RAWIO
CAP_SYS_CHROOT = _capng.CAP_SYS_CHROOT
CAP_SYS_PTRACE = _capng.CAP_SYS_PTRACE
CAP_SYS_PACCT = _capng.CAP_SYS_PACCT
CAP_SYS_ADMIN = _capng.CAP_SYS_ADMIN
CAP_SYS_BOOT = _capng.CAP_SYS_BOOT
CAP_SYS_NICE = _capng.CAP_SYS_NICE
CAP_SYS_RESOURCE = _capng.CAP_SYS_RESOURCE
CAP_SYS_TIME = _capng.CAP_SYS_TIME
CAP_SYS_TTY_CONFIG = _capng.CAP_SYS_TTY_CONFIG
CAP_MKNOD = _capng.CAP_MKNOD
CAP_LEASE = _capng.CAP_LEASE
CAP_AUDIT_WRITE = _capng.CAP_AUDIT_WRITE
CAP_AUDIT_CONTROL = _capng.CAP_AUDIT_CONTROL
CAP_SETFCAP = _capng.CAP_SETFCAP
CAP_MAC_OVERRIDE = _capng.CAP_MAC_OVERRIDE
CAP_MAC_ADMIN = _capng.CAP_MAC_ADMIN
CAP_SYSLOG = _capng.CAP_SYSLOG
CAP_WAKE_ALARM = _capng.CAP_WAKE_ALARM
CAP_LAST_CAP = _capng.CAP_LAST_CAP
CAPNG_DROP = _capng.CAPNG_DROP
CAPNG_ADD = _capng.CAPNG_ADD
CAPNG_EFFECTIVE = _capng.CAPNG_EFFECTIVE
CAPNG_PERMITTED = _capng.CAPNG_PERMITTED
CAPNG_INHERITABLE = _capng.CAPNG_INHERITABLE
CAPNG_BOUNDING_SET = _capng.CAPNG_BOUNDING_SET
CAPNG_SELECT_CAPS = _capng.CAPNG_SELECT_CAPS
CAPNG_SELECT_BOUNDS = _capng.CAPNG_SELECT_BOUNDS
CAPNG_SELECT_BOTH = _capng.CAPNG_SELECT_BOTH
CAPNG_FAIL = _capng.CAPNG_FAIL
CAPNG_NONE = _capng.CAPNG_NONE
CAPNG_PARTIAL = _capng.CAPNG_PARTIAL
CAPNG_FULL = _capng.CAPNG_FULL
CAPNG_PRINT_STDOUT = _capng.CAPNG_PRINT_STDOUT
CAPNG_PRINT_BUFFER = _capng.CAPNG_PRINT_BUFFER
CAPNG_NO_FLAG = _capng.CAPNG_NO_FLAG
CAPNG_DROP_SUPP_GRP = _capng.CAPNG_DROP_SUPP_GRP
CAPNG_CLEAR_BOUNDING = _capng.CAPNG_CLEAR_BOUNDING

def capng_clear(*args):
  return _capng.capng_clear(*args)
capng_clear = _capng.capng_clear

def capng_fill(*args):
  return _capng.capng_fill(*args)
capng_fill = _capng.capng_fill

def capng_setpid(*args):
  return _capng.capng_setpid(*args)
capng_setpid = _capng.capng_setpid

def capng_get_caps_process():
  return _capng.capng_get_caps_process()
capng_get_caps_process = _capng.capng_get_caps_process

def capng_update(*args):
  return _capng.capng_update(*args)
capng_update = _capng.capng_update

def capng_updatev(*args):
  return _capng.capng_updatev(*args)
capng_updatev = _capng.capng_updatev

def capng_apply(*args):
  return _capng.capng_apply(*args)
capng_apply = _capng.capng_apply

def capng_lock():
  return _capng.capng_lock()
capng_lock = _capng.capng_lock

def capng_change_id(*args):
  return _capng.capng_change_id(*args)
capng_change_id = _capng.capng_change_id

def capng_get_caps_fd(*args):
  return _capng.capng_get_caps_fd(*args)
capng_get_caps_fd = _capng.capng_get_caps_fd

def capng_apply_caps_fd(*args):
  return _capng.capng_apply_caps_fd(*args)
capng_apply_caps_fd = _capng.capng_apply_caps_fd

def capng_have_capabilities(*args):
  return _capng.capng_have_capabilities(*args)
capng_have_capabilities = _capng.capng_have_capabilities

def capng_have_capability(*args):
  return _capng.capng_have_capability(*args)
capng_have_capability = _capng.capng_have_capability

def capng_print_caps_numeric(*args):
  return _capng.capng_print_caps_numeric(*args)
capng_print_caps_numeric = _capng.capng_print_caps_numeric

def capng_print_caps_text(*args):
  return _capng.capng_print_caps_text(*args)
capng_print_caps_text = _capng.capng_print_caps_text

def capng_name_to_capability(*args):
  return _capng.capng_name_to_capability(*args)
capng_name_to_capability = _capng.capng_name_to_capability

def capng_capability_to_name(*args):
  return _capng.capng_capability_to_name(*args)
capng_capability_to_name = _capng.capng_capability_to_name
# This file is compatible with both classic and new-style classes.


