コード例 #1
0
ファイル: options.py プロジェクト: GovanifY/PyTouhou
class Options:
    def __init__(self, name, defaults):
        load_paths = list(reversed([os.path.join(directory, '%s.cfg' % name)
                                    for directory
                                    in load_config_paths(name)]))
        self.save_path = os.path.join(save_config_path(name), '%s.cfg' % name)

        self.config = RawConfigParser(defaults)
        self.paths = self.config.read(load_paths)
        self.section = name if self.config.has_section(name) else 'DEFAULT'

    def get(self, option):
        try:
            return self.config.get(self.section, option)
        except NoOptionError:
            return None

    def set(self, option, value):
        if value is not None:
            self.config.set(self.section, option, value)
        else:
            self.config.remove_option(self.section, option)

        defaults = self.config._defaults
        self.config._defaults = None
        with open(self.save_path, 'w') as save_file:
            self.config.write(save_file)
        self.config._defaults = defaults
コード例 #2
0
class Options:
    def __init__(self, name, defaults):
        load_paths = list(
            reversed([
                os.path.join(directory, '%s.cfg' % name)
                for directory in load_config_paths(name)
            ]))
        self.save_path = os.path.join(save_config_path(name), '%s.cfg' % name)

        self.config = RawConfigParser(defaults)
        self.paths = self.config.read(load_paths)
        self.section = name if self.config.has_section(name) else 'DEFAULT'

    def get(self, option):
        try:
            return self.config.get(self.section, option)
        except NoOptionError:
            return None

    def set(self, option, value):
        if value is not None:
            self.config.set(self.section, option, value)
        else:
            self.config.remove_option(self.section, option)

        defaults = self.config._defaults
        self.config._defaults = None
        with open(self.save_path, 'w') as save_file:
            self.config.write(save_file)
        self.config._defaults = defaults
