def test_chmod_cymbal(): """change mode of a single directory""" # setup d1 = 'd1' mkdir(d1) # run test for i in range(8): chmod(i, d1) # 0o040000 represents a directory assert to_path(d1).stat().st_mode == 0o040000 + i assert getmod(d1) == i chmod(8 * i, d1) assert to_path(d1).stat().st_mode == 0o040000 + 8 * i assert getmod(d1) == 8 * i chmod(8 * 8 * i, d1) assert to_path(d1).stat().st_mode == 0o040000 + 8 * 8 * i assert getmod(d1) == 8 * 8 * i # cleanup rm(d1)
def test_chmod_ground(): """change mode of a single file""" # setup f1 = 'f1' touch(f1) # run test for i in range(8): chmod(i, f1) # 0o100000 represents a regular file assert to_path(f1).stat().st_mode == 0o100000 + i assert getmod(f1) == i chmod(8 * i, f1) assert to_path(f1).stat().st_mode == 0o100000 + 8 * i assert getmod(f1) == 8 * i chmod(8 * 8 * i, f1) assert to_path(f1).stat().st_mode == 0o100000 + 8 * 8 * i assert getmod(f1) == 8 * 8 * i # cleanup rm(f1)
def test_chmod_gathering(): """change mode of a multiple files""" # setup f1 = to_path('f1') f2 = to_path('f2') touch(f1, f2) # run test for i in range(8): chmod(i, f1, f2) # 0o100000 represents a regular file assert f1.stat().st_mode == 0o100000 + i assert getmod(f1) == i assert f2.stat().st_mode == 0o100000 + i assert getmod(f2) == i chmod(8 * i, f1, f2) assert f1.stat().st_mode == 0o100000 + 8 * i assert getmod(f1) == 8 * i assert f2.stat().st_mode == 0o100000 + 8 * i assert getmod(f2) == 8 * i chmod(8 * 8 * i, f1, f2) assert f1.stat().st_mode == 0o100000 + 8 * 8 * i assert f2.stat().st_mode == 0o100000 + 8 * 8 * i assert getmod(f1) == 8 * 8 * i assert getmod(f2) == 8 * 8 * i # cleanup rm(f1, f2)
def test_chmod_quisling(): """change mode of a multiple directories""" # setup d1 = to_path('d1') d2 = to_path('d2') mkdir(d1, d2) # run test for i in range(8): chmod(i, [d1, d2]) # 0o040000 represents a directory assert d1.stat().st_mode == 0o040000 + i assert getmod(d1) == i assert d2.stat().st_mode == 0o040000 + i assert getmod(d2) == i chmod(8 * i, d1, d2) assert d1.stat().st_mode == 0o040000 + 8 * i assert getmod(d1) == 8 * i assert d2.stat().st_mode == 0o040000 + 8 * i assert getmod(d2) == 8 * i chmod(8 * 8 * i, d1, d2) assert d1.stat().st_mode == 0o040000 + 8 * 8 * i assert d2.stat().st_mode == 0o040000 + 8 * 8 * i assert getmod(d1) == 8 * 8 * i assert getmod(d2) == 8 * 8 * i # cleanup rm(d1)
def read(self, name=None, path=None): """Recursively read configuration files. name (str): Name of desired configuration. Passed only when reading the top level settings file. Default is the default configuration as specified in the settings file, or if that is not specified then the first configuration given is used. path (str): Full path to settings file. Should not be given for the top level settings file (SETTINGS_FILE in CONFIG_DIR). """ if path: settings = PythonFile(path).run() parent = path.parent includes = Collection(settings.get(INCLUDE_SETTING)) else: # this is the generic settings file parent = self.config_dir if not parent.exists(): # config dir does not exist, create and populate it narrate('creating config directory:', str(parent)) parent.mkdir(mode=0o700, parents=True, exist_ok=True) for name, contents in [ (SETTINGS_FILE, INITIAL_SETTINGS_FILE_CONTENTS), ('root', INITIAL_ROOT_CONFIG_FILE_CONTENTS), ('home', INITIAL_HOME_CONFIG_FILE_CONTENTS), ]: path = parent / name path.write_text(contents) path.chmod(0o600) output( f'Configuration directory created: {parent!s}.', 'Includes example settings files. Edit them to suit your needs.', 'Search for and replace any fields delimited with << and >>.', 'Delete any configurations you do not need.', 'Generally you will use either home or root, but not both.', sep='\n') done() path = PythonFile(parent, SETTINGS_FILE) settings_filename = path.path settings = path.run() config = get_config(name, settings, self.composite_config_allowed) settings['config_name'] = config self.config_name = config includes = Collection(settings.get(INCLUDE_SETTING)) includes = [config] + list(includes.values()) if settings.get('passphrase'): if getmod(path) & 0o077: warn("file permissions are too loose.", culprit=path) codicil(f"Recommend running: chmod 600 {path!s}") self.settings.update(settings) for include in includes: path = to_path(parent, include) self.read(path=path) # default src_dirs if not given if not self.settings.get('src_dirs'): self.settings['src_dirs'] = [] # default archive if not given if 'archive' not in self.settings: if not 'prefix' in self.settings: self.settings[ 'prefix'] = '{host_name}-{user_name}-{config_name}-' self.settings['archive'] = self.settings['prefix'] + '{{now}}'
def read(self, name=None, path=None): """Recursively read configuration files. name (str): Name of desired configuration. Passed only when reading the top level settings file. Default is the default configuration as specified in the settings file, or if that is not specified then the first configuration given is used. path (str): Full path to settings file. Should not be given for the top level settings file (SETTINGS_FILE in CONFIG_DIR). """ if path: settings = PythonFile(path).run() parent = path.parent includes = Collection( settings.get(INCLUDE_SETTING), split_lines, comment="#", strip=True, cull=True, ) else: # this is the generic settings file parent = self.config_dir if not parent.exists(): # config dir does not exist, create and populate it narrate("creating config directory:", str(parent)) parent.mkdir(mode=0o700, parents=True, exist_ok=True) for name, contents in [ (SETTINGS_FILE, INITIAL_SETTINGS_FILE_CONTENTS), ("root", INITIAL_ROOT_CONFIG_FILE_CONTENTS), ("home", INITIAL_HOME_CONFIG_FILE_CONTENTS), ]: path = parent / name path.write_text(contents) path.chmod(0o600) output( f"Configuration directory created: {parent!s}.", "Includes example settings files. Edit them to suit your needs.", "Search for and replace any fields delimited with << and >>.", "Delete any configurations you do not need.", "Generally you will use either home or root, but not both.", sep="\n", ) done() path = PythonFile(parent, SETTINGS_FILE) self.settings_filename = path.path settings = path.run() config = get_config(name, settings, self.composite_config_response, self.show_config_name) settings["config_name"] = config self.config_name = config includes = Collection(settings.get(INCLUDE_SETTING)) includes = [config] + list(includes.values()) if settings.get("passphrase"): if getmod(path) & 0o077: warn("file permissions are too loose.", culprit=path) codicil(f"Recommend running: chmod 600 {path!s}") self.settings.update(settings) # read include files, if any are specified for include in includes: path = to_path(parent, include) self.read(path=path)
def read_config(self, name=None, path=None, queue=None): """Recursively read configuration files. name (str): Name of desired configuration. Passed only when reading the top level settings file. Default is the default configuration as specified in the settings file, or if that is not specified then the first configuration given is used. path (str): Full path to settings file. Should not be given for the top level settings file (SETTINGS_FILE in CONFIG_DIR). """ if path: # we are reading an include file settings = PythonFile(path).run() parent = path.parent includes = Collection( settings.get(INCLUDE_SETTING), split_lines, comment="#", strip=True, cull=True, ) else: # this is the base-level settings file parent = self.config_dir if not parent.exists(): # config dir does not exist, create and populate it narrate("creating config directory:", str(parent)) parent.mkdir(mode=0o700, parents=True, exist_ok=True) for fname, contents in [ (SETTINGS_FILE, INITIAL_SETTINGS_FILE_CONTENTS), ("root", INITIAL_ROOT_CONFIG_FILE_CONTENTS), ("home", INITIAL_HOME_CONFIG_FILE_CONTENTS), ]: path = parent / fname path.write_text(contents) path.chmod(0o600) output( f"Configuration directory created: {parent!s}.", "Includes example settings files. Edit them to suit your needs.", "Search for and replace any fields delimited with ⟪ and ⟫.", "Delete any configurations you do not need.", "Generally you will use either home or root, but not both.", sep="\n", ) done() # read the shared settings file path = PythonFile(parent, SETTINGS_FILE) self.settings_filename = path.path settings = path.run() # initialize the config queue if not queue: # this is a request through the API queue = ConfigQueue() if queue.uninitialized: queue.initialize(name, settings) config = queue.get_active_config() self.configs = queue.configs self.log_command = queue.log_command # save config name settings["config_name"] = config self.config_name = config if not config: # this happens on composite configs for commands that do not # need access to a specific config, such as help and configs self.settings.update(settings) return # get includes includes = Collection(settings.get(INCLUDE_SETTING)) includes = [config] + list(includes.values()) if settings.get("passphrase"): if getmod(path) & 0o077: warn("file permissions are too loose.", culprit=path) codicil(f"Recommend running: chmod 600 {path!s}") self.settings.update(settings) # read include files, if any are specified for include in includes: path = to_path(parent, include) self.read_config(path=path)