コード例 #3
0
class TestGithubService(TestCase):
    def setUp(self):
        self.config = RawConfigParser()
        self.config.interactive = False
        self.config.add_section('general')
        self.config.add_section('mygithub')
        self.config.set('mygithub', 'service', 'github')
        self.config.set('mygithub', 'github.login', 'tintin')
        self.config.set('mygithub', 'github.username', 'milou')
        self.config.set('mygithub', 'github.password', 't0ps3cr3t')
        self.service_config = ServiceConfig(GithubService.CONFIG_PREFIX,
                                            self.config, 'mygithub')

    def test_token_authorization_header(self):
        self.config.remove_option('mygithub', 'github.password')
        self.config.set('mygithub', 'github.token',
                        '@oracle:eval:echo 1234567890ABCDEF')
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEqual(service.client.session.headers['Authorization'],
                         "token 1234567890ABCDEF")

    def test_default_host(self):
        """ Check that if github.host is not set, we default to github.com """
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEquals("github.com", service.host)

    def test_overwrite_host(self):
        """ Check that if github.host is set, we use its value as host """
        self.config.set('mygithub', 'github.host', 'github.example.com')
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEquals("github.example.com", service.host)

    def test_keyring_service(self):
        """ Checks that the keyring service name """
        keyring_service = GithubService.get_keyring_service(
            self.service_config)
        self.assertEquals("github://[email protected]/milou", keyring_service)

    def test_keyring_service_host(self):
        """ Checks that the keyring key depends on the github host. """
        self.config.set('mygithub', 'github.host', 'github.example.com')
        keyring_service = GithubService.get_keyring_service(
            self.service_config)
        self.assertEquals("github://[email protected]/milou",
                          keyring_service)

    def test_get_repository_from_issue_url__issue(self):
        issue = dict(repos_url="https://github.com/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)

    def test_get_repository_from_issue_url__pull_request(self):
        issue = dict(repos_url="https://github.com/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)

    def test_get_repository_from_issue__enterprise_github(self):
        issue = dict(repos_url="https://github.acme.biz/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)
コード例 #4
0
ファイル: test_github.py プロジェクト: ralphbean/bugwarrior
class TestGithubService(TestCase):

    def setUp(self):
        self.config = RawConfigParser()
        self.config.interactive = False
        self.config.add_section('general')
        self.config.add_section('mygithub')
        self.config.set('mygithub', 'service', 'github')
        self.config.set('mygithub', 'github.login', 'tintin')
        self.config.set('mygithub', 'github.username', 'milou')
        self.config.set('mygithub', 'github.password', 't0ps3cr3t')
        self.service_config = ServiceConfig(
            GithubService.CONFIG_PREFIX, self.config, 'mygithub')

    def test_token_authorization_header(self):
        self.config.remove_option('mygithub', 'github.password')
        self.config.set('mygithub', 'github.token',
                        '@oracle:eval:echo 1234567890ABCDEF')
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEqual(service.client.session.headers['Authorization'],
                         "token 1234567890ABCDEF")

    def test_default_host(self):
        """ Check that if github.host is not set, we default to github.com """
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEquals("github.com", service.host)

    def test_overwrite_host(self):
        """ Check that if github.host is set, we use its value as host """
        self.config.set('mygithub', 'github.host', 'github.example.com')
        service = GithubService(self.config, 'general', 'mygithub')
        self.assertEquals("github.example.com", service.host)

    def test_keyring_service(self):
        """ Checks that the keyring service name """
        keyring_service = GithubService.get_keyring_service(self.service_config)
        self.assertEquals("github://[email protected]/milou", keyring_service)

    def test_keyring_service_host(self):
        """ Checks that the keyring key depends on the github host. """
        self.config.set('mygithub', 'github.host', 'github.example.com')
        keyring_service = GithubService.get_keyring_service(self.service_config)
        self.assertEquals("github://[email protected]/milou", keyring_service)

    def test_get_repository_from_issue_url__issue(self):
        issue = dict(repos_url="https://github.com/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)

    def test_get_repository_from_issue_url__pull_request(self):
        issue = dict(repos_url="https://github.com/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)

    def test_get_repository_from_issue__enterprise_github(self):
        issue = dict(repos_url="https://github.acme.biz/foo/bar")
        repository = GithubService.get_repository_from_issue(issue)
        self.assertEquals("foo/bar", repository)
コード例 #5
0
ファイル: config.py プロジェクト: Perdu/poezio
 def remove_and_save(self, option, section=DEFSECTION):
     """
     Remove an option and then save it the config file
     """
     if self.has_section(section):
         RawConfigParser.remove_option(self, section, option)
     if not self.remove_in_file(section, option):
         return (_('Unable to save the config file'), 'Error')
     return (_('Option %s deleted') % option, 'Info')
コード例 #6
0
ファイル: config.py プロジェクト: stressrelief/poezio
 def remove_and_save(self, option, section=DEFSECTION):
     """
     Remove an option and then save it the config file
     """
     if self.has_section(section):
         RawConfigParser.remove_option(self, section, option)
     if not self.remove_in_file(section, option):
         return ('Unable to save the config file', 'Error')
     return ('Option %s deleted' % option, 'Info')
コード例 #7
0
ファイル: settings.py プロジェクト: unkie/exaile
    def remove_option(self, option):
        """
        Removes an option (in ``section/key`` syntax),
        thus will not be saved anymore

        :param option: the option path
        :type option: string
        """
        splitvals = option.split('/')
        section, key = "/".join(splitvals[:-1]), splitvals[-1]

        RawConfigParser.remove_option(self, section, key)
コード例 #8
0
ファイル: spanned_monome.py プロジェクト: chailight/Runcible
    def parse_config(self, filename):
        #from ConfigParser import RawConfigParser
        from configparser import RawConfigParser
        import io
        config = RawConfigParser()
        config.readfp(io.open(filename, 'r', encoding='utf_8_sig'))
        for s in config.sections():
            port = int(config.get(s, 'port'))
            config.remove_option(s, 'port')

            xsize, ysize = [int(d) for d in config.get(s, 'size').split(",")]
            config.remove_option(s, 'size')

            x_off, y_off = [int(d) for d in config.get(s, 'offset').split(",")]
            config.remove_option(s, 'offset')
            self.offsets[s] = (x_off, y_off)

            for device, offset in config.items(s):
                x_off, y_off = [int(d) for d in offset.split(",")]
                if device in self.offsets:
                    if (x_off, y_off) != self.offsets[device]:
                        raise RuntimeError(
                            "conflicting offsets for device %s" % device)
                self.offsets[device] = (x_off, y_off)

                if s in self.transtbl: self.transtbl[s].append(device)
                else: self.transtbl[s] = [device]
                if device in self.transtbl: self.transtbl[device].append(s)
                else: self.transtbl[device] = [s]
            self.add_virtual(s, xsize, ysize, port)
コード例 #9
0
ファイル: setopt.py プロジェクト: anagels/python
def edit_config(filename, settings, dry_run=False):
    """Edit a configuration file to include `settings`

    `settings` is a dictionary of dictionaries or ``None`` values, keyed by
    command/section name.  A ``None`` value means to delete the entire section,
    while a dictionary lists settings to be changed or deleted in that section.
    A setting of ``None`` means to delete that setting.
    """
    from configparser import RawConfigParser
    log.debug("Reading configuration from %s", filename)
    opts = RawConfigParser()
    opts.read([filename])
    for section, options in list(settings.items()):
        if options is None:
            log.info("Deleting section [%s] from %s", section, filename)
            opts.remove_section(section)
        else:
            if not opts.has_section(section):
                log.debug("Adding new section [%s] to %s", section, filename)
                opts.add_section(section)
            for option,value in list(options.items()):
                if value is None:
                    log.debug("Deleting %s.%s from %s",
                        section, option, filename
                    )
                    opts.remove_option(section,option)
                    if not opts.options(section):
                        log.info("Deleting empty [%s] section from %s",
                                  section, filename)
                        opts.remove_section(section)
                else:
                    log.debug(
                        "Setting %s.%s to %r in %s",
                        section, option, value, filename
                    )
                    opts.set(section,option,value)

    log.info("Writing %s", filename)
    if not dry_run:
        f = open(filename,'w'); opts.write(f); f.close()
コード例 #10
0
def cleanup():
  cfg_files = glob(CFGFILES)

  for file in cfg_files:
    parser = RawConfigParser(allow_no_value=True)
    parser.optionxform = str
    parser.read(unicode(file))

    for section in parser:
      if not section.startswith('plot:'):
        if(section != 'DEFAULT'):
          print('Invalid configuration section: %s:%s, skipping.' % (file, section))
        continue
      
      if not PLOTNAMEPATTERN.match(section.lstrip('plot:')):
        print("Invalid plot name: '%s:%s' Plot names can contain only: [a-zA-Z0-9_+-]" % (file, section.lstrip('plot:')))
        continue

      if 'metric' not in parser[section] or\
         'relativePath' not in parser[section] or\
         'yTitle' not in parser[section]:
        print('Plot missing required attributes: %s:%s, skipping.' % (file, section))
        print('Required parameters: metric, relativePath, yTitle')
        continue

      parser.remove_option(section, 'runOffset')
      parser.remove_option(section, 'relSystematic')
      parser.remove_option(section, 'absSystematic')
      parser.remove_option(section, 'yMin')
      parser.remove_option(section, 'yMax')
      parser.remove_option(section, 'yMin')
      parser.remove_option(section, 'yMin')

      if 'hTitle' in parser[section]:
        parser[section]['plotTitle'] = parser[section]['hTitle']
        parser.remove_option(section, 'hTitle')

      with open(file, 'w') as configfile:
        parser.write(configfile)
コード例 #11
0
ファイル: setopt.py プロジェクト: haradashinya/yosan
def edit_config(filename, settings, dry_run=False):
    """Edit a configuration file to include `settings`

    `settings` is a dictionary of dictionaries or ``None`` values, keyed by
    command/section name.  A ``None`` value means to delete the entire section,
    while a dictionary lists settings to be changed or deleted in that section.
    A setting of ``None`` means to delete that setting.
    """
    from configparser import RawConfigParser
    log.debug("Reading configuration from %s", filename)
    opts = RawConfigParser()
    opts.read([filename])
    for section, options in list(settings.items()):
        if options is None:
            log.info("Deleting section [%s] from %s", section, filename)
            opts.remove_section(section)
        else:
            if not opts.has_section(section):
                log.debug("Adding new section [%s] to %s", section, filename)
                opts.add_section(section)
            for option, value in list(options.items()):
                if value is None:
                    log.debug("Deleting %s.%s from %s", section, option,
                              filename)
                    opts.remove_option(section, option)
                    if not opts.options(section):
                        log.info("Deleting empty [%s] section from %s",
                                 section, filename)
                        opts.remove_section(section)
                else:
                    log.debug("Setting %s.%s to %r in %s", section, option,
                              value, filename)
                    opts.set(section, option, value)

    log.info("Writing %s", filename)
    if not dry_run:
        f = open(filename, 'w')
        opts.write(f)
        f.close()
コード例 #12
0
ファイル: config.py プロジェクト: wjl198435/MyFakerData
class Config:
    def __init__(self, path):
        self.mutex = RLock()
        self.path = path
        self.config = RawConfigParser()
        self.config.optionxform = str
        try:
            with open(path) as fp:
                self.config.read_file(fp)
        except:
            pass

    def set(self, section, key, value):
        with self.mutex:
            try:
                self.config.set(section, key, value)
            except NoSectionError:
                self.config.add_section(section)
                self.config.set(section, key, value)
        self.save()

    def get(self, section, key, fallback=_UNSET):
        return self.config.get(section, key, fallback=fallback)

    def getInt(self, section, key, fallback=_UNSET):
        return self.config.getint(section, key, fallback=fallback)

    def remove(self, section, key):
        with self.mutex:
            result = self.config.remove_option(section, key)
        self.save()

    def save(self):
        with self.mutex:
            with open(self.path, 'w') as configfile:
                self.config.write(configfile)

    def sections(self):
        return self.config.sections()
コード例 #13
0
ファイル: __init__.py プロジェクト: artemiljin/bumpversion
def main(original_args=None):
    positionals, args = split_args_in_optional_and_positional(
        sys.argv[1:] if original_args is None else original_args)

    if len(positionals[1:]) > 2:
        warnings.warn(
            "Giving multiple files on the command line will be deprecated, please use [bumpversion:file:...] in a config file.",
            PendingDeprecationWarning)

    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument('--verbose',
                         action='count',
                         default=0,
                         help='Print verbose logging to stderr',
                         required=False)

    parser1.add_argument('--list',
                         action='store_true',
                         default=False,
                         help='List machine readable information',
                         required=False)

    known_args, remaining_argv = parser1.parse_known_args(args)

    logformatter = logging.Formatter('%(message)s')

    if len(logger.handlers) == 0:
        ch = logging.StreamHandler(sys.stderr)
        ch.setFormatter(logformatter)
        logger.addHandler(ch)

    if len(logger_list.handlers) == 0:
        ch2 = logging.StreamHandler(sys.stdout)
        ch2.setFormatter(logformatter)
        logger_list.addHandler(ch2)

    if known_args.list:
        logger_list.setLevel(1)

    log_level = {
        0: logging.WARNING,
        1: logging.INFO,
        2: logging.DEBUG,
    }.get(known_args.verbose, logging.DEBUG)

    logger.setLevel(log_level)

    logger.debug("Starting {}".format(DESCRIPTION))

    defaults = {}
    vcs_info = {}

    config = RawConfigParser('')

    # don't transform keys to lowercase (which would be the default)
    config.optionxform = lambda option: option

    config.add_section('bumpversion')

    # We need setup.py to get the major, minor versions
    ver_sources = ['setup.py', 'plugin.json', 'VERSION']
    ver_source = ver_file_check(ver_sources)
    if ver_source is None:
        message = "Could not read any of {} file".format(str(ver_sources))
        logger.error(message)
        sys.exit(2)
    # We don't work with other configuration files except .bumpversion.cfg
    config_file = '.bumpversion.cfg'
    if not os.path.exists(config_file):
        message = "Could not read {} file".format(config_file)
        logger.error(message)
        sys.exit(2)

    part_configs = {}

    files = []

    logger.info("Reading config file {}:".format(config_file))
    logger.info(io.open(config_file, 'rt', encoding='utf-8').read())

    config.readfp(io.open(config_file, 'rt', encoding='utf-8'))

    log_config = StringIO()
    config.write(log_config)

    if 'files' in dict(config.items("bumpversion")):
        warnings.warn(
            "'files =' configuration is will be deprecated, please use [bumpversion:file:...]",
            PendingDeprecationWarning)

    defaults.update(dict(config.items("bumpversion")))

    for listvaluename in ("serialize", ):
        try:
            value = config.get("bumpversion", listvaluename)
            defaults[listvaluename] = list(
                filter(None, (x.strip() for x in value.splitlines())))
        except NoOptionError:
            pass  # no default value then ;)

    for boolvaluename in "dry_run":
        try:
            defaults[boolvaluename] = config.getboolean(
                "bumpversion", boolvaluename)
        except NoOptionError:
            pass  # no default value then ;)

    for section_name in config.sections():

        section_name_match = re.compile("^bumpversion:(file|part):(.+)").match(
            section_name)

        if not section_name_match:
            continue

        section_prefix, section_value = section_name_match.groups()

        section_config = dict(config.items(section_name))

        if section_prefix == "part":

            ThisVersionPartConfiguration = NumericVersionPartConfiguration

            if 'values' in section_config:
                section_config['values'] = list(
                    filter(None,
                           (x.strip()
                            for x in section_config['values'].splitlines())))
                ThisVersionPartConfiguration = ConfiguredVersionPartConfiguration

            part_configs[section_value] = ThisVersionPartConfiguration(
                **section_config)

        elif section_prefix == "file":

            filename = section_value

            if 'serialize' in section_config:
                section_config['serialize'] = list(
                    filter(
                        None,
                        (x.strip()
                         for x in section_config['serialize'].splitlines())))

            section_config['part_configs'] = part_configs

            if not 'parse' in section_config:
                section_config['parse'] = defaults.get(
                    "parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)')

            if not 'serialize' in section_config:
                section_config['serialize'] = defaults.get(
                    'serialize', [str('{major}.{minor}.{patch}')])

            if not 'search' in section_config:
                section_config['search'] = defaults.get(
                    "search", '{current_version}')

            if not 'replace' in section_config:
                section_config['replace'] = defaults.get(
                    "replace", '{new_version}')

            files.append(
                ConfiguredFile(filename, VersionConfig(**section_config)))

    parser2 = argparse.ArgumentParser(prog='bumpversion',
                                      add_help=False,
                                      parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--parse',
                         metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get(
                             "parse",
                             '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize',
                         metavar='FORMAT',
                         action=DiscardDefaultIfSpecifiedAppendAction,
                         help='How to format what is parsed back to a version',
                         default=defaults.get(
                             "serialize", [str('{major}.{minor}.{patch}')]))
    parser2.add_argument('--search',
                         metavar='SEARCH',
                         help='Template for complete string to search',
                         default=defaults.get("search", '{current_version}'))
    parser2.add_argument('--replace',
                         metavar='REPLACE',
                         help='Template for complete string to replace',
                         default=defaults.get("replace", '{new_version}'))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    assert type(known_args.serialize) == list

    context = dict(
        list(time_context.items()) + list(prefixed_environ().items()) +
        list(vcs_info.items()))

    try:
        vc = VersionConfig(
            parse=known_args.parse,
            serialize=known_args.serialize,
            search=known_args.search,
            replace=known_args.replace,
            part_configs=part_configs,
        )
    except sre_constants.error as e:
        sys.exit(1)

    current_version = vc.parse(
        known_args.current_version) if known_args.current_version else None
    leave_config_ver = True
    new_version = None
    if len(positionals) > 0:
        setup_version, zero_patch_setup_version = ConfiguredFile(
            ver_source, vc).find(positionals[0])
        compare = setup_version.compare(vc.order(), current_version)
        for part in compare:
            if part == positionals[0]:
                continue
            else:
                leave_config_ver = leave_config_ver and compare[part]

        try:
            if leave_config_ver and current_version:
                logger.info("Attempting to increment part '{}'".format(
                    positionals[0]))
                new_version = current_version.bump(positionals[0], vc.order())
                logger.info("Values are now: " +
                            keyvaluestring(new_version._values))
                defaults['new_version'] = vc.serialize(new_version, context)
            elif not leave_config_ver:
                logger.info("Using Version from {}".format(ver_source))
                defaults['new_version'] = vc.serialize(
                    zero_patch_setup_version, context)
                new_version = zero_patch_setup_version
                logger.info("Values are now: " +
                            keyvaluestring(setup_version._values))
        except MissingValueForSerializationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except IncompleteVersionRepresenationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except KeyError as e:
            logger.info("Opportunistic finding of new_version failed")
    parser3 = argparse.ArgumentParser(
        prog='bumpversion',
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--dry-run',
                         '-n',
                         action='store_true',
                         default=False,
                         help="Don't write any files, just pretend.")

    file_names = []
    if 'files' in defaults:
        assert defaults['files'] != None
        file_names = defaults['files'].split(' ')

    parser3.add_argument('part', help='Part of the version to be bumped.')
    parser3.add_argument('files',
                         metavar='file',
                         nargs='*',
                         help='Files to change',
                         default=file_names)
    args = parser3.parse_args(remaining_argv + positionals)

    if args.dry_run:
        logger.info("Dry run active, won't touch any files.")

    # make sure files exist and contain version string
    # if leave_config_ver and new_version:
    logger.info("Update info in {}".format(ver_source))
    ConfiguredFile(ver_source, vc).replace(setup_version, new_version, context,
                                           args.dry_run)
    config.set('bumpversion', 'new_version', args.new_version)

    for key, value in config.items('bumpversion'):
        logger_list.info("{}={}".format(key, value))

    config.remove_option('bumpversion', 'new_version')

    config.set('bumpversion', 'current_version', args.new_version)

    new_config = StringIO()

    try:
        write_to_config_file = not args.dry_run

        logger.info("{} to config file {}:".format(
            "Would write" if not write_to_config_file else "Writing",
            config_file,
        ))

        config.write(new_config)
        logger.info(new_config.getvalue())

        if write_to_config_file:
            with io.open(config_file, 'wb') as f:
                f.write(new_config.getvalue().encode('utf-8'))

    except UnicodeEncodeError:
        warnings.warn(
            "Unable to write UTF-8 to config file, because of an old configparser version. "
            "Update with `pip install --upgrade configparser`.")
コード例 #14
0
 def remove_option(self, option):
     return _RawConfigParser.remove_option(self, self._default_section,
                                           option)
コード例 #15
0
class Config(object):

    OUT_MKT_EDDN      = 1
    # OUT_MKT_BPC     = 2	# No longer supported
    OUT_MKT_TD        = 4
    OUT_MKT_CSV       = 8
    OUT_SHIP          = 16
    # OUT_SHIP_EDS    = 16	# Replaced by OUT_SHIP
    # OUT_SYS_FILE    = 32	# No longer supported
    # OUT_STAT        = 64	# No longer available
    # OUT_SHIP_CORIOLIS = 128	# Replaced by OUT_SHIP
    OUT_STATION_ANY   = OUT_MKT_EDDN|OUT_MKT_TD|OUT_MKT_CSV
    # OUT_SYS_EDSM      = 256	# Now a plugin
    # OUT_SYS_AUTO    = 512	# Now always automatic
    OUT_MKT_MANUAL    = 1024
    OUT_SYS_EDDN      = 2048
    OUT_SYS_DELAY     = 4096

    if platform=='darwin':

        def __init__(self):
            self.app_dir = join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], appname)
            if not isdir(self.app_dir):
                mkdir(self.app_dir)

            self.plugin_dir = join(self.app_dir, 'plugins')
            if not isdir(self.plugin_dir):
                mkdir(self.plugin_dir)

            self.internal_plugin_dir = getattr(sys, 'frozen', False) and normpath(join(dirname(sys.executable), pardir, 'Library', 'plugins')) or join(dirname(__file__), 'plugins')

            self.default_journal_dir = join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], 'Frontier Developments', 'Elite Dangerous')

            self.home = expanduser('~')

            self.respath = getattr(sys, 'frozen', False) and normpath(join(dirname(sys.executable), pardir, 'Resources')) or dirname(__file__)

            if not getattr(sys, 'frozen', False):
                # Don't use Python's settings if interactive
                self.identifier = 'uk.org.marginal.%s' % appname.lower()
                NSBundle.mainBundle().infoDictionary()['CFBundleIdentifier'] = self.identifier
            else:
                self.identifier = NSBundle.mainBundle().bundleIdentifier()
            self.defaults = NSUserDefaults.standardUserDefaults()
            self.settings = dict(self.defaults.persistentDomainForName_(self.identifier) or {})	# make writeable

            # Check out_dir exists
            if not self.get('outdir') or not isdir(self.get('outdir')):
                self.set('outdir', NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0])

        def get(self, key):
            val = self.settings.get(key)
            if val is None:
                return None
            elif isinstance(val, str):
                return str(val)
            elif hasattr(val, '__iter__'):
                return list(val)	# make writeable
            else:
                return None

        def getint(self, key):
            try:
                return int(self.settings.get(key, 0))	# should already be int, but check by casting
            except:
                return 0

        def set(self, key, val):
            self.settings[key] = val

        def delete(self, key):
            self.settings.pop(key, None)

        def save(self):
            self.defaults.setPersistentDomain_forName_(self.settings, self.identifier)
            self.defaults.synchronize()

        def close(self):
            self.save()
            self.defaults = None

    elif platform=='win32':

        def __init__(self):

            self.app_dir = join(KnownFolderPath(FOLDERID_LocalAppData), appname)
            if not isdir(self.app_dir):
                mkdir(self.app_dir)

            self.plugin_dir = join(self.app_dir, 'plugins')
            if not isdir(self.plugin_dir):
                mkdir(self.plugin_dir)

            self.internal_plugin_dir = join(dirname(getattr(sys, 'frozen', False) and sys.executable or __file__), u'plugins')

            # expanduser in Python 2 on Windows doesn't handle non-ASCII - http://bugs.python.org/issue13207
            self.home = KnownFolderPath(FOLDERID_Profile) or u'\\'

            journaldir = KnownFolderPath(FOLDERID_SavedGames)
            self.default_journal_dir = journaldir and join(journaldir, 'Frontier Developments', 'Elite Dangerous') or None

            self.respath = dirname(getattr(sys, 'frozen', False) and sys.executable or __file__)

            self.identifier = applongname

            self.hkey = HKEY()
            disposition = DWORD()
            if RegCreateKeyEx(HKEY_CURRENT_USER, r'Software\EDD\EDD-EDMC', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(self.hkey), ctypes.byref(disposition)):
                raise Exception()

            # set WinSparkle defaults - https://github.com/vslavik/winsparkle/wiki/Registry-Settings
            #sparklekey = HKEY()
            #if not RegCreateKeyEx(self.hkey, 'WinSparkle', 0, None, 0, KEY_ALL_ACCESS, None, ctypes.byref(sparklekey), ctypes.byref(disposition)):
            #    if disposition.value == REG_CREATED_NEW_KEY:
            #        buf = ctypes.create_unicode_buffer('1')
            #        RegSetValueEx(sparklekey, 'CheckForUpdates', 0, 1, buf, len(buf)*2)
            #        buf = ctypes.create_unicode_buffer(str(update_interval))
            #        RegSetValueEx(sparklekey, 'UpdateInterval', 0, 1, buf, len(buf)*2)
            #    RegCloseKey(sparklekey)

            if not self.get('outdir') or not isdir(self.get('outdir')):
                self.set('outdir', KnownFolderPath(FOLDERID_Documents) or self.home)

        def get(self, key):
            typ  = DWORD()
            size = DWORD()
            if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), None, ctypes.byref(size)) or typ.value not in [REG_SZ, REG_MULTI_SZ]:
                return None
            buf = ctypes.create_unicode_buffer(int(size.value / 2))
            if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), buf, ctypes.byref(size)):
                return None
            elif typ.value == REG_MULTI_SZ:
                return [x for x in ctypes.wstring_at(buf, len(buf)-2).split(u'\x00')]
            else:
                return str(buf.value)

        def getint(self, key):
            typ  = DWORD()
            size = DWORD(4)
            val  = DWORD()
            if RegQueryValueEx(self.hkey, key, 0, ctypes.byref(typ), ctypes.byref(val), ctypes.byref(size)) or typ.value != REG_DWORD:
                return 0
            else:
                return val.value

        def set(self, key, val):
            if isinstance(val, str):
                buf = ctypes.create_unicode_buffer(val)
                RegSetValueEx(self.hkey, key, 0, REG_SZ, buf, len(buf)*2)
            elif isinstance(val, numbers.Integral):
                RegSetValueEx(self.hkey, key, 0, REG_DWORD, ctypes.byref(DWORD(val)), 4)
            elif hasattr(val, '__iter__'):	# iterable
                stringval = u'\x00'.join([str(x) or u' ' for x in val] + [u''])	# null terminated non-empty strings
                buf = ctypes.create_unicode_buffer(stringval)
                RegSetValueEx(self.hkey, key, 0, REG_MULTI_SZ, buf, len(buf)*2)
            else:
                raise NotImplementedError()

        def delete(self, key):
            RegDeleteValue(self.hkey, key)

        def save(self):
            pass	# Redundant since registry keys are written immediately

        def close(self):
            RegCloseKey(self.hkey)
            self.hkey = None

    elif platform=='linux':

        SECTION = 'config'

        def __init__(self):

            # http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
            self.app_dir = join(getenv('XDG_DATA_HOME', expanduser('~/.local/share')), appname)
            if not isdir(self.app_dir):
                makedirs(self.app_dir)

            self.plugin_dir = join(self.app_dir, 'plugins')
            if not isdir(self.plugin_dir):
                mkdir(self.plugin_dir)

            self.internal_plugin_dir = join(dirname(__file__), 'plugins')

            self.default_journal_dir = None

            self.home = expanduser('~')

            self.respath = dirname(__file__)

            self.identifier = 'uk.org.marginal.%s' % appname.lower()

            self.filename = join(getenv('XDG_CONFIG_HOME', expanduser('~/.config')), appname, '%s.ini' % appname)
            if not isdir(dirname(self.filename)):
                makedirs(dirname(self.filename))

            self.config = RawConfigParser(comment_prefixes = ('#',))
            try:
                with codecs.open(self.filename, 'r') as h:
                    self.config.read_file(h)
            except:
                self.config.add_section(self.SECTION)

            if not self.get('outdir') or not isdir(self.get('outdir')):
                self.set('outdir', expanduser('~'))

        def get(self, key):
            try:
                val = self.config.get(self.SECTION, key)
                if u'\n' in val:	# list
                    # ConfigParser drops the last entry if blank, so we add a spurious ';' entry in set() and remove it here
                    assert val.split('\n')[-1] == ';', val.split('\n')
                    return [self._unescape(x) for x in val.split(u'\n')[:-1]]
                else:
                    return self._unescape(val)
            except:
                return None

        def getint(self, key):
            try:
                return self.config.getint(self.SECTION, key)
            except:
                return 0

        def set(self, key, val):
            if isinstance(val, bool):
                self.config.set(self.SECTION, key, val and '1' or '0')
            elif isinstance(val, str) or isinstance(val, numbers.Integral):
                self.config.set(self.SECTION, key, self._escape(val))
            elif hasattr(val, '__iter__'):	# iterable
                self.config.set(self.SECTION, key, u'\n'.join([self._escape(x) for x in val] + [u';']))
            else:
                raise NotImplementedError()

        def delete(self, key):
            self.config.remove_option(self.SECTION, key)

        def save(self):
            with codecs.open(self.filename, 'w', 'utf-8') as h:
                self.config.write(h)

        def close(self):
            self.save()
            self.config = None

        def _escape(self, val):
            return str(val).replace(u'\\', u'\\\\').replace(u'\n', u'\\n').replace(u';', u'\\;')

        def _unescape(self, val):
            chars = list(val)
            i = 0
            while i < len(chars):
                if chars[i] == '\\':
                    chars.pop(i)
                    if chars[i] == 'n':
                        chars[i] = '\n'
                i += 1
            return u''.join(chars)

    else:	# ???

        def __init__(self):
            raise NotImplementedError('Implement me')

    # Common

    def get_password(self, account):
        try:
            import keyring
            return keyring.get_password(self.identifier, account)
        except ImportError:
            return None

    def set_password(self, account, password):
        try:
            import keyring
            keyring.set_password(self.identifier, account, password)
        except ImportError:
            pass

    def delete_password(self, account):
        try:
            import keyring
            keyring.delete_password(self.identifier, account)
        except:
            pass	# don't care - silently fail
コード例 #16
0
class MrxsFile(object):
    def __init__(self, filename):
        # Split filename
        dirname, ext = os.path.splitext(filename)
        if ext != ".mrxs":
            raise UnrecognizedFile

        # Parse slidedat
        self._slidedatfile = os.path.join(dirname, "Slidedat.ini")
        self._dat = RawConfigParser()
        self._dat.optionxform = str
        try:
            with open(self._slidedatfile, "rb") as fh:
                self._have_bom = fh.read(len(UTF8_BOM)) == UTF8_BOM
                if not self._have_bom:
                    fh.seek(0)
                self._dat.readfp(fh)
        except IOError:
            raise UnrecognizedFile

        # Get file paths
        self._indexfile = os.path.join(
            dirname, self._dat.get(MRXS_HIERARCHICAL, "INDEXFILE"))
        self._datafiles = [
            os.path.join(dirname, self._dat.get("DATAFILE", "FILE_%d" % i))
            for i in range(self._dat.getint("DATAFILE", "FILE_COUNT"))
        ]

        # Build levels
        self._make_levels()

    def _make_levels(self):
        self._levels = {}
        self._level_list = []
        layer_count = self._dat.getint(MRXS_HIERARCHICAL, "NONHIER_COUNT")
        for layer_id in range(layer_count):
            level_count = self._dat.getint(MRXS_HIERARCHICAL,
                                           "NONHIER_%d_COUNT" % layer_id)
            for level_id in range(level_count):
                level = MrxsNonHierLevel(self._dat, layer_id, level_id,
                                         len(self._level_list))
                self._levels[(level.layer_name, level.name)] = level
                self._level_list.append(level)

    @classmethod
    def _read_int32(cls, f):
        buf = f.read(4)
        if len(buf) != 4:
            raise IOError("Short read")
        return struct.unpack("<i", buf)[0]

    @classmethod
    def _assert_int32(cls, f, value):
        v = cls._read_int32(f)
        if v != value:
            raise ValueError("%d != %d" % (v, value))

    def _get_data_location(self, record):
        with open(self._indexfile, "rb") as fh:
            fh.seek(MRXS_NONHIER_ROOT_OFFSET)
            # seek to record
            table_base = self._read_int32(fh)
            fh.seek(table_base + record * 4)
            # seek to list head
            list_head = self._read_int32(fh)
            fh.seek(list_head)
            # seek to data page
            self._assert_int32(fh, 0)
            page = self._read_int32(fh)
            fh.seek(page)
            # check pagesize
            self._assert_int32(fh, 1)
            # read rest of prologue
            self._read_int32(fh)
            self._assert_int32(fh, 0)
            self._assert_int32(fh, 0)
            # read values
            position = self._read_int32(fh)
            size = self._read_int32(fh)
            fileno = self._read_int32(fh)
            return (self._datafiles[fileno], position, size)

    def _zero_record(self, record):
        path, offset, length = self._get_data_location(record)
        with open(path, "r+b") as fh:
            fh.seek(0, 2)
            do_truncate = fh.tell() == offset + length
            if DEBUG:
                if do_truncate:
                    print("Truncating", path, "to", offset)
                else:
                    print("Zeroing", path, "at", offset, "for", length)
            fh.seek(offset)
            buf = fh.read(len(JPEG_SOI))
            if buf != JPEG_SOI:
                raise IOError("Unexpected data in nonhier image")
            if do_truncate:
                fh.truncate(offset)
            else:
                fh.seek(offset)
                fh.write("\0" * length)

    def _delete_index_record(self, record):
        if DEBUG:
            print("Deleting record", record)
        with open(self._indexfile, "r+b") as fh:
            entries_to_move = len(self._level_list) - record - 1
            if entries_to_move == 0:
                return
            # get base of table
            fh.seek(MRXS_NONHIER_ROOT_OFFSET)
            table_base = self._read_int32(fh)
            # read tail of table
            fh.seek(table_base + (record + 1) * 4)
            buf = fh.read(entries_to_move * 4)
            if len(buf) != entries_to_move * 4:
                raise IOError("Short read")
            # overwrite the target record
            fh.seek(table_base + record * 4)
            fh.write(buf)

    def _hier_keys_for_level(self, level):
        ret = []
        for k, _ in self._dat.items(MRXS_HIERARCHICAL):
            if k == level.key_prefix or k.startswith(level.key_prefix + "_"):
                ret.append(k)
        return ret

    def _rename_section(self, old, new):
        if self._dat.has_section(old):
            if DEBUG:
                print("[%s] -> [%s]" % (old, new))
            self._dat.add_section(new)
            for k, v in self._dat.items(old):
                self._dat.set(new, k, v)
            self._dat.remove_section(old)
        elif DEBUG:
            print("[%s] does not exist" % old)

    def _delete_section(self, section):
        if DEBUG:
            print("Deleting [%s]" % section)
        self._dat.remove_section(section)

    def _set_key(self, section, key, value):
        if DEBUG:
            prev = self._dat.get(section, key)
            print("[%s] %s: %s -> %s" % (section, key, prev, value))
        self._dat.set(section, key, value)

    def _rename_key(self, section, old, new):
        if DEBUG:
            print("[%s] %s -> %s" % (section, old, new))
        v = self._dat.get(section, old)
        self._dat.remove_option(section, old)
        self._dat.set(section, new, v)

    def _delete_key(self, section, key):
        if DEBUG:
            print("Deleting [%s] %s" % (section, key))
        self._dat.remove_option(section, key)

    def _write(self):
        buf = io.StringIO()
        self._dat.write(buf)
        with open(self._slidedatfile, "wb") as fh:
            if self._have_bom:
                fh.write(bytearray(UTF8_BOM))
            fh.write(bytearray(buf.getvalue().replace("\n", "\r\n")))

    def delete_level(self, layer_name, level_name):
        level = self._levels[(layer_name, level_name)]
        record = level.record

        # Zero image data
        self._zero_record(record)

        # Delete pointer from nonhier table in index
        self._delete_index_record(record)

        # Remove slidedat keys
        for k in self._hier_keys_for_level(level):
            self._delete_key(MRXS_HIERARCHICAL, k)

        # Remove slidedat section
        self._delete_section(level.section)

        # Rename section and keys for subsequent levels in the layer
        prev_level = level
        for cur_level in self._level_list[record + 1:]:
            if cur_level.layer_id != prev_level.layer_id:
                break
            for k in self._hier_keys_for_level(cur_level):
                new_k = k.replace(cur_level.key_prefix, prev_level.key_prefix,
                                  1)
                self._rename_key(MRXS_HIERARCHICAL, k, new_k)
            self._set_key(MRXS_HIERARCHICAL, prev_level.section_key,
                          prev_level.section)
            self._rename_section(cur_level.section, prev_level.section)
            prev_level = cur_level

        # Update level count within layer
        count_k = "NONHIER_%d_COUNT" % level.layer_id
        count_v = self._dat.getint(MRXS_HIERARCHICAL, count_k)
        self._set_key(MRXS_HIERARCHICAL, count_k, count_v - 1)

        # Write slidedat
        self._write()

        # Refresh metadata
        self._make_levels()
コード例 #17
0
def main(original_args=None):

    positionals, args = split_args_in_optional_and_positional(
        sys.argv[1:] if original_args is None else original_args)

    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument('--config-file',
                         default='.bumpversion.cfg',
                         metavar='FILE',
                         help='Config file to read most of the variables from',
                         required=False)

    parser1.add_argument('--verbose',
                         action='count',
                         default=0,
                         help='Print verbose logging to stderr',
                         required=False)

    known_args, remaining_argv = parser1.parse_known_args(args)

    if len(logger.handlers) == 0:
        ch = logging.StreamHandler(sys.stderr)
        logformatter = logging.Formatter('%(message)s')
        ch.setFormatter(logformatter)
        logger.addHandler(ch)

    log_level = {
        0: logging.WARNING,
        1: logging.INFO,
        2: logging.DEBUG,
    }.get(known_args.verbose, logging.DEBUG)

    logger.setLevel(log_level)

    logger.debug("Starting {}".format(DESCRIPTION))

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if 'current_version' in vcs_info:
        defaults['current_version'] = vcs_info['current_version']

    config = None
    if os.path.exists(known_args.config_file):
        config = RawConfigParser()
        config.readfp(io.open(known_args.config_file, 'rt', encoding='utf-8'))

        log_config = StringIO()
        config.write(log_config)
        logger.info("Reading config file {}:".format(known_args.config_file))

        logger.info(log_config.getvalue())

        defaults.update(dict(config.items("bumpversion")))

        for listvaluename in ("serialize", ):
            try:
                value = config.get("bumpversion", listvaluename)
                defaults[listvaluename] = list(
                    filter(None, (x.strip() for x in value.splitlines())))
            except NoOptionError:
                pass  # no default value then ;)

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean(
                    "bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

    else:
        message = "Could not read config file at {}".format(
            known_args.config_file)
        if known_args.config_file != parser1.get_default('config_file'):
            raise argparse.ArgumentTypeError(message)
        else:
            logger.info(message)

    parser2 = argparse.ArgumentParser(add_help=False, parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--current-version',
                         metavar='VERSION',
                         help='Version that needs to be updated',
                         required=False)
    parser2.add_argument('--parse',
                         metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get(
                             "parse",
                             '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize',
                         metavar='FORMAT',
                         action=DiscardDefaultIfSpecifiedAppendAction,
                         help='How to format what is parsed back to a version',
                         default=defaults.get(
                             "serialize", [str('{major}.{minor}.{patch}')]))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    assert type(known_args.serialize) == list

    time_context = {
        'now': datetime.now(),
        'utcnow': datetime.utcnow(),
    }

    try:
        v = Version(
            known_args.parse,
            known_args.serialize,
            context=dict(
                list(time_context.items()) + list(prefixed_environ().items()) +
                list(vcs_info.items())))
    except sre_constants.error as e:
        sys.exit(1)

    if not 'new_version' in defaults and known_args.current_version:
        v.parse(known_args.current_version)

        if len(positionals) > 0:
            v.bump(positionals[0])

        try:
            defaults['new_version'] = v.serialize()
        except MissingValueForSerializationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except IncompleteVersionRepresenationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except KeyError as e:
            logger.info("Opportunistic finding of new_version failed")

    parser3 = argparse.ArgumentParser(
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--current-version',
                         metavar='VERSION',
                         help='Version that needs to be updated',
                         required=not 'current_version' in defaults)
    parser3.add_argument('--dry-run',
                         '-n',
                         action='store_true',
                         default=False,
                         help="Don't write any files, just pretend.")
    parser3.add_argument('--new-version',
                         metavar='VERSION',
                         help='New version that should be in the files',
                         required=not 'new_version' in defaults)

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument('--commit',
                             action='store_true',
                             dest="commit",
                             help='Commit to version control',
                             default=defaults.get("commit", False))
    commitgroup.add_argument('--no-commit',
                             action='store_false',
                             dest="commit",
                             help='Do not commit to version control',
                             default=argparse.SUPPRESS)

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument('--tag',
                          action='store_true',
                          dest="tag",
                          default=defaults.get("tag", False),
                          help='Create a tag in version control')
    taggroup.add_argument('--no-tag',
                          action='store_false',
                          dest="tag",
                          help='Do not create a tag in version control',
                          default=argparse.SUPPRESS)

    parser3.add_argument('--tag-name',
                         metavar='TAG_NAME',
                         help='Tag name (only works with --tag)',
                         default=defaults.get('tag_name', 'v{new_version}'))

    parser3.add_argument(
        '--message',
        '-m',
        metavar='COMMIT_MSG',
        help='Commit message',
        default=defaults.get(
            'message', 'Bump version: {current_version} → {new_version}'))

    files = []
    if 'files' in defaults:
        assert defaults['files'] != None
        files = defaults['files'].split(' ')

    parser3.add_argument('part', help='Part of the version to be bumped.')
    parser3.add_argument('files',
                         metavar='file',
                         nargs='*',
                         help='Files to change',
                         default=files)

    args = parser3.parse_args(remaining_argv + positionals)

    if args.dry_run:
        logger.info("Dry run active, won't touch any files.")

    logger.info("New version will be '{}'".format(args.new_version))

    files = files or positionals[1:]

    for vcs in VCS:
        if vcs.is_usable():
            vcs.assert_nondirty()
            break
        else:
            vcs = None

    # make sure files exist and contain version string

    logger.info("Asserting files {} contain string '{}':".format(
        ", ".join(files), args.current_version))

    for path in files:
        with io.open(path, 'rb') as f:

            found_before = False

            for lineno, line in enumerate(f.readlines()):
                if args.current_version in line.decode('utf-8'):
                    found_before = True
                    logger.info("Found '{}' in {} at line {}: {}".format(
                        args.current_version, path, lineno,
                        line.decode('utf-8').rstrip()))

            assert found_before, 'Did not find string {} in file {}'.format(
                args.current_version, path)

    # change version string in files
    for path in files:
        with io.open(path, 'rb') as f:
            before = f.read().decode('utf-8')

        after = before.replace(args.current_version, args.new_version)

        logger.info("{} file {}:".format(
            "Would change" if args.dry_run else "Changing",
            path,
        ))
        logger.info("\n".join(
            list(
                unified_diff(before.splitlines(),
                             after.splitlines(),
                             lineterm="",
                             fromfile="a/" + path,
                             tofile="b/" + path))))

        if not args.dry_run:
            with io.open(path, 'wt', encoding='utf-8') as f:
                f.write(after)

    commit_files = files

    if config:
        config.remove_option('bumpversion', 'new_version')

        config.set('bumpversion', 'current_version', args.new_version)

        s = StringIO()

        try:
            config.write(s)

            logger.info("{} to config file {}:".format(
                "Would write" if args.dry_run else "Writing",
                known_args.config_file,
            ))
            logger.info(log_config.getvalue())

            if not args.dry_run:
                with io.open(known_args.config_file, 'wb') as f:
                    f.write(s.getvalue().encode('utf-8'))

        except UnicodeEncodeError:
            warnings.warn(
                "Unable to write UTF-8 to config file, because of an old configparser version. "
                "Update with `pip install --upgrade configparser`.")

        commit_files.append(known_args.config_file)

    if not vcs:
        return

    assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(
        vcs.__name__)

    do_commit = (not args.dry_run) and args.commit
    do_tag = (not args.dry_run) and args.tag

    logger.info("{} {} commit".format(
        "Would prepare" if not do_commit else "Preparing",
        vcs.__name__,
    ))

    for path in commit_files:
        logger.info("{} changes in file '{}' to {}".format(
            "Would add" if not do_commit else "Adding",
            path,
            vcs.__name__,
        ))

        if do_commit:
            vcs.add_path(path)

    vcs_context = {
        "current_version": args.current_version,
        "new_version": args.new_version,
    }
    vcs_context.update(time_context)
    vcs_context.update(prefixed_environ())

    commit_message = args.message.format(**vcs_context)

    logger.info("{} to {} with message '{}'".format(
        "Would commit" if not do_commit else "Committing",
        vcs.__name__,
        commit_message,
    ))

    if do_commit:
        vcs.commit(message=commit_message)

    tag_name = args.tag_name.format(**vcs_context)
    logger.info("{} '{}' in {}".format(
        "Would tag" if not do_tag else "Tagging", tag_name, vcs.__name__))

    if do_tag:
        vcs.tag(tag_name)
コード例 #18
0
class MrxsFile(object):
    def __init__(self, filename):
        # Split filename
        dirname, ext = os.path.splitext(filename)
        if ext != '.mrxs':
            raise UnrecognizedFile

        # Parse slidedat
        self._slidedatfile = os.path.join(dirname, 'Slidedat.ini')
        self._slidedatfile_upperdir = os.path.join(dirname, '../Slidedat.ini')
        self._dat = RawConfigParser()
        self._dat.optionxform = str
        self._anonymize_meta(dirname)
        try:
            with open(self._slidedatfile, 'r', encoding="utf-8-sig") as fh:
                self._have_bom = (fh.read(len(UTF8_BOM)) == UTF8_BOM)
                if not self._have_bom:
                    fh.seek(0)
                self._dat.read_file(fh)
        except IOError:
            raise UnrecognizedFile

        # Get file paths
        self._indexfile = os.path.join(
            dirname, self._dat.get(MRXS_HIERARCHICAL, 'INDEXFILE'))
        self._datafiles = [
            os.path.join(dirname, self._dat.get('DATAFILE', 'FILE_%d' % i))
            for i in range(self._dat.getint('DATAFILE', 'FILE_COUNT'))
        ]

        # Build levels
        self._make_levels()

    def _anonymize_meta(self, dirname):
        for filename in [
                os.path.join(dirname, 'Slidedat.ini'),
                os.path.join(dirname, '../Slidedat.ini')
        ]:
            filedata = ''
            if os.path.exists(filename):
                with open(filename, 'r') as fh:
                    filedata = fh.read()
                    filedata = re.sub(r"SLIDE_NAME.*", "SLIDE_NAME = None",
                                      filedata)
                    filedata = re.sub(r"PROJECT_NAME.*", "PROJECT_NAME = None",
                                      filedata)
                    filedata = re.sub(r"SLIDE_CREATIONDATETIME.*",
                                      "SLIDE_CREATIONDATETIME = None",
                                      filedata)
                    fh.close

                with open(filename, 'w') as fh:
                    fh.write(filedata)
                    fh.close()

    def _make_levels(self):
        self._levels = {}
        self._level_list = []
        layer_count = self._dat.getint(MRXS_HIERARCHICAL, 'NONHIER_COUNT')
        for layer_id in range(layer_count):
            level_count = self._dat.getint(MRXS_HIERARCHICAL,
                                           'NONHIER_%d_COUNT' % layer_id)
            for level_id in range(level_count):
                level = MrxsNonHierLevel(self._dat, layer_id, level_id,
                                         len(self._level_list))
                self._levels[(level.layer_name, level.name)] = level
                self._level_list.append(level)

    @classmethod
    def _read_int32(cls, f):
        buf = f.read(4)
        if len(buf) != 4:
            raise IOError('Short read')
        return struct.unpack('<i', buf)[0]

    @classmethod
    def _assert_int32(cls, f, value):
        v = cls._read_int32(f)
        if v != value:
            raise ValueError('%d != %d' % (v, value))

    def _get_data_location(self, record):
        with open(self._indexfile, 'rb') as fh:
            fh.seek(MRXS_NONHIER_ROOT_OFFSET)
            # seek to record
            table_base = self._read_int32(fh)
            fh.seek(table_base + record * 4)
            # seek to list head
            list_head = self._read_int32(fh)
            fh.seek(list_head)
            # seek to data page
            self._assert_int32(fh, 0)
            page = self._read_int32(fh)
            fh.seek(page)
            # check pagesize
            self._assert_int32(fh, 1)
            # read rest of prologue
            self._read_int32(fh)
            self._assert_int32(fh, 0)
            self._assert_int32(fh, 0)
            # read values
            position = self._read_int32(fh)
            size = self._read_int32(fh)
            fileno = self._read_int32(fh)
            return (self._datafiles[fileno], position, size)

    def _zero_record(self, record):
        path, offset, length = self._get_data_location(record)
        with open(path, 'r+b') as fh:
            fh.seek(0, 2)
            do_truncate = (fh.tell() == offset + length)
            if DEBUG:
                if do_truncate:
                    print('Truncating', path, 'to', offset)
                else:
                    print('Zeroing', path, 'at', offset, 'for', length)
            fh.seek(offset)
            buf = fh.read(len(JPEG_SOI))
            # print(buf)
            # exit()
            if buf != JPEG_SOI:
                raise IOError('Unexpected data in nonhier image')
            if do_truncate:
                fh.truncate(offset)
            else:
                fh.seek(offset)
                fh.write('\0' * length)

    def _delete_index_record(self, record):
        if DEBUG:
            print('Deleting record', record)
        with open(self._indexfile, 'r+b') as fh:
            entries_to_move = len(self._level_list) - record - 1
            if entries_to_move == 0:
                return
            # get base of table
            fh.seek(MRXS_NONHIER_ROOT_OFFSET)
            table_base = self._read_int32(fh)
            # read tail of table
            fh.seek(table_base + (record + 1) * 4)
            buf = fh.read(entries_to_move * 4)
            if len(buf) != entries_to_move * 4:
                raise IOError('Short read')
            # overwrite the target record
            fh.seek(table_base + record * 4)
            fh.write(buf)

    def _hier_keys_for_level(self, level):
        ret = []
        for k, _ in self._dat.items(MRXS_HIERARCHICAL):
            if k == level.key_prefix or k.startswith(level.key_prefix + '_'):
                ret.append(k)
        return ret

    def _rename_section(self, old, new):
        if self._dat.has_section(old):
            if DEBUG:
                print('[%s] -> [%s]' % (old, new))
            self._dat.add_section(new)
            for k, v in self._dat.items(old):
                self._dat.set(new, k, v)
            self._dat.remove_section(old)
        elif DEBUG:
            print('[%s] does not exist' % old)

    def _delete_section(self, section):
        if DEBUG:
            print('Deleting [%s]' % section)
        self._dat.remove_section(section)

    def _set_key(self, section, key, value):
        if DEBUG:
            prev = self._dat.get(section, key)
            print('[%s] %s: %s -> %s' % (section, key, prev, value))
        self._dat.set(section, key, value)

    def _rename_key(self, section, old, new):
        if DEBUG:
            print('[%s] %s -> %s' % (section, old, new))
        v = self._dat.get(section, old)
        self._dat.remove_option(section, old)
        self._dat.set(section, new, v)

    def _delete_key(self, section, key):
        if DEBUG:
            print('Deleting [%s] %s' % (section, key))
        self._dat.remove_option(section, key)

    def _write(self):
        buf = StringIO()
        self._dat.write(buf)
        with open(self._slidedatfile, 'wb') as fh:
            if self._have_bom:
                fh.write(UTF8_BOM.encode())
            fh.write(buf.getvalue().replace('\n', '\r\n').encode())

    def delete_level(self, layer_name, level_name):
        level = self._levels[(layer_name, level_name)]
        record = level.record

        # Zero image data
        self._zero_record(record)

        # Delete pointer from nonhier table in index
        self._delete_index_record(record)

        # Remove slidedat keys
        for k in self._hier_keys_for_level(level):
            self._delete_key(MRXS_HIERARCHICAL, k)

        # Remove slidedat section
        self._delete_section(level.section)

        # Rename section and keys for subsequent levels in the layer
        prev_level = level
        for cur_level in self._level_list[record + 1:]:
            if cur_level.layer_id != prev_level.layer_id:
                break
            for k in self._hier_keys_for_level(cur_level):
                new_k = k.replace(cur_level.key_prefix, prev_level.key_prefix,
                                  1)
                self._rename_key(MRXS_HIERARCHICAL, k, new_k)
            self._set_key(MRXS_HIERARCHICAL, prev_level.section_key,
                          prev_level.section)
            self._rename_section(cur_level.section, prev_level.section)
            prev_level = cur_level

        # Update level count within layer
        count_k = 'NONHIER_%d_COUNT' % level.layer_id
        count_v = self._dat.getint(MRXS_HIERARCHICAL, count_k)
        self._set_key(MRXS_HIERARCHICAL, count_k, count_v - 1)

        # Write slidedat
        self._write()

        # Refresh metadata
        self._make_levels()
コード例 #19
0
class BaseConfigStore(object):
    # the actual config store functionality
    def __init__(self, name, *arg, **kw):
        super(BaseConfigStore, self).__init__(*arg, **kw)
        self.dirty = False
        self.config = RawConfigParser()
        config_dir = os.environ.get('PHOTINI_CONFIG')
        if config_dir:
            config_dir = os.path.expanduser(config_dir)
        elif hasattr(appdirs, 'user_config_dir'):
            config_dir = appdirs.user_config_dir('photini')
        else:
            config_dir = appdirs.user_data_dir('photini')
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir, mode=stat.S_IRWXU)
        self.file_name = os.path.join(config_dir, name + '.ini')
        if os.path.isfile(self.file_name):
            kwds = {'encoding': 'utf-8'}
            with open(self.file_name, 'r', **kwds) as fp:
                self.config.read_file(fp)
        self.has_section = self.config.has_section

    def get(self, section, option, default=None):
        if self.config.has_option(section, option):
            return self.config.get(section, option)
        if default is not None:
            self.set(section, option, default)
        return default

    def set(self, section, option, value):
        if not self.config.has_section(section):
            self.config.add_section(section)
        elif (self.config.has_option(section, option)
              and self.config.get(section, option) == value):
            return
        self.config.set(section, option, value)
        self.dirty = True

    def delete(self, section, option):
        if not self.config.has_section(section):
            return
        if self.config.has_option(section, option):
            self.config.remove_option(section, option)
        if not self.config.options(section):
            self.config.remove_section(section)
        self.dirty = True

    def remove_section(self, section):
        if not self.config.has_section(section):
            return
        for option in self.config.options(section):
            self.config.remove_option(section, option)
        self.config.remove_section(section)
        self.dirty = True

    def save(self):
        if not self.dirty:
            return
        kwds = {'encoding': 'utf-8'}
        with open(self.file_name, 'w', **kwds) as fp:
            self.config.write(fp)
        os.chmod(self.file_name, stat.S_IRUSR | stat.S_IWUSR)
        self.dirty = False
コード例 #20
0
 def remove_option(self, section, option):
     if self.has_option(section, option):
         RawConfigParser.remove_option(self, section, option)
コード例 #21
0
ファイル: config.py プロジェクト: zsau/quodlibet
class Config(object):
    """A wrapper around RawConfigParser.

    Provides a ``defaults`` attribute of the same type which can be used
    to set default values.
    """

    def __init__(self, version=None, _defaults=True):
        """Use read() to read in an existing config file.

        version should be an int starting with 0 that gets incremented if you
        want to register a new upgrade function. If None, upgrade is disabled.
        """

        self._config = ConfigParser(dict_type=_sorted_dict)
        self.defaults = None
        if _defaults:
            self.defaults = Config(_defaults=False)
        self._version = version
        self._loaded_version = None
        self._upgrade_funcs = []

    def _do_upgrade(self, func):
        assert self._loaded_version is not None
        assert self._version is not None

        old_version = self._loaded_version
        new_version = self._version
        if old_version != new_version:
            print_d("Config upgrade: %d->%d (%r)" % (
                old_version, new_version, func))
            func(self, old_version, new_version)

    def get_version(self):
        """Get the version of the loaded config file (for testing only)

        Raises Error if no file was loaded or versioning is disabled.
        """

        if self._version is None:
            raise Error("Versioning disabled")

        if self._loaded_version is None:
            raise Error("No file loaded")

        return self._loaded_version

    def register_upgrade_function(self, function):
        """Register an upgrade function that gets called at each read()
        if the current config version and the loaded version don't match.

        Can also be registered after read was called.

        function(config, old_version: int, new_version: int) -> None
        """

        if self._version is None:
            raise Error("Versioning disabled")

        self._upgrade_funcs.append(function)
        # after read(), so upgrade now
        if self._loaded_version is not None:
            self._do_upgrade(function)
        return function

    def reset(self, section, option):
        """Reset the value to the default state"""

        assert self.defaults is not None

        try:
            self._config.remove_option(section, option)
        except NoSectionError:
            pass

    def options(self, section):
        """Returns a list of options available in the specified section."""

        try:
            options = self._config.options(section)
        except NoSectionError:
            if self.defaults:
                return self.defaults.options(section)
            raise
        else:
            if self.defaults:
                try:
                    options.extend(self.defaults.options(section))
                    options = list_unique(options)
                except NoSectionError:
                    pass
            return options

    def get(self, section, option, default=_DEFAULT):
        """get(section, option[, default]) -> str

        If default is not given or set, raises Error in case of an error
        """

        try:
            return self._config.get(section, option)
        except Error:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.get(section, option)
                    except Error:
                        pass
                raise
            return default

    def gettext(self, *args, **kwargs):
        value = self.get(*args, **kwargs)
        # make sure there are no surrogates
        value.encode("utf-8")
        return value

    def getbytes(self, section, option, default=_DEFAULT):
        try:
            value = self._config.get(section, option)
            value = value.encode("utf-8", "surrogateescape")
            return value
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getbytes(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getboolean(self, section, option, default=_DEFAULT):
        """getboolean(section, option[, default]) -> bool

        If default is not given or set, raises Error in case of an error
        """

        try:
            return self._config.getboolean(section, option)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getboolean(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getint(self, section, option, default=_DEFAULT):
        """getint(section, option[, default]) -> int

        If default is not give or set, raises Error in case of an error
        """

        try:
            return int(self._config.getfloat(section, option))
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getint(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getfloat(self, section, option, default=_DEFAULT):
        """getfloat(section, option[, default]) -> float

        If default is not give or set, raises Error in case of an error
        """

        try:
            return self._config.getfloat(section, option)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getfloat(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getstringlist(self, section, option, default=_DEFAULT):
        """getstringlist(section, option[, default]) -> list

        If default is not given or set, raises Error in case of an error.
        Gets a list of strings, using CSV to parse and delimit.
        """

        try:
            value = self._config.get(section, option)

            parser = csv.reader(
                [value], lineterminator='\n', quoting=csv.QUOTE_MINIMAL)
            try:
                vals = next(parser)
            except (csv.Error, ValueError) as e:
                raise Error(e)
            return vals
        except Error as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getstringlist(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def setstringlist(self, section, option, values):
        """Saves a list of unicode strings using the csv module"""

        sw = StringIO()
        values = [str(v) for v in values]

        writer = csv.writer(sw, lineterminator='\n', quoting=csv.QUOTE_MINIMAL)
        writer.writerow(values)
        self.set(section, option, sw.getvalue())

    def setlist(self, section, option, values, sep=","):
        """Saves a list of str using ',' as a separator and \\ for escaping"""

        values = [str(v) for v in values]
        joined = join_escape(values, sep)
        self.set(section, option, joined)

    def getlist(self, section, option, default=_DEFAULT, sep=","):
        """Returns a str list saved with setlist()"""

        try:
            value = self._config.get(section, option)
            return split_escape(value, sep)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getlist(section, option, sep=sep)
                    except Error:
                        pass
                raise Error(e)
            return default

    def set(self, section, option, value):
        """Saves the string representation for the passed value

        Don't pass unicode, encode first.
        """

        if isinstance(value, bytes):
            raise TypeError("use setbytes")

        # RawConfigParser only allows string values but doesn't
        # scream if they are not (and it only fails before the
        # first config save..)
        if not isinstance(value, str):
            value = str(value)

        try:
            self._config.set(section, option, value)
        except NoSectionError:
            if self.defaults and self.defaults.has_section(section):
                self._config.add_section(section)
                self._config.set(section, option, value)
            else:
                raise

    def settext(self, section, option, value):
        value = str(value)

        # make sure there are no surrogates
        value.encode("utf-8")

        self.set(section, option, value)

    def setbytes(self, section, option, value):
        assert isinstance(value, bytes)

        value = value.decode("utf-8", "surrogateescape")

        self.set(section, option, value)

    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert isinstance(filename, fsnative)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, "wb") as fileobj:
                temp = StringIO()
                self._config.write(temp)
                data = temp.getvalue().encode("utf-8", "surrogateescape")
                fileobj.write(data)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)

    def clear(self):
        """Remove all sections."""

        for section in self._config.sections():
            self._config.remove_section(section)

    def is_empty(self):
        """Whether the config has any sections"""

        return not self._config.sections()

    def read(self, filename):
        """Reads the config from `filename` if the file exists,
        otherwise does nothing

        Can raise EnvironmentError, Error.
        """

        try:
            with open(filename, "rb") as fileobj:
                fileobj = StringIO(
                    fileobj.read().decode("utf-8", "surrogateescape"))
                self._config.readfp(fileobj, filename)
        except (IOError, OSError):
            return

        # don't upgrade if we just created a new config
        if self._version is not None:
            self._loaded_version = self.getint("__config__", "version", -1)
            for func in self._upgrade_funcs:
                self._do_upgrade(func)

    def has_option(self, section, option):
        """If the given section exists, and contains the given option"""

        return self._config.has_option(section, option) or (
            self.defaults and self.defaults.has_option(section, option))

    def has_section(self, section):
        """If the given section exists"""

        return self._config.has_section(section) or (
            self.defaults and self.defaults.has_section(section))

    def remove_option(self, section, option):
        """Remove the specified option from the specified section

        Can raise Error.
        """

        return self._config.remove_option(section, option)

    def add_section(self, section):
        """Add a section named section to the instance if it not already
        exists."""

        if not self._config.has_section(section):
            self._config.add_section(section)
コード例 #22
0
ファイル: __init__.py プロジェクト: inirudebwoy/bumpversion
def main(original_args=None):

    positionals, args = split_args_in_optional_and_positional(
      sys.argv[1:] if original_args is None else original_args
    )

    if len(positionals[1:]) > 2:
        warnings.warn("Giving multiple files on the command line will be deprecated, please use [bumpversion:file:...] in a config file.", PendingDeprecationWarning)

    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument(
        '--config-file', metavar='FILE',
        default=argparse.SUPPRESS, required=False,
        help='Config file to read most of the variables from (default: .bumpversion.cfg)')

    parser1.add_argument(
        '--verbose', action='count', default=0,
        help='Print verbose logging to stderr', required=False)

    parser1.add_argument(
        '--list', action='store_true', default=False,
        help='List machine readable information', required=False)

    parser1.add_argument(
        '--allow-dirty', action='store_true', default=False,
        help="Don't abort if working directory is dirty", required=False)

    known_args, remaining_argv = parser1.parse_known_args(args)

    logformatter = logging.Formatter('%(message)s')

    if len(logger.handlers) == 0:
        ch = logging.StreamHandler(sys.stderr)
        ch.setFormatter(logformatter)
        logger.addHandler(ch)

    if len(logger_list.handlers) == 0:
       ch2 = logging.StreamHandler(sys.stdout)
       ch2.setFormatter(logformatter)
       logger_list.addHandler(ch2)

    if known_args.list:
          logger_list.setLevel(1)

    log_level = {
        0: logging.WARNING,
        1: logging.INFO,
        2: logging.DEBUG,
    }.get(known_args.verbose, logging.DEBUG)

    logger.setLevel(log_level)

    logger.debug("Starting {}".format(DESCRIPTION))

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if 'current_version' in vcs_info:
        defaults['current_version'] = vcs_info['current_version']

    config = RawConfigParser('')

    # don't transform keys to lowercase (which would be the default)
    config.optionxform = lambda option: option

    config.add_section('bumpversion')

    explicit_config = hasattr(known_args, 'config_file')

    if explicit_config:
        config_file = known_args.config_file
    elif not os.path.exists('.bumpversion.cfg') and \
            os.path.exists('setup.cfg'):
        config_file = 'setup.cfg'
    else:
        config_file = '.bumpversion.cfg'

    config_file_exists = os.path.exists(config_file)

    part_configs = {}

    files = []

    if config_file_exists:

        logger.info("Reading config file {}:".format(config_file))
        logger.info(io.open(config_file, 'rt', encoding='utf-8').read())

        config.readfp(io.open(config_file, 'rt', encoding='utf-8'))

        log_config = StringIO()
        config.write(log_config)

        if 'files' in dict(config.items("bumpversion")):
            warnings.warn(
                "'files =' configuration is will be deprecated, please use [bumpversion:file:...]",
                PendingDeprecationWarning
            )

        defaults.update(dict(config.items("bumpversion")))

        for listvaluename in ("serialize",):
            try:
                value = config.get("bumpversion", listvaluename)
                defaults[listvaluename] = list(filter(None, (x.strip() for x in value.splitlines())))
            except NoOptionError:
                pass  # no default value then ;)

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean(
                    "bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

        for section_name in config.sections():

            section_name_match = re.compile("^bumpversion:(file|part):(.+)").match(section_name)

            if not section_name_match:
                continue

            section_prefix, section_value = section_name_match.groups()

            section_config = dict(config.items(section_name))

            if section_prefix == "part":

                ThisVersionPartConfiguration = NumericVersionPartConfiguration

                if 'values' in section_config:
                    section_config['values'] = list(filter(None, (x.strip() for x in section_config['values'].splitlines())))
                    ThisVersionPartConfiguration = ConfiguredVersionPartConfiguration

                part_configs[section_value] = ThisVersionPartConfiguration(**section_config)

            elif section_prefix == "file":

                filename = section_value

                if 'serialize' in section_config:
                    section_config['serialize'] = list(filter(None, (x.strip() for x in section_config['serialize'].splitlines())))

                section_config['part_configs'] = part_configs

                if not 'parse' in section_config:
                    section_config['parse'] = defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)')

                if not 'serialize' in section_config:
                    section_config['serialize'] = defaults.get('serialize', [str('{major}.{minor}.{patch}')])

                if not 'search' in section_config:
                    section_config['search'] = defaults.get("search", '{current_version}')

                if not 'replace' in section_config:
                    section_config['replace'] = defaults.get("replace", '{new_version}')

                files.append(ConfiguredFile(filename, VersionConfig(**section_config)))

    else:
        message = "Could not read config file at {}".format(config_file)
        if explicit_config:
            raise argparse.ArgumentTypeError(message)
        else:
            logger.info(message)

    parser2 = argparse.ArgumentParser(prog='bumpversion', add_help=False, parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated', required=False)
    parser2.add_argument('--parse', metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize', metavar='FORMAT',
                         action=DiscardDefaultIfSpecifiedAppendAction,
                         help='How to format what is parsed back to a version',
                         default=defaults.get("serialize", [str('{major}.{minor}.{patch}')]))
    parser2.add_argument('--search', metavar='SEARCH',
                         help='Template for complete string to search',
                         default=defaults.get("search", '{current_version}'))
    parser2.add_argument('--replace', metavar='REPLACE',
                         help='Template for complete string to replace',
                         default=defaults.get("replace", '{new_version}'))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    assert type(known_args.serialize) == list

    context = dict(list(time_context.items()) + list(prefixed_environ().items()) + list(vcs_info.items()))

    try:
        vc = VersionConfig(
            parse=known_args.parse,
            serialize=known_args.serialize,
            search=known_args.search,
            replace=known_args.replace,
            part_configs=part_configs,
        )
    except sre_constants.error as e:
        sys.exit(1)

    current_version = vc.parse(known_args.current_version) if known_args.current_version else None

    new_version = None

    if not 'new_version' in defaults and known_args.current_version:
        try:
            if current_version and len(positionals) > 0:
                logger.info("Attempting to increment part '{}'".format(positionals[0]))
                new_version = current_version.bump(positionals[0], vc.order())
                logger.info("Values are now: " + keyvaluestring(new_version._values))
                defaults['new_version'] = vc.serialize(new_version, context)
        except MissingValueForSerializationException as e:
            logger.info("Opportunistic finding of new_version failed: " + e.message)
        except IncompleteVersionRepresenationException as e:
            logger.info("Opportunistic finding of new_version failed: " + e.message)
        except KeyError as e:
            logger.info("Opportunistic finding of new_version failed")

    parser3 = argparse.ArgumentParser(
        prog='bumpversion',
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated',
                         required=not 'current_version' in defaults)
    parser3.add_argument('--dry-run', '-n', action='store_true',
                         default=False, help="Don't write any files, just pretend.")
    parser3.add_argument('--new-version', metavar='VERSION',
                         help='New version that should be in the files',
                         required=not 'new_version' in defaults)

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument('--commit', action='store_true', dest="commit",
                             help='Commit to version control', default=defaults.get("commit", False))
    commitgroup.add_argument('--no-commit', action='store_false', dest="commit",
                             help='Do not commit to version control', default=argparse.SUPPRESS)

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument('--tag', action='store_true', dest="tag", default=defaults.get("tag", False),
                          help='Create a tag in version control')
    taggroup.add_argument('--no-tag', action='store_false', dest="tag",
                          help='Do not create a tag in version control', default=argparse.SUPPRESS)

    parser3.add_argument('--tag-name', metavar='TAG_NAME',
                         help='Tag name (only works with --tag)',
                         default=defaults.get('tag_name', 'v{new_version}'))

    parser3.add_argument('--message', '-m', metavar='COMMIT_MSG',
                         help='Commit message',
                         default=defaults.get('message', 'Bump version: {current_version} → {new_version}'))


    file_names = []
    if 'files' in defaults:
        assert defaults['files'] != None
        file_names = defaults['files'].split(' ')

    parser3.add_argument('part',
                         help='Part of the version to be bumped.')
    parser3.add_argument('files', metavar='file',
                         nargs='*',
                         help='Files to change', default=file_names)

    args = parser3.parse_args(remaining_argv + positionals)

    if args.dry_run:
        logger.info("Dry run active, won't touch any files.")

    if args.new_version:
        new_version = vc.parse(args.new_version)

    logger.info("New version will be '{}'".format(args.new_version))

    file_names = file_names or positionals[1:]

    for file_name in file_names:
        files.append(ConfiguredFile(file_name, vc))

    for vcs in VCS:
        if vcs.is_usable():
            try:
                vcs.assert_nondirty()
            except WorkingDirectoryIsDirtyException as e:
                if not defaults['allow_dirty']:
                    logger.warn(
                        "{}\n\nUse --allow-dirty to override this if you know what you're doing.".format(e.message))
                    raise
            break
        else:
            vcs = None

    # make sure files exist and contain version string

    logger.info("Asserting files {} contain the version string:".format(", ".join([str(f) for f in files])))

    for f in files:
        f.should_contain_version(current_version, context)

    # change version string in files
    for f in files:
        f.replace(current_version, new_version, context, args.dry_run)

    commit_files = [f.path for f in files]

    config.set('bumpversion', 'new_version', args.new_version)

    for key, value in config.items('bumpversion'):
        logger_list.info("{}={}".format(key, value))

    config.remove_option('bumpversion', 'new_version')

    config.set('bumpversion', 'current_version', args.new_version)

    new_config = StringIO()

    try:
        write_to_config_file = (not args.dry_run) and config_file_exists

        logger.info("{} to config file {}:".format(
            "Would write" if not write_to_config_file else "Writing",
            config_file,
        ))

        config.write(new_config)
        logger.info(new_config.getvalue())

        if write_to_config_file:
            with io.open(config_file, 'wb') as f:
                f.write(new_config.getvalue().encode('utf-8'))

    except UnicodeEncodeError:
        warnings.warn(
            "Unable to write UTF-8 to config file, because of an old configparser version. "
            "Update with `pip install --upgrade configparser`."
        )

    if config_file_exists:
        commit_files.append(config_file)

    if not vcs:
        return

    assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(vcs.__name__)

    do_commit = (not args.dry_run) and args.commit
    do_tag = (not args.dry_run) and args.tag

    logger.info("{} {} commit".format(
        "Would prepare" if not do_commit else "Preparing",
        vcs.__name__,
    ))

    for path in commit_files:
        logger.info("{} changes in file '{}' to {}".format(
            "Would add" if not do_commit else "Adding",
            path,
            vcs.__name__,
        ))

        if do_commit:
            vcs.add_path(path)

    vcs_context = {
        "current_version": args.current_version,
        "new_version": args.new_version,
    }
    vcs_context.update(time_context)
    vcs_context.update(prefixed_environ())

    commit_message = args.message.format(**vcs_context)

    logger.info("{} to {} with message '{}'".format(
        "Would commit" if not do_commit else "Committing",
        vcs.__name__,
        commit_message,
    ))

    if do_commit:
        vcs.commit(message=commit_message)

    tag_name = args.tag_name.format(**vcs_context)
    logger.info("{} '{}' in {}".format(
        "Would tag" if not do_tag else "Tagging",
        tag_name,
        vcs.__name__
    ))

    if do_tag:
        vcs.tag(tag_name)
コード例 #23
0
class ConfigEditor:
    def __init__(self):
        self.config_parser = RawConfigParser()
        self.config_file = None

    def open(self, config_file):
        """
        Open and read a config file

        :param config_file: config file path
        """
        logger.debug('Opening {}'.format(config_file))
        self.config_file = config_file
        if os.access(config_file, os.R_OK):
            logger.debug('Parsing config file')
            self.config_parser.read(config_file)

    def read(self, section, option, fallback=None):
        """
        Returns a config option value from config file

        :param section: section where the option is stored
        :param option: option name
        :param fallback: (optional) fallback value
        :return: a config option value
        :rtype: string
        """
        if self.config_file == None:
            raise InvalidOperation('read')
        if fallback is None:
            return self.config_parser.get(section, option)
        else:
            return self.config_parser.get(section, option, fallback=fallback)

    def readboolean(self, section, option, fallback=False):
        """
        Returns a boolean config option value from config file

        :param section: section where the option is stored
        :param option: option name
        :param fallback: (optional) fallback value
        :return: a config option value
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('readboolean')
        return self.config_parser.getboolean(section,
                                             option,
                                             fallback=fallback)

    def write(self, section, option, value):
        """
        Write a config option value in config object

        :param section: section where the option is stored
        :param option: option name
        :param value: option value
        """
        if self.config_file == None:
            raise InvalidOperation('write')
        if section != 'DEFAULT' and not self.config_parser.has_section(
                section):
            logger.debug('Adding new section {}'.format(section))
            self.config_parser.add_section(section)
        logger.debug('Adding {}.{} with value {}'.format(
            section, option, value))
        self.config_parser.set(section, option, value)

    def remove(self, section, option):
        """
        Remove a config option in config object

        :param section: section where the option is stored
        :param option: option name
        :return: True if option is removed, False if not exist
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('remove')
        logger.debug('Removing {}.{}'.format(section, option))
        option_removed = self.config_parser.remove_option(section, option)
        if section != 'DEFAULT' and option_removed:
            if self.config_parser.items(section) == self.config_parser.items(
                    'DEFAULT'):
                logger.debug('Removing empty section {}'.format(section))
                self.config_parser.remove_section(section)
        return option_removed

    def remove_project(self, project):
        """
        Remove a project (config section in config object)

        :param project: section name
        :return: True if section is removed, False if not exist
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('remove')
        logger.debug('Removing {}'.format(project))
        return self.config_parser.remove_section(project)

    def list(self):
        """
        List config sections

        :return: list of projects (sections in config)
        :rtype: list
        """
        if self.config_file == None:
            raise InvalidOperation('list')
        return self.config_parser.sections()

    def list_enabled_projects(self):
        """
        Get the list of enabled projects

        :return: list of enabled projects
        :rtype: list
        """
        if self.config_file == None:
            raise InvalidOperation('list_enabled_projects')
        try:
            return self.config_parser.get('DEFAULT', 'sync_projects').split()
        except NoOptionError:
            return []

    def enable_project(self, project):
        """
        Enable a project adding it to sync_projects

        :param project: project name
        """
        if self.config_file == None:
            raise InvalidOperation('enable_project')
        logger.debug('Enabling project {}'.format(project))
        enabled_projects = self.list_enabled_projects()
        enabled_projects.append(project)
        enabled_projects.sort()
        self.config_parser.set('DEFAULT', 'sync_projects',
                               ' '.join(enabled_projects))

    def disable_project(self, project):
        """
        Disable a project removing it from sync_projects

        :param project: project name
        :return: True if project is disabled, False if not
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('disable_project')
        logger.debug('Disabling project {}'.format(project))
        enabled_projects = self.list_enabled_projects()
        try:
            enabled_projects.remove(project)
            self.config_parser.set('DEFAULT', 'sync_projects',
                                   ' '.join(enabled_projects))
            return True
        except ValueError:
            logger.debug(
                'Nothing to do, {} is not in enabled projects'.format(project))
            return False

    def has_project(self, project):
        """
        Check if a project (a section in config) is present

        :param project: section name
        :return: True if section exists, False if not
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('has_project')
        return self.config_parser.has_section(project)

    def has_project_enabled(self, project):
        """
        Check if a project is enabled

        :param project: project name
        :return: True if project is enabled, False if not
        :rtype: boolean
        """
        if self.config_file == None:
            raise InvalidOperation('has_project_enabled')
        return True if project in self.list_enabled_projects() else False

    def save(self):
        """
        Save the config object in config file
        """
        if self.config_file == None:
            raise InvalidOperation('save')
        logger.debug('Saving config in config file')
        with open(self.config_file, 'w') as configfile:
            self.config_parser.write(configfile)
        self.config_file = None

    def clean(self):
        """
        Cleans the config editor
        """
        logger.debug('Cleaning config editor')
        self.config_parser = RawConfigParser()
        self.config_file = None
コード例 #24
0
class ParamStore(object):
    def __init__(self, root_dir, file_name):
        self._lock = threading.Lock()
        with self._lock:
            if not os.path.isdir(root_dir):
                raise RuntimeError('Directory "' + root_dir +
                                   '" does not exist.')
            self._path = os.path.join(root_dir, file_name)
            self._dirty = False
            # open config file
            self._config = RawConfigParser()
            self._config.read(self._path)

    def flush(self):
        if not self._dirty:
            return
        with self._lock:
            self._dirty = False
            with open(self._path, 'w') as of:
                self._config.write(of)

    def get(self, section, option, default=None):
        """Get a parameter value and return a string.

        If default is specified and section or option are not defined
        in the file, they are created and set to default, which is
        then the return value.

        """
        with self._lock:
            if not self._config.has_option(section, option):
                if default is not None:
                    self._set(section, option, default)
                return default
            return self._config.get(section, option)

    def get_datetime(self, section, option, default=None):
        result = self.get(section, option, default)
        if result:
            return WSDateTime.from_csv(result)
        return result

    def set(self, section, option, value):
        """Set option in section to string value."""
        with self._lock:
            self._set(section, option, value)

    def _set(self, section, option, value):
        if not self._config.has_section(section):
            self._config.add_section(section)
        elif (self._config.has_option(section, option)
              and self._config.get(section, option) == value):
            return
        self._config.set(section, option, value)
        self._dirty = True

    def unset(self, section, option):
        """Remove option from section."""
        with self._lock:
            if not self._config.has_section(section):
                return
            if self._config.has_option(section, option):
                self._config.remove_option(section, option)
                self._dirty = True
            if not self._config.options(section):
                self._config.remove_section(section)
                self._dirty = True
コード例 #25
0
ファイル: __init__.py プロジェクト: niedbalski/bumpversion
def main(original_args=None):
    positionals, args = split_args_in_optional_and_positional(original_args)
    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument(
        "--config-file",
        default=".bumpversion.cfg",
        metavar="FILE",
        help="Config file to read most of the variables from",
        required=False,
    )

    known_args, remaining_argv = parser1.parse_known_args(args)

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if "current_version" in vcs_info:
        defaults["current_version"] = vcs_info["current_version"]

    config = None
    if os.path.exists(known_args.config_file):
        config = RawConfigParser()
        config.readfp(io.open(known_args.config_file, "rt", encoding="utf-8"))

        defaults.update(dict(config.items("bumpversion")))

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean("bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

    elif known_args.config_file != parser1.get_default("config_file"):
        raise argparse.ArgumentTypeError("Could not read config file at {}".format(known_args.config_file))

    parser2 = argparse.ArgumentParser(add_help=False, parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument(
        "--current-version", metavar="VERSION", help="Version that needs to be updated", required=False
    )
    parser2.add_argument(
        "--parse",
        metavar="REGEX",
        help="Regex parsing the version string",
        default="(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)",
    )
    parser2.add_argument(
        "--serialize",
        metavar="FORMAT",
        help="How to format what is parsed back to a version",
        default="{major}.{minor}.{patch}",
    )

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    time_context = {"now": datetime.now(), "utcnow": datetime.utcnow()}

    v = Version(
        known_args.parse,
        known_args.serialize,
        context=dict(list(time_context.items()) + list(prefixed_environ().items()) + list(vcs_info.items())),
    )

    if not "new_version" in defaults and known_args.current_version:
        v.parse(known_args.current_version)

        if len(positionals) > 0:
            v.bump(positionals[0])

        defaults["new_version"] = v.serialize()

    parser3 = argparse.ArgumentParser(
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler="resolve",
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument(
        "--current-version",
        metavar="VERSION",
        help="Version that needs to be updated",
        required=not "current_version" in defaults,
    )
    parser3.add_argument(
        "--dry-run", "-n", action="store_true", default=False, help="Don't write any files, just pretend."
    )
    parser3.add_argument(
        "--new-version",
        metavar="VERSION",
        help="New version that should be in the files",
        required=not "new_version" in defaults,
    )

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument(
        "--commit",
        action="store_true",
        dest="commit",
        help="Commit to version control",
        default=defaults.get("commit", False),
    )
    commitgroup.add_argument(
        "--no-commit",
        action="store_false",
        dest="commit",
        help="Do not commit to version control",
        default=argparse.SUPPRESS,
    )

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument(
        "--tag",
        action="store_true",
        dest="tag",
        default=defaults.get("tag", False),
        help="Create a tag in version control",
    )
    taggroup.add_argument(
        "--no-tag",
        action="store_false",
        dest="tag",
        help="Do not create a tag in version control",
        default=argparse.SUPPRESS,
    )

    parser3.add_argument(
        "--tag-name",
        metavar="TAG_NAME",
        help="Tag name (only works with --tag)",
        default=defaults.get("tag_name", "v{new_version}"),
    )

    parser3.add_argument(
        "--message",
        "-m",
        metavar="COMMIT_MSG",
        help="Commit message",
        default=defaults.get("message", "Bump version: {current_version} → {new_version}"),
    )

    files = []
    if "files" in defaults:
        assert defaults["files"] != None
        files = defaults["files"].split(" ")

    parser3.add_argument("part", help="Part of the version to be bumped.")
    parser3.add_argument("files", metavar="file", nargs="*", help="Files to change", default=files)

    args = parser3.parse_args(remaining_argv + positionals)

    files = files or positionals[1:]

    for vcs in VCS:
        if vcs.is_usable():
            vcs.assert_nondirty()
            break

    # make sure files exist and contain version string
    for path in files:
        with io.open(path, "rb") as f:
            before = f.read().decode("utf-8")

        assert args.current_version in before, "Did not find string {} in file {}".format(args.current_version, path)

    # change version string in files
    for path in files:
        with io.open(path, "rb") as f:
            before = f.read().decode("utf-8")

        # assert type(args.current_version) == bytes
        # assert type(args.new_version) == bytes

        after = before.replace(args.current_version, args.new_version)

        if not args.dry_run:
            with io.open(path, "wt", encoding="utf-8") as f:
                f.write(after)

    commit_files = files

    if config:
        config.remove_option("bumpversion", "new_version")

        config.set("bumpversion", "current_version", args.new_version)

        if not args.dry_run:
            s = StringIO()

            try:
                config.write(s)
                with io.open(known_args.config_file, "wb") as f:
                    f.write(s.getvalue().encode("utf-8"))
            except UnicodeEncodeError:
                warnings.warn(
                    "Unable to write UTF-8 to config file, because of an old configparser version. "
                    "Update with `pip install --upgrade configparser`."
                )

            commit_files.append(known_args.config_file)

    if args.commit:
        if not args.dry_run:
            for path in commit_files:
                vcs.add_path(path)

            vcs_context = {"current_version": args.current_version, "new_version": args.new_version}
            vcs_context.update(time_context)
            vcs_context.update(prefixed_environ())

            vcs.commit(message=args.message.format(**vcs_context))

            if args.tag:
                vcs.tag(args.tag_name.format(**vcs_context))
コード例 #26
0
ファイル: __init__.py プロジェクト: miloh/bumpversion
def main(original_args=None):

    positionals, args = split_args_in_optional_and_positional(
      sys.argv[1:] if original_args is None else original_args
    )

    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument(
        '--config-file', default='.bumpversion.cfg', metavar='FILE',
        help='Config file to read most of the variables from', required=False)

    parser1.add_argument(
        '--verbose', action='count', default=0,
        help='Print verbose logging to stderr', required=False)

    known_args, remaining_argv = parser1.parse_known_args(args)

    if len(logger.handlers) == 0:
        ch = logging.StreamHandler(sys.stderr)
        logformatter = logging.Formatter('%(message)s')
        ch.setFormatter(logformatter)
        logger.addHandler(ch)

    log_level = {
        0: logging.WARNING,
        1: logging.INFO,
        2: logging.DEBUG,
    }.get(known_args.verbose, logging.DEBUG)

    logger.setLevel(log_level)

    logger.debug("Starting {}".format(DESCRIPTION))

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if 'current_version' in vcs_info:
        defaults['current_version'] = vcs_info['current_version']

    config = None
    if os.path.exists(known_args.config_file):
        config = RawConfigParser()
        config.readfp(io.open(known_args.config_file, 'rt', encoding='utf-8'))

        log_config = StringIO()
        config.write(log_config)
        logger.info("Reading config file {}:".format(known_args.config_file))

        logger.info(log_config.getvalue())

        defaults.update(dict(config.items("bumpversion")))

        for listvaluename in ("serialize",):
            try:
                value = config.get("bumpversion", listvaluename)
                defaults[listvaluename] = list(filter(None, (x.strip() for x in value.splitlines())))
            except NoOptionError:
                pass  # no default value then ;)

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean(
                    "bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

    else:
        message = "Could not read config file at {}".format(known_args.config_file)
        if known_args.config_file != parser1.get_default('config_file'):
            raise argparse.ArgumentTypeError(message)
        else:
            logger.info(message)

    parser2 = argparse.ArgumentParser(add_help=False, parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated', required=False)
    parser2.add_argument('--parse', metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize', metavar='FORMAT',
                         action=DiscardDefaultIfSpecifiedAppendAction,
                         help='How to format what is parsed back to a version',
                         default=defaults.get("serialize", [str('{major}.{minor}.{patch}')]))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    assert type(known_args.serialize) == list

    time_context = {
        'now': datetime.now(),
        'utcnow': datetime.utcnow(),
    }

    try:
        v = Version(
            known_args.parse,
            known_args.serialize,
            context=dict(list(time_context.items()) + list(prefixed_environ().items()) + list(vcs_info.items()))
        )
    except sre_constants.error as e:
        sys.exit(1)

    if not 'new_version' in defaults and known_args.current_version:
        v.parse(known_args.current_version)

        if len(positionals) > 0:
            v.bump(positionals[0])

        try:
            defaults['new_version'] = v.serialize()
        except MissingValueForSerializationException as e:
            logger.info("Opportunistic finding of new_version failed: " + e.message)
        except IncompleteVersionRepresenationException as e:
            logger.info("Opportunistic finding of new_version failed: " + e.message)
        except KeyError as e:
            logger.info("Opportunistic finding of new_version failed")

    parser3 = argparse.ArgumentParser(
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated',
                         required=not 'current_version' in defaults)
    parser3.add_argument('--dry-run', '-n', action='store_true',
                         default=False, help="Don't write any files, just pretend.")
    parser3.add_argument('--new-version', metavar='VERSION',
                         help='New version that should be in the files',
                         required=not 'new_version' in defaults)

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument('--commit', action='store_true', dest="commit",
                             help='Commit to version control', default=defaults.get("commit", False))
    commitgroup.add_argument('--no-commit', action='store_false', dest="commit",
                             help='Do not commit to version control', default=argparse.SUPPRESS)

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument('--tag', action='store_true', dest="tag", default=defaults.get("tag", False),
                          help='Create a tag in version control')
    taggroup.add_argument('--no-tag', action='store_false', dest="tag",
                          help='Do not create a tag in version control', default=argparse.SUPPRESS)

    parser3.add_argument('--tag-name', metavar='TAG_NAME',
                         help='Tag name (only works with --tag)',
                         default=defaults.get('tag_name', 'v{new_version}'))

    parser3.add_argument('--message', '-m', metavar='COMMIT_MSG',
                         help='Commit message',
                         default=defaults.get('message', 'Bump version: {current_version} → {new_version}'))

    files = []
    if 'files' in defaults:
        assert defaults['files'] != None
        files = defaults['files'].split(' ')

    parser3.add_argument('part',
                         help='Part of the version to be bumped.')
    parser3.add_argument('files', metavar='file',
                         nargs='*',
                         help='Files to change', default=files)

    args = parser3.parse_args(remaining_argv + positionals)

    if args.dry_run:
        logger.info("Dry run active, won't touch any files.")

    logger.info("New version will be '{}'".format(args.new_version))

    files = files or positionals[1:]


    for vcs in VCS:
        if vcs.is_usable():
            vcs.assert_nondirty()
            break
        else:
            vcs = None

    # make sure files exist and contain version string

    logger.info("Asserting files {} contain string '{}':".format(", ".join(files), args.current_version))

    for path in files:
        with io.open(path, 'rb') as f:

            found_before = False

            for lineno, line in enumerate(f.readlines()):
                if args.current_version in line.decode('utf-8'):
                    found_before = True
                    logger.info("Found '{}' in {} at line {}: {}".format(args.current_version, path, lineno, line.decode('utf-8').rstrip()))

            assert found_before, 'Did not find string {} in file {}'.format(
                args.current_version, path)

    # change version string in files
    for path in files:
        with io.open(path, 'rb') as f:
            before = f.read().decode('utf-8')

        after = before.replace(args.current_version, args.new_version)

        logger.info("{} file {}:".format(
            "Would change" if args.dry_run else "Changing",
            path,
        ))
        logger.info("\n".join(list(unified_diff(before.splitlines(), after.splitlines(), lineterm="", fromfile="a/"+path, tofile="b/"+path))))

        if not args.dry_run:
            with io.open(path, 'wt', encoding='utf-8') as f:
                f.write(after)

    commit_files = files

    if config:
        config.remove_option('bumpversion', 'new_version')

        config.set('bumpversion', 'current_version', args.new_version)

        s = StringIO()

        try:
            config.write(s)

            logger.info("{} to config file {}:".format(
                "Would write" if args.dry_run else "Writing",
                known_args.config_file,
            ))
            logger.info(log_config.getvalue())

            if not args.dry_run:
                with io.open(known_args.config_file, 'wb') as f:
                    f.write(s.getvalue().encode('utf-8'))

        except UnicodeEncodeError:
            warnings.warn(
                "Unable to write UTF-8 to config file, because of an old configparser version. "
                "Update with `pip install --upgrade configparser`."
            )

        commit_files.append(known_args.config_file)

    if not vcs:
        return

    assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(vcs.__name__)

    do_commit = (not args.dry_run) and args.commit
    do_tag = (not args.dry_run) and args.tag

    logger.info("{} {} commit".format(
        "Would prepare" if not do_commit else "Preparing",
        vcs.__name__,
    ))

    for path in commit_files:
        logger.info("{} changes in file '{}' to {}".format(
            "Would add" if not do_commit else "Adding",
            path,
            vcs.__name__,
        ))

        if do_commit:
            vcs.add_path(path)

    vcs_context = {
        "current_version": args.current_version,
        "new_version": args.new_version,
    }
    vcs_context.update(time_context)
    vcs_context.update(prefixed_environ())

    commit_message = args.message.format(**vcs_context)

    logger.info("{} to {} with message '{}'".format(
        "Would commit" if not do_commit else "Committing",
        vcs.__name__,
        commit_message,
    ))

    if do_commit:
        vcs.commit(message=commit_message)

    tag_name = args.tag_name.format(**vcs_context)
    logger.info("{} '{}' in {}".format(
        "Would tag" if not do_tag else "Tagging",
        tag_name,
        vcs.__name__
    ))

    if do_tag:
        vcs.tag(tag_name)
コード例 #27
0
 def remove_option(self, option):
     return _RawConfigParser.remove_option(self, self._default_section, option)
コード例 #28
0
def main(args):
    config = ConfigParser({"htrc": False,
                           "sentences": "False"})
    config.read(args.config_file)

    if config.getboolean("main", "sentences"):
        from vsm.extensions.ldasentences import CorpusSent as Corpus
    else:
        from vsm.corpus import Corpus

    if args.lang is None:
        args.lang = []

    args.corpus_path = config.get("main", "corpus_file")
    c = Corpus.load(args.corpus_path)

    # check for htrc metadata
    if args.htrc or config.get("main", "htrc"):
        htrc_langs = get_htrc_langs(args)
        if htrc_langs:
            args.lang.extend(new_langs)

    # auto-guess a language
    """
    new_langs = [lang for lang in detect_langs(c) if lang in langs and lang not in args.lang]
    if new_langs:
        args.lang.extend(new_langs)
    """

    # add default locale if no other languages are specified
    # do not add if in quiet mode -- make everything explicit
    if not args.lang and not args.quiet:
        import locale
        locale = locale.getdefaultlocale()[0].split('_')[0].lower()
        if locale in langs.keys():
            args.lang.append(locale)

    # check for any new candidates
    args.lang = [lang for lang in args.lang if stop_language(c, langs[lang])]
    if args.lang and not args.quiet:
        args.lang = lang_prompt(args.lang)

    stoplist = set()
    # Apply stop words
    print(" ")
    for lang in args.lang:
        print("Applying", langs[lang], "stopwords")
        candidates = stop_language(c, langs[lang])
        if len(candidates):
            stoplist.update(candidates)

    # Apply custom stopwords file
    if args.stopword_file:
        with open(args.stopword_file, encoding='utf8') as swf:
            #candidates = [unidecode(word.strip()) for word in swf]
            candidates = [word.strip() for word in swf]

            if len(candidates):
                print("Applying custom stopword file to remove {} word{}.".format(
                    len(candidates), 's' if len(candidates) > 1 else ''))
                stoplist.update(candidates)

    if args.min_word_len:
        candidates = get_small_words(c, args.min_word_len)
        if len(candidates):
            print("Filtering {} small word{} with less than {} characters.".format(
                len(candidates), 's' if len(candidates) > 1 else '', args.min_word_len))
            stoplist.update(candidates)

    if not args.special_chars:
        candidates = get_special_chars(c)
        if len(candidates):
            print("Filtering {} word{} with special characters.".format(
                len(candidates), 's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)

    if args.high_filter is None and not args.quiet:
        args.high_filter, candidates = get_high_filter(args, c, words=stoplist)
        if len(candidates):
            print("Filtering {} high frequency word{}.".format(len(candidates),
                                                               's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)
    elif args.high_filter > 0:
        candidates = get_candidate_words(c, args.high_filter, sort=False)
        if len(candidates):
            print("Filtering {} high frequency word{}.".format(len(candidates),
                                                               's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)

    if args.low_filter is None and not args.quiet:
        args.low_filter, candidates = get_low_filter(args, c, words=stoplist)
        if len(candidates):
            print("Filtering {} low frequency word{}.".format(len(candidates),
                                                              's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)
    elif args.low_filter > 0:
        candidates = get_candidate_words(c, -1 * args.low_filter, sort=False)
        if len(candidates):
            print("Filtering {} low frequency words.".format(len(candidates)))
            stoplist.update(candidates)

    if not stoplist:
        print("No stopwords applied.\n\n")

        sys.exit(0)
    else:
        print("\n\nApplying {} stopword{}".format(len(stoplist),
                                                  's' if len(stoplist) > 1 else ''))
        c.in_place_stoplist(stoplist)
        print("\n")

    def name_corpus(dirname, languages, lowfreq=None, highfreq=None):
        items, counts = get_items_counts(c.corpus)

        corpus_name = [dirname]
        if args.lang:
            corpus_name.append('nltk')
            corpus_name.append(''.join(args.lang))
        if lowfreq > 0:
            corpus_name.append('freq%s' % lowfreq)
        else:
            corpus_name.append('freq%s' % min(counts))

        if highfreq > 0:
            corpus_name.append('N%s' % highfreq)
        else:
            corpus_name.append('freq%s' % max(counts))

        corpus_name = '-'.join(corpus_name)
        corpus_name += '.npz'
        return corpus_name

    dirname = os.path.basename(args.corpus_path).split('-nltk-')[0].replace('.npz', '')
    corpus_name = name_corpus(dirname, ['en'], args.low_filter, args.high_filter)

    model_path = os.path.dirname(args.corpus_path)
    args.corpus_path = os.path.join(model_path, corpus_name)
    c.save(args.corpus_path)

    config.set("main", "corpus_file", args.corpus_path)
    config.remove_option("main", "model_pattern")
    with open(args.config_file, 'w') as configfh:
        config.write(configfh)
コード例 #29
0
def main(original_args=None):

    positionals, args = split_args_in_optional_and_positional(
        sys.argv[1:] if original_args is None else original_args)

    if len(positionals[1:]) > 2:
        warnings.warn(
            "Giving multiple files on the command line will be deprecated, please use [bumpversion:file:...] in a config file.",
            PendingDeprecationWarning)

    parser1 = argparse.ArgumentParser(add_help=False)

    parser1.add_argument(
        '--config-file',
        metavar='FILE',
        default=argparse.SUPPRESS,
        required=False,
        help=
        'Config file to read most of the variables from (default: .bumpversion.cfg)'
    )

    parser1.add_argument('--verbose',
                         action='count',
                         default=0,
                         help='Print verbose logging to stderr',
                         required=False)

    parser1.add_argument('--list',
                         action='store_true',
                         default=False,
                         help='List machine readable information',
                         required=False)

    parser1.add_argument('--allow-dirty',
                         action='store_true',
                         default=False,
                         help="Don't abort if working directory is dirty",
                         required=False)

    known_args, remaining_argv = parser1.parse_known_args(args)

    logformatter = logging.Formatter('%(message)s')

    if len(logger.handlers) == 0:
        ch = logging.StreamHandler(sys.stderr)
        ch.setFormatter(logformatter)
        logger.addHandler(ch)

    if len(logger_list.handlers) == 0:
        ch2 = logging.StreamHandler(sys.stdout)
        ch2.setFormatter(logformatter)
        logger_list.addHandler(ch2)

    if known_args.list:
        logger_list.setLevel(1)

    log_level = {
        0: logging.WARNING,
        1: logging.INFO,
        2: logging.DEBUG,
    }.get(known_args.verbose, logging.DEBUG)

    logger.setLevel(log_level)

    logger.debug("Starting {}".format(DESCRIPTION))

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if 'current_version' in vcs_info:
        defaults['current_version'] = vcs_info['current_version']

    config = RawConfigParser('')

    # don't transform keys to lowercase (which would be the default)
    config.optionxform = lambda option: option

    config.add_section('bumpversion')

    explicit_config = hasattr(known_args, 'config_file')

    if explicit_config:
        config_file = known_args.config_file
    elif not os.path.exists('.bumpversion.cfg') and \
            os.path.exists('setup.cfg'):
        config_file = 'setup.cfg'
    else:
        config_file = '.bumpversion.cfg'

    config_file_exists = os.path.exists(config_file)

    part_configs = {}

    files = []

    if config_file_exists:

        logger.info("Reading config file {}:".format(config_file))
        logger.info(io.open(config_file, 'rt', encoding='utf-8').read())

        config.readfp(io.open(config_file, 'rt', encoding='utf-8'))

        log_config = StringIO()
        config.write(log_config)

        if 'files' in dict(config.items("bumpversion")):
            warnings.warn(
                "'files =' configuration is will be deprecated, please use [bumpversion:file:...]",
                PendingDeprecationWarning)

        defaults.update(dict(config.items("bumpversion")))

        for listvaluename in ("serialize", ):
            try:
                value = config.get("bumpversion", listvaluename)
                defaults[listvaluename] = list(
                    filter(None, (x.strip() for x in value.splitlines())))
            except NoOptionError:
                pass  # no default value then ;)

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean(
                    "bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

        for section_name in config.sections():

            section_name_match = re.compile(
                "^bumpversion:(file|part):(.+)").match(section_name)

            if not section_name_match:
                continue

            section_prefix, section_value = section_name_match.groups()

            section_config = dict(config.items(section_name))

            if section_prefix == "part":

                ThisVersionPartConfiguration = NumericVersionPartConfiguration

                if 'values' in section_config:
                    section_config['values'] = list(
                        filter(
                            None,
                            (x.strip()
                             for x in section_config['values'].splitlines())))
                    ThisVersionPartConfiguration = ConfiguredVersionPartConfiguration

                part_configs[section_value] = ThisVersionPartConfiguration(
                    **section_config)

            elif section_prefix == "file":

                filename = section_value

                if 'serialize' in section_config:
                    section_config['serialize'] = list(
                        filter(
                            None,
                            (x.strip()
                             for x in section_config['serialize'].splitlines()
                             )))

                section_config['part_configs'] = part_configs

                if not 'parse' in section_config:
                    section_config['parse'] = defaults.get(
                        "parse",
                        '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)')

                if not 'serialize' in section_config:
                    section_config['serialize'] = defaults.get(
                        'serialize', [str('{major}.{minor}.{patch}')])

                if not 'search' in section_config:
                    section_config['search'] = defaults.get(
                        "search", '{current_version}')

                if not 'replace' in section_config:
                    section_config['replace'] = defaults.get(
                        "replace", '{new_version}')

                files.append(
                    ConfiguredFile(filename, VersionConfig(**section_config)))

    else:
        message = "Could not read config file at {}".format(config_file)
        if explicit_config:
            raise argparse.ArgumentTypeError(message)
        else:
            logger.info(message)

    parser2 = argparse.ArgumentParser(prog='bumpversion',
                                      add_help=False,
                                      parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--current-version',
                         metavar='VERSION',
                         help='Version that needs to be updated',
                         required=False)
    parser2.add_argument('--parse',
                         metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get(
                             "parse",
                             '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize',
                         metavar='FORMAT',
                         action=DiscardDefaultIfSpecifiedAppendAction,
                         help='How to format what is parsed back to a version',
                         default=defaults.get(
                             "serialize", [str('{major}.{minor}.{patch}')]))
    parser2.add_argument('--search',
                         metavar='SEARCH',
                         help='Template for complete string to search',
                         default=defaults.get("search", '{current_version}'))
    parser2.add_argument('--replace',
                         metavar='REPLACE',
                         help='Template for complete string to replace',
                         default=defaults.get("replace", '{new_version}'))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    assert type(known_args.serialize) == list

    context = dict(
        list(time_context.items()) + list(prefixed_environ().items()) +
        list(vcs_info.items()))

    try:
        vc = VersionConfig(
            parse=known_args.parse,
            serialize=known_args.serialize,
            search=known_args.search,
            replace=known_args.replace,
            part_configs=part_configs,
        )
    except sre_constants.error as e:
        sys.exit(1)

    current_version = vc.parse(
        known_args.current_version) if known_args.current_version else None

    new_version = None

    if not 'new_version' in defaults and known_args.current_version:
        try:
            if current_version and len(positionals) > 0:
                logger.info("Attempting to increment part '{}'".format(
                    positionals[0]))
                new_version = current_version.bump(positionals[0], vc.order())
                logger.info("Values are now: " +
                            keyvaluestring(new_version._values))
                defaults['new_version'] = vc.serialize(new_version, context)
        except MissingValueForSerializationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except IncompleteVersionRepresenationException as e:
            logger.info("Opportunistic finding of new_version failed: " +
                        e.message)
        except KeyError as e:
            logger.info("Opportunistic finding of new_version failed")

    parser3 = argparse.ArgumentParser(
        prog='bumpversion',
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--current-version',
                         metavar='VERSION',
                         help='Version that needs to be updated',
                         required=not 'current_version' in defaults)
    parser3.add_argument('--dry-run',
                         '-n',
                         action='store_true',
                         default=False,
                         help="Don't write any files, just pretend.")
    parser3.add_argument('--new-version',
                         metavar='VERSION',
                         help='New version that should be in the files',
                         required=not 'new_version' in defaults)

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument('--commit',
                             action='store_true',
                             dest="commit",
                             help='Commit to version control',
                             default=defaults.get("commit", False))
    commitgroup.add_argument('--no-commit',
                             action='store_false',
                             dest="commit",
                             help='Do not commit to version control',
                             default=argparse.SUPPRESS)

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument('--tag',
                          action='store_true',
                          dest="tag",
                          default=defaults.get("tag", False),
                          help='Create a tag in version control')
    taggroup.add_argument('--no-tag',
                          action='store_false',
                          dest="tag",
                          help='Do not create a tag in version control',
                          default=argparse.SUPPRESS)

    signtagsgroup = parser3.add_mutually_exclusive_group()
    signtagsgroup.add_argument('--sign-tags',
                               action='store_true',
                               dest="sign_tags",
                               help='Sign tags if created',
                               default=defaults.get("sign_tags", False))
    signtagsgroup.add_argument('--no-sign-tags',
                               action='store_false',
                               dest="sign_tags",
                               help='Do not sign tags if created',
                               default=argparse.SUPPRESS)

    parser3.add_argument('--tag-name',
                         metavar='TAG_NAME',
                         help='Tag name (only works with --tag)',
                         default=defaults.get('tag_name', 'v{new_version}'))

    parser3.add_argument(
        '--tag-message',
        metavar='TAG_MESSAGE',
        dest='tag_message',
        help='Tag message',
        default=defaults.get(
            'tag_message', 'Bump version: {current_version} → {new_version}'))

    parser3.add_argument(
        '--message',
        '-m',
        metavar='COMMIT_MSG',
        help='Commit message',
        default=defaults.get(
            'message', 'Bump version: {current_version} → {new_version}'))

    file_names = []
    if 'files' in defaults:
        assert defaults['files'] != None
        file_names = defaults['files'].split(' ')

    parser3.add_argument('part', help='Part of the version to be bumped.')
    parser3.add_argument('files',
                         metavar='file',
                         nargs='*',
                         help='Files to change',
                         default=file_names)

    args = parser3.parse_args(remaining_argv + positionals)

    if args.dry_run:
        logger.info("Dry run active, won't touch any files.")

    if args.new_version:
        new_version = vc.parse(args.new_version)

    logger.info("New version will be '{}'".format(args.new_version))

    file_names = file_names or positionals[1:]

    for file_name in file_names:
        files.append(ConfiguredFile(file_name, vc))

    for vcs in VCS:
        if vcs.is_usable():
            try:
                vcs.assert_nondirty()
            except WorkingDirectoryIsDirtyException as e:
                if not defaults['allow_dirty']:
                    logger.warn(
                        "{}\n\nUse --allow-dirty to override this if you know what you're doing."
                        .format(e.message))
                    raise
            break
        else:
            vcs = None

    # make sure files exist and contain version string

    logger.info("Asserting files {} contain the version string:".format(
        ", ".join([str(f) for f in files])))

    for f in files:
        f.should_contain_version(current_version, context)

    # change version string in files
    for f in files:
        f.replace(current_version, new_version, context, args.dry_run)

    commit_files = [f.path for f in files]

    config.set('bumpversion', 'new_version', args.new_version)

    for key, value in config.items('bumpversion'):
        logger_list.info("{}={}".format(key, value))

    config.remove_option('bumpversion', 'new_version')

    config.set('bumpversion', 'current_version', args.new_version)

    new_config = StringIO()

    try:
        write_to_config_file = (not args.dry_run) and config_file_exists

        logger.info("{} to config file {}:".format(
            "Would write" if not write_to_config_file else "Writing",
            config_file,
        ))

        config.write(new_config)
        logger.info(new_config.getvalue())

        if write_to_config_file:
            with io.open(config_file, 'wb') as f:
                f.write(new_config.getvalue().encode('utf-8'))

    except UnicodeEncodeError:
        warnings.warn(
            "Unable to write UTF-8 to config file, because of an old configparser version. "
            "Update with `pip install --upgrade configparser`.")

    if config_file_exists:
        commit_files.append(config_file)

    if not vcs:
        return

    assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(
        vcs.__name__)

    do_commit = (not args.dry_run) and args.commit
    do_tag = (not args.dry_run) and args.tag

    logger.info("{} {} commit".format(
        "Would prepare" if not do_commit else "Preparing",
        vcs.__name__,
    ))

    for path in commit_files:
        logger.info("{} changes in file '{}' to {}".format(
            "Would add" if not do_commit else "Adding",
            path,
            vcs.__name__,
        ))

        if do_commit:
            vcs.add_path(path)

    vcs_context = {
        "current_version": args.current_version,
        "new_version": args.new_version,
    }
    vcs_context.update(time_context)
    vcs_context.update(prefixed_environ())

    commit_message = args.message.format(**vcs_context)

    logger.info("{} to {} with message '{}'".format(
        "Would commit" if not do_commit else "Committing",
        vcs.__name__,
        commit_message,
    ))

    if do_commit:
        vcs.commit(message=commit_message)

    sign_tags = args.sign_tags
    tag_name = args.tag_name.format(**vcs_context)
    tag_message = args.tag_message.format(**vcs_context)
    logger.info("{} '{}' {} in {} and {}".format(
        "Would tag" if not do_tag else "Tagging", tag_name,
        "with message '{}'".format(tag_message)
        if tag_message else "without message", vcs.__name__,
        "signing" if sign_tags else "not signing"))

    if do_tag:
        vcs.tag(sign_tags, tag_name, tag_message)
コード例 #30
0
ファイル: config.py プロジェクト: weblate/quodlibet
class Config:
    """A wrapper around RawConfigParser.

    Provides a ``defaults`` attribute of the same type which can be used
    to set default values.
    """
    def __init__(self, version=None, _defaults=True):
        """Use read() to read in an existing config file.

        version should be an int starting with 0 that gets incremented if you
        want to register a new upgrade function. If None, upgrade is disabled.
        """

        self._config = ConfigParser(dict_type=_sorted_dict)
        self.defaults = None
        if _defaults:
            self.defaults = Config(_defaults=False)
        self._version = version
        self._loaded_version = None
        self._upgrade_funcs = []

    def _do_upgrade(self, func):
        assert self._loaded_version is not None
        assert self._version is not None

        old_version = self._loaded_version
        new_version = self._version
        if old_version != new_version:
            print_d("Config upgrade: %d->%d (%r)" %
                    (old_version, new_version, func))
            func(self, old_version, new_version)

    def get_version(self):
        """Get the version of the loaded config file (for testing only)

        Raises Error if no file was loaded or versioning is disabled.
        """

        if self._version is None:
            raise Error("Versioning disabled")

        if self._loaded_version is None:
            raise Error("No file loaded")

        return self._loaded_version

    def register_upgrade_function(self, function):
        """Register an upgrade function that gets called at each read()
        if the current config version and the loaded version don't match.

        Can also be registered after read was called.

        function(config, old_version: int, new_version: int) -> None
        """

        if self._version is None:
            raise Error("Versioning disabled")

        self._upgrade_funcs.append(function)
        # after read(), so upgrade now
        if self._loaded_version is not None:
            self._do_upgrade(function)
        return function

    def reset(self, section, option):
        """Reset the value to the default state"""

        assert self.defaults is not None

        try:
            self._config.remove_option(section, option)
        except NoSectionError:
            pass

    def options(self, section):
        """Returns a list of options available in the specified section."""

        try:
            options = self._config.options(section)
        except NoSectionError:
            if self.defaults:
                return self.defaults.options(section)
            raise
        else:
            if self.defaults:
                try:
                    options.extend(self.defaults.options(section))
                    options = list_unique(options)
                except NoSectionError:
                    pass
            return options

    def get(self, section, option, default=_DEFAULT):
        """get(section, option[, default]) -> str

        If default is not given or set, raises Error in case of an error
        """

        try:
            return self._config.get(section, option)
        except Error:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.get(section, option)
                    except Error:
                        pass
                raise
            return default

    def gettext(self, *args, **kwargs):
        value = self.get(*args, **kwargs)
        # make sure there are no surrogates
        value.encode("utf-8")
        return value

    def getbytes(self, section, option, default=_DEFAULT):
        try:
            value = self._config.get(section, option)
            value = value.encode("utf-8", "surrogateescape")
            return value
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getbytes(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getboolean(self, section, option, default=_DEFAULT):
        """getboolean(section, option[, default]) -> bool

        If default is not given or set, raises Error in case of an error
        """

        try:
            return self._config.getboolean(section, option)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getboolean(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getint(self, section, option, default=_DEFAULT):
        """getint(section, option[, default]) -> int

        If default is not give or set, raises Error in case of an error
        """

        try:
            return int(self._config.getfloat(section, option))
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getint(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getfloat(self, section, option, default=_DEFAULT):
        """getfloat(section, option[, default]) -> float

        If default is not give or set, raises Error in case of an error
        """

        try:
            return self._config.getfloat(section, option)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getfloat(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def getstringlist(self, section, option, default=_DEFAULT):
        """getstringlist(section, option[, default]) -> list

        If default is not given or set, raises Error in case of an error.
        Gets a list of strings, using CSV to parse and delimit.
        """

        try:
            value = self._config.get(section, option)

            parser = csv.reader([value],
                                lineterminator='\n',
                                quoting=csv.QUOTE_MINIMAL)
            try:
                vals = next(parser)
            except (csv.Error, ValueError) as e:
                raise Error(e)
            return vals
        except Error as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getstringlist(section, option)
                    except Error:
                        pass
                raise Error(e)
            return default

    def setstringlist(self, section, option, values):
        """Saves a list of unicode strings using the csv module"""

        sw = StringIO()
        values = [str(v) for v in values]

        writer = csv.writer(sw, lineterminator='\n', quoting=csv.QUOTE_MINIMAL)
        writer.writerow(values)
        self.set(section, option, sw.getvalue())

    def setlist(self, section, option, values, sep=","):
        """Saves a list of str using ',' as a separator and \\ for escaping"""

        values = [str(v) for v in values]
        joined = join_escape(values, sep)
        self.set(section, option, joined)

    def getlist(self, section, option, default=_DEFAULT, sep=","):
        """Returns a str list saved with setlist()"""

        try:
            value = self._config.get(section, option)
            return split_escape(value, sep)
        except (Error, ValueError) as e:
            if default is _DEFAULT:
                if self.defaults is not None:
                    try:
                        return self.defaults.getlist(section, option, sep=sep)
                    except Error:
                        pass
                raise Error(e)
            return default

    def set(self, section, option, value):
        """Saves the string representation for the passed value

        Don't pass unicode, encode first.
        """

        if isinstance(value, bytes):
            raise TypeError("use setbytes")

        # RawConfigParser only allows string values but doesn't
        # scream if they are not (and it only fails before the
        # first config save..)
        if not isinstance(value, str):
            value = str(value)

        try:
            self._config.set(section, option, value)
        except NoSectionError:
            if self.defaults and self.defaults.has_section(section):
                self._config.add_section(section)
                self._config.set(section, option, value)
            else:
                raise

    def settext(self, section, option, value):
        value = str(value)

        # make sure there are no surrogates
        value.encode("utf-8")

        self.set(section, option, value)

    def setbytes(self, section, option, value):
        assert isinstance(value, bytes)

        value = value.decode("utf-8", "surrogateescape")

        self.set(section, option, value)

    def write(self, filename):
        """Write config to filename.

        Can raise EnvironmentError
        """

        assert isinstance(filename, fsnative)

        mkdir(os.path.dirname(filename))

        # temporary set the new version for saving
        if self._version is not None:
            self.add_section("__config__")
            self.set("__config__", "version", self._version)
        try:
            with atomic_save(filename, "wb") as fileobj:
                temp = StringIO()
                self._config.write(temp)
                data = temp.getvalue().encode("utf-8", "surrogateescape")
                fileobj.write(data)
        finally:
            if self._loaded_version is not None:
                self.set("__config__", "version", self._loaded_version)

    def clear(self):
        """Remove all sections."""

        for section in self._config.sections():
            self._config.remove_section(section)

    def is_empty(self):
        """Whether the config has any sections"""

        return not self._config.sections()

    def read(self, filename):
        """Reads the config from `filename` if the file exists,
        otherwise does nothing

        Can raise EnvironmentError, Error.
        """

        try:
            with open(filename, "rb") as fileobj:
                fileobj = StringIO(fileobj.read().decode(
                    "utf-8", "surrogateescape"))
                self._config.readfp(fileobj, filename)
        except (IOError, OSError):
            return

        # don't upgrade if we just created a new config
        if self._version is not None:
            self._loaded_version = self.getint("__config__", "version", -1)
            for func in self._upgrade_funcs:
                self._do_upgrade(func)

    def has_option(self, section, option):
        """If the given section exists, and contains the given option"""

        return self._config.has_option(
            section, option) or (self.defaults
                                 and self.defaults.has_option(section, option))

    def has_section(self, section):
        """If the given section exists"""

        return self._config.has_section(section) or (
            self.defaults and self.defaults.has_section(section))

    def remove_option(self, section, option):
        """Remove the specified option from the specified section

        Can raise Error.
        """

        return self._config.remove_option(section, option)

    def add_section(self, section):
        """Add a section named section to the instance if it not already
        exists."""

        if not self._config.has_section(section):
            self._config.add_section(section)
コード例 #31
0
ファイル: __init__.py プロジェクト: brouberol/bumpversion
def main(original_args=None):

    positionals, args = split_args_in_optional_and_positional(
      sys.argv[1:] if original_args is None else original_args
    )

    parser1 = argparse.ArgumentParser(add_help=False, prog='bumpversion')

    parser1.add_argument(
        '--config-file', default='.bumpversion.cfg', metavar='FILE',
        help='Config file to read most of the variables from', required=False)
    parser1.add_argument('-v', '--version', action='version',
                         version="%s %s" % (parser1.prog, __VERSION__))

    known_args, remaining_argv = parser1.parse_known_args(args)

    defaults = {}
    vcs_info = {}

    for vcs in VCS:
        if vcs.is_usable():
            vcs_info.update(vcs.latest_tag_info())

    if 'current_version' in vcs_info:
        defaults['current_version'] = vcs_info['current_version']

    config = None
    if os.path.exists(known_args.config_file):
        config = RawConfigParser()
        config.readfp(io.open(known_args.config_file, 'rt', encoding='utf-8'))

        defaults.update(dict(config.items("bumpversion")))

        for boolvaluename in ("commit", "tag", "dry_run"):
            try:
                defaults[boolvaluename] = config.getboolean(
                    "bumpversion", boolvaluename)
            except NoOptionError:
                pass  # no default value then ;)

    elif known_args.config_file != parser1.get_default('config_file'):
        raise argparse.ArgumentTypeError("Could not read config file at {}".format(
            known_args.config_file))

    parser2 = argparse.ArgumentParser(add_help=False, parents=[parser1])
    parser2.set_defaults(**defaults)

    parser2.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated', required=False)
    parser2.add_argument('--parse', metavar='REGEX',
                         help='Regex parsing the version string',
                         default=defaults.get("parse", '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'))
    parser2.add_argument('--serialize', metavar='FORMAT',
                         help='How to format what is parsed back to a version',
                         default=defaults.get("serialize", str('{major}.{minor}.{patch}')))

    known_args, remaining_argv = parser2.parse_known_args(args)

    defaults.update(vars(known_args))

    time_context = {
        'now': datetime.now(),
        'utcnow': datetime.utcnow(),
    }

    v = Version(
        known_args.parse,
        known_args.serialize,
        context=dict(list(time_context.items()) + list(prefixed_environ().items()) + list(vcs_info.items()))
    )

    if not 'new_version' in defaults and known_args.current_version:
        v.parse(known_args.current_version)

        if len(positionals) > 0:
            v.bump(positionals[0])

        defaults['new_version'] = v.serialize()

    parser3 = argparse.ArgumentParser(
        description=DESCRIPTION,
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        conflict_handler='resolve',
        parents=[parser2],
    )

    parser3.set_defaults(**defaults)

    parser3.add_argument('--current-version', metavar='VERSION',
                         help='Version that needs to be updated',
                         required=not 'current_version' in defaults)
    parser3.add_argument('--dry-run', '-n', action='store_true',
                         default=False, help="Don't write any files, just pretend.")
    parser3.add_argument('--new-version', metavar='VERSION',
                         help='New version that should be in the files',
                         required=not 'new_version' in defaults)

    commitgroup = parser3.add_mutually_exclusive_group()

    commitgroup.add_argument('--commit', action='store_true', dest="commit",
                             help='Commit to version control', default=defaults.get("commit", False))
    commitgroup.add_argument('--no-commit', action='store_false', dest="commit",
                             help='Do not commit to version control', default=argparse.SUPPRESS)

    taggroup = parser3.add_mutually_exclusive_group()

    taggroup.add_argument('--tag', action='store_true', dest="tag", default=defaults.get("tag", False),
                          help='Create a tag in version control')
    taggroup.add_argument('--no-tag', action='store_false', dest="tag",
                          help='Do not create a tag in version control', default=argparse.SUPPRESS)

    parser3.add_argument('--tag-name', metavar='TAG_NAME',
                         help='Tag name (only works with --tag)',
                         default=defaults.get('tag_name', 'v{new_version}'))

    parser3.add_argument('--message', '-m', metavar='COMMIT_MSG',
                         help='Commit message',
                         default=defaults.get('message', 'Bump version: {current_version} → {new_version}'))

    files = []
    if 'files' in defaults:
        assert defaults['files'] != None
        files = defaults['files'].split(' ')

    parser3.add_argument('part',
                         help='Part of the version to be bumped.')
    parser3.add_argument('files', metavar='file',
                         nargs='*',
                         help='Files to change', default=files)

    args = parser3.parse_args(remaining_argv + positionals)

    files = files or positionals[1:]

    for vcs in VCS:
        if vcs.is_usable():
            vcs.assert_nondirty()
            break

    # make sure files exist and contain version string
    for path in files:
        with io.open(path, 'rb') as f:
            before = f.read().decode('utf-8')

        assert args.current_version in before, 'Did not find string {} in file {}'.format(
            args.current_version, path)

    # change version string in files
    for path in files:
        with io.open(path, 'rb') as f:
            before = f.read().decode('utf-8')

        # assert type(args.current_version) == bytes
        # assert type(args.new_version) == bytes

        after = before.replace(args.current_version, args.new_version)

        if not args.dry_run:
            with io.open(path, 'wt', encoding='utf-8') as f:
                f.write(after)

    commit_files = files

    if config:
        config.remove_option('bumpversion', 'new_version')

        config.set('bumpversion', 'current_version', args.new_version)

        if not args.dry_run:
            s = StringIO()

            try:
                config.write(s)
                with io.open(known_args.config_file, 'wb') as f:
                    f.write(s.getvalue().encode('utf-8'))
            except UnicodeEncodeError:
                warnings.warn(
                    "Unable to write UTF-8 to config file, because of an old configparser version. "
                    "Update with `pip install --upgrade configparser`."
                )

            commit_files.append(known_args.config_file)

    if args.commit:

        assert vcs.is_usable(), "Did find '{}' unusable, unable to commit.".format(vcs.__name__)

        if not args.dry_run:
            for path in commit_files:
                vcs.add_path(path)

            vcs_context = {
                "current_version": args.current_version,
                "new_version": args.new_version,
            }
            vcs_context.update(time_context)
            vcs_context.update(prefixed_environ())

            vcs.commit(message=args.message.format(**vcs_context))

            if args.tag:
                vcs.tag(args.tag_name.format(**vcs_context))
コード例 #32
0
def main(args):
    config = ConfigParser({"htrc": False, "sentences": "False"})
    config.read(args.config_file)

    if config.getboolean("main", "sentences"):
        from vsm.extensions.ldasentences import CorpusSent as Corpus
    else:
        from vsm.corpus import Corpus

    if args.lang is None:
        args.lang = []

    args.corpus_path = config.get("main", "corpus_file")
    c = Corpus.load(args.corpus_path)

    # check for htrc metadata
    if args.htrc or config.get("main", "htrc"):
        htrc_langs = get_htrc_langs(args)
        if htrc_langs:
            args.lang.extend(new_langs)

    # auto-guess a language
    """
    new_langs = [lang for lang in detect_langs(c) if lang in langs and lang not in args.lang]
    if new_langs:
        args.lang.extend(new_langs)
    """

    # add default locale if no other languages are specified
    # do not add if in quiet mode -- make everything explicit
    if not args.lang and not args.quiet:
        import locale
        locale = locale.getdefaultlocale()[0].split('_')[0].lower()
        if locale in langs.keys():
            args.lang.append(locale)

    # check for any new candidates
    args.lang = [lang for lang in args.lang if stop_language(c, langs[lang])]
    if args.lang and not args.quiet:
        args.lang = lang_prompt(args.lang)

    stoplist = set()
    # Apply stop words
    print(" ")
    for lang in args.lang:
        print("Applying", langs[lang], "stopwords")
        candidates = stop_language(c, langs[lang])
        if len(candidates):
            stoplist.update(candidates)

    # Apply custom stopwords file
    if args.stopword_file:
        with open(args.stopword_file, encoding='utf8') as swf:
            #candidates = [unidecode(word.strip()) for word in swf]
            candidates = [word.strip() for word in swf]

            if len(candidates):
                print("Applying custom stopword file to remove {} word{}.".
                      format(len(candidates),
                             's' if len(candidates) > 1 else ''))
                stoplist.update(candidates)

    if args.min_word_len:
        candidates = get_small_words(c, args.min_word_len)
        if len(candidates):
            print("Filtering {} small word{} with less than {} characters.".
                  format(len(candidates), 's' if len(candidates) > 1 else '',
                         args.min_word_len))
            stoplist.update(candidates)

    if not args.special_chars:
        candidates = get_special_chars(c)
        if len(candidates):
            print("Filtering {} word{} with special characters.".format(
                len(candidates), 's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)

    if args.high_filter is None and not args.quiet:
        args.high_filter, candidates = get_high_filter(args, c, words=stoplist)
        if len(candidates):
            print("Filtering {} high frequency word{}.".format(
                len(candidates), 's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)
    elif args.high_filter > 0:
        candidates = get_candidate_words(c, args.high_filter, sort=False)
        if len(candidates):
            print("Filtering {} high frequency word{}.".format(
                len(candidates), 's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)

    if args.low_filter is None and not args.quiet:
        args.low_filter, candidates = get_low_filter(args, c, words=stoplist)
        if len(candidates):
            print("Filtering {} low frequency word{}.".format(
                len(candidates), 's' if len(candidates) > 1 else ''))
            stoplist.update(candidates)
    elif args.low_filter > 0:
        candidates = get_candidate_words(c, -1 * args.low_filter, sort=False)
        if len(candidates):
            print("Filtering {} low frequency words.".format(len(candidates)))
            stoplist.update(candidates)

    if not stoplist:
        print("No stopwords applied.\n\n")

        sys.exit(0)
    else:
        print("\n\nApplying {} stopword{}".format(
            len(stoplist), 's' if len(stoplist) > 1 else ''))
        c.in_place_stoplist(stoplist)
        print("\n")

    def name_corpus(dirname, languages, lowfreq=None, highfreq=None):
        items, counts = get_items_counts(c.corpus)

        corpus_name = [dirname]
        if args.lang:
            corpus_name.append('nltk')
            corpus_name.append(''.join(args.lang))
        if lowfreq > 0:
            corpus_name.append('freq%s' % lowfreq)
        else:
            corpus_name.append('freq%s' % min(counts))

        if highfreq > 0:
            corpus_name.append('N%s' % highfreq)
        else:
            corpus_name.append('freq%s' % max(counts))

        corpus_name = '-'.join(corpus_name)
        corpus_name += '.npz'
        return corpus_name

    dirname = os.path.basename(args.corpus_path).split('-nltk-')[0].replace(
        '.npz', '')
    corpus_name = name_corpus(dirname, ['en'], args.low_filter,
                              args.high_filter)

    model_path = os.path.dirname(args.corpus_path)
    args.corpus_path = os.path.join(model_path, corpus_name)
    c.save(args.corpus_path)

    config.set("main", "corpus_file", args.corpus_path)
    config.remove_option("main", "model_pattern")
    with open(args.config_file, 'w') as configfh:
        config.write(configfh)
コード例 #33
0
ファイル: storage.py プロジェクト: jim-easterbrook/pywws
class ParamStore(object):
    def __init__(self, root_dir, file_name):
        self._lock = threading.Lock()
        with self._lock:
            if not os.path.isdir(root_dir):
                raise RuntimeError(
                    'Directory "' + root_dir + '" does not exist.')
            self._path = os.path.join(root_dir, file_name)
            self._dirty = False
            # open config file
            self._config = RawConfigParser()
            self._config.read(self._path)

    def flush(self):
        if not self._dirty:
            return
        with self._lock:
            self._dirty = False
            with open(self._path, 'w') as of:
                self._config.write(of)

    def get(self, section, option, default=None):
        """Get a parameter value and return a string.

        If default is specified and section or option are not defined
        in the file, they are created and set to default, which is
        then the return value.

        """
        with self._lock:
            if not self._config.has_option(section, option):
                if default is not None:
                    self._set(section, option, default)
                return default
            return self._config.get(section, option)

    def get_datetime(self, section, option, default=None):
        result = self.get(section, option, default)
        if result:
            return WSDateTime.from_csv(result)
        return result

    def set(self, section, option, value):
        """Set option in section to string value."""
        with self._lock:
            self._set(section, option, value)

    def _set(self, section, option, value):
        if not self._config.has_section(section):
            self._config.add_section(section)
        elif (self._config.has_option(section, option) and
              self._config.get(section, option) == value):
            return
        self._config.set(section, option, value)
        self._dirty = True

    def unset(self, section, option):
        """Remove option from section."""
        with self._lock:
            if not self._config.has_section(section):
                return
            if self._config.has_option(section, option):
                self._config.remove_option(section, option)
                self._dirty = True
            if not self._config.options(section):
                self._config.remove_section(section)
                self._dirty = True