def test_override(monkeypatch, short, equals): """Test overriding env variables with command line. :param monkeypatch: pytest fixture. :param bool short: Use short arg names. :param bool equals: Use ['--key=val'] or ['-kval'] instead of ['--key', 'val']. """ monkeypatch.setenv("FAM_FFMPEG_BIN", "/tmp/ffmpeg") monkeypatch.setenv("FAM_VERBOSE", "False") if equals and short: argv = ["run", "-f/tmp/arg/ffmpeg", "-v"] elif equals: argv = ["run", "--ffmpeg-bin=/tmp/arg/ffmpeg", "--verbose"] else: argv = ["run", "--ffmpeg-bin", "/tmp/arg/ffmpeg", "--verbose"] actual = docoptcfg(DOCSTRING_FAM, argv, env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--ffmpeg-bin"] = "/tmp/arg/ffmpeg" expected["--verbose"] = True assert actual == expected actual = docoptcfg(DOCSTRING_FAM, ["run"], env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--ffmpeg-bin"] = "/tmp/ffmpeg" expected["--verbose"] = False assert actual == expected
def test_multi(monkeypatch, multi, set_key, set_key0, set_key1): """Test with repeatable non-boolean options. :param monkeypatch: pytest fixture. :param bool multi: Test with ... and without ... in docstring. :param str set_key: Set MULTI_KEY to this value if not None. :param str set_key0: Set MULTI_KEY0 to this value if not None. :param str set_key1: Set MULTI_KEY1 to this value if not None. """ monkeypatch.setattr("sys.argv", ["pytest", "1", "--flag"]) docstring = DOCSTRING_MULTI if multi else DOCSTRING_NOT_MULTI expected = EXPECTED_MULTI.copy() if multi else EXPECTED_NOT_MULTI.copy() expected["--flag"] = 1 if multi else True # Set variables. if set_key is not None: monkeypatch.setenv("MULTI_KEY", set_key) if set_key0 is not None: monkeypatch.setenv("MULTI_KEY0", set_key0) if set_key1 is not None: monkeypatch.setenv("MULTI_KEY1", set_key1) # Test not multi. if not multi: if set_key is not None: expected["--key"] = str(set_key) # Others are ignored. actual = docoptcfg(docstring, env_prefix="MULTI_") assert actual == expected return set_keys = (set_key is not None, set_key0 is not None, set_key1 is not None) if set_keys == (True, True, True): expected["--key"] = [set_key, set_key0, set_key1] elif set_keys == (True, True, False): expected["--key"] = [set_key, set_key0] elif set_keys == (True, False, False): expected["--key"] = [set_key] elif set_keys == (False, False, False): expected["--key"] = [] elif set_keys == (False, False, True): expected["--key"] = [] elif set_keys == (False, True, True): expected["--key"] = [set_key0, set_key1] elif set_keys == (False, True, False): expected["--key"] = [set_key0] elif set_keys == (True, False, True): expected["--key"] = [set_key] else: raise NotImplementedError actual = docoptcfg(docstring, env_prefix="MULTI_") assert actual == expected
def test_no_settable(): """Test with all options overridden by command line.""" actual = docoptcfg(DOCSTRING_MULTI, ['1', '--config=config.ini', '--flag', '--key=val'], env_prefix='MULTI_') expected = EXPECTED_MULTI.copy() expected['--config'] = 'config.ini' expected['--flag'] = 1 expected['--key'] = ['val'] assert actual == expected
def test_override(tmpdir, short, equals): """Test overriding config values with command line. :param tmpdir: pytest fixture. :param bool short: Use short arg names. :param bool equals: Use ['--key=val'] or ['-kval'] instead of ['--key', 'val']. """ config_file = tmpdir.join('config.ini') config_file.write( dedent("""\ [FlashAirMusic] ffmpeg-bin=/tmp/ffmpeg verbose=false """)) if equals and short: argv = ['run', '-c', str(config_file), '-f/tmp/arg/ffmpeg', '-v'] elif equals: argv = [ 'run', '-c', str(config_file), '--ffmpeg-bin=/tmp/arg/ffmpeg', '--verbose' ] else: argv = [ 'run', '-c', str(config_file), '--ffmpeg-bin', '/tmp/arg/ffmpeg', '--verbose' ] actual = docoptcfg(DOCSTRING_FAM, argv, config_option='--config') expected = EXPECTED_FAM.copy() expected['--config'] = str(config_file) expected['--ffmpeg-bin'] = '/tmp/arg/ffmpeg' expected['--verbose'] = True assert actual == expected actual = docoptcfg(DOCSTRING_FAM, ['run', '-c', str(config_file)], config_option='--config') expected = EXPECTED_FAM.copy() expected['--config'] = str(config_file) expected['--ffmpeg-bin'] = '/tmp/ffmpeg' expected['--verbose'] = False assert actual == expected
def test_docopt_default(monkeypatch, short): """Test compatibility with "default" feature in docopt. :param monkeypatch: pytest fixture. :param bool short: Use short arg names. """ monkeypatch.setenv("FAM_THREADS", "2") # Test override. actual = docoptcfg(DOCSTRING_FAM, ["run", "-t" if short else "--threads", "1"], env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--threads"] = "1" assert actual == expected # Test "default". actual = docoptcfg(DOCSTRING_FAM, ["run"], env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--threads"] = "2" assert actual == expected
def test_docopt_default(monkeypatch, short): """Test compatibility with "default" feature in docopt. :param monkeypatch: pytest fixture. :param bool short: Use short arg names. """ monkeypatch.setenv('FAM_THREADS', '2') # Test override. actual = docoptcfg(DOCSTRING_FAM, ['run', '-t' if short else '--threads', '1'], env_prefix='FAM_') expected = EXPECTED_FAM.copy() expected['--threads'] = '1' assert actual == expected # Test "default". actual = docoptcfg(DOCSTRING_FAM, ['run'], env_prefix='FAM_') expected = EXPECTED_FAM.copy() expected['--threads'] = '2' assert actual == expected
def test_fam(monkeypatch, tmpdir): """Make sure config file and environment variables aren't being handled. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. """ monkeypatch.setenv('FFMPEG_BIN', tmpdir.ensure('ffmpeg')) tmpdir.join('config.ini').write('[FlashAirMusic]\nmac-addr = 00:11:22:33:44:55') actual = docoptcfg(DOCSTRING_FAM, ['run', '--config', str(tmpdir.join('config.ini'))]) expected = EXPECTED_FAM.copy() expected['--config'] = str(tmpdir.join('config.ini')) assert actual == expected
def test_multi(monkeypatch, tmpdir): """Same with multi options. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. """ monkeypatch.setenv('FFMPEG_BIN', tmpdir.ensure('ffmpeg')) tmpdir.join('config.ini').write('[my_script]\nkey = \n val1,\n val2') actual = docoptcfg(DOCSTRING_MULTI, ['1', '--config', str(tmpdir.join('config.ini'))]) expected = EXPECTED_MULTI.copy() expected['--config'] = str(tmpdir.join('config.ini')) assert actual == expected
def test_multi_a_lot(monkeypatch): """Test setting >99 env variables. For branch coverage. :param monkeypatch: pytest fixture. """ expected = EXPECTED_MULTI.copy() monkeypatch.setenv("MULTI_FLAG", "1") # Ignore. for i in range(100): monkeypatch.setenv("MULTI_KEY{0}".format(i), str(i)) if i < 99: expected["--key"].append(str(i)) actual = docoptcfg(DOCSTRING_MULTI, ["1"], ignore=("-h", "-V", "--flag"), env_prefix="MULTI_") assert actual == expected assert "MULTI_KEY99" in os.environ assert "99" not in actual["--key"]
def test_data_types(monkeypatch, tmpdir, source, data_type): """Ensure all sources produce the exact same non-boolean data types and values. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. :param source: Config source to test. :param data_type: Data type to test. """ argv = ["run"] expected = EXPECTED_FAM.copy() if source == "file": config_file = tmpdir.join("config.ini") if data_type == "str": config_file.write("[FlashAirMusic]\nmac-addr = one") elif data_type == "int": config_file.write("[FlashAirMusic]\nmac-addr = 1") else: config_file.write("[FlashAirMusic]\nmac-addr = 2.3") monkeypatch.setenv("FAM_CONFIG", str(config_file)) expected["--config"] = str(config_file) elif source == "env": if data_type == "str": monkeypatch.setenv("FAM_MAC_ADDR", "one") elif data_type == "int": monkeypatch.setenv("FAM_MAC_ADDR", "1") else: monkeypatch.setenv("FAM_MAC_ADDR", "2.3") else: if data_type == "str": argv.extend(["--mac-addr", "one"]) elif data_type == "int": argv.extend(["--mac-addr", "1"]) else: argv.extend(["--mac-addr", "2.3"]) # Set expected. if data_type == "str": expected["--mac-addr"] = "one" elif data_type == "int": expected["--mac-addr"] = "1" else: expected["--mac-addr"] = "2.3" actual = docoptcfg(DOCSTRING_FAM, argv, config_option="-c", env_prefix="FAM_") assert actual == expected
def test_data_types(monkeypatch, tmpdir, source, data_type): """Ensure all sources produce the exact same non-boolean data types and values. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. :param source: Config source to test. :param data_type: Data type to test. """ argv = ['run'] expected = EXPECTED_FAM.copy() if source == 'file': config_file = tmpdir.join('config.ini') if data_type == 'str': config_file.write('[FlashAirMusic]\nmac-addr = one') elif data_type == 'int': config_file.write('[FlashAirMusic]\nmac-addr = 1') else: config_file.write('[FlashAirMusic]\nmac-addr = 2.3') monkeypatch.setenv('FAM_CONFIG', str(config_file)) expected['--config'] = str(config_file) elif source == 'env': if data_type == 'str': monkeypatch.setenv('FAM_MAC_ADDR', 'one') elif data_type == 'int': monkeypatch.setenv('FAM_MAC_ADDR', '1') else: monkeypatch.setenv('FAM_MAC_ADDR', '2.3') else: if data_type == 'str': argv.extend(['--mac-addr', 'one']) elif data_type == 'int': argv.extend(['--mac-addr', '1']) else: argv.extend(['--mac-addr', '2.3']) # Set expected. if data_type == 'str': expected['--mac-addr'] = 'one' elif data_type == 'int': expected['--mac-addr'] = '1' else: expected['--mac-addr'] = '2.3' actual = docoptcfg(DOCSTRING_FAM, argv, config_option='-c', env_prefix='FAM_') assert actual == expected
def test_multi_a_lot(monkeypatch): """Test setting >99 env variables. For branch coverage. :param monkeypatch: pytest fixture. """ expected = EXPECTED_MULTI.copy() monkeypatch.setenv('MULTI_FLAG', '1') # Ignore. for i in range(100): monkeypatch.setenv('MULTI_KEY{0}'.format(i), str(i)) if i < 99: expected['--key'].append(str(i)) actual = docoptcfg(DOCSTRING_MULTI, ['1'], ignore=('-h', '-V', '--flag'), env_prefix='MULTI_') assert actual == expected assert 'MULTI_KEY99' in os.environ assert '99' not in actual['--key']
def test_config_file_in_env(monkeypatch, tmpdir): """Test specifying a config file using only env variables. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. """ config_file = tmpdir.join('config.ini') config_file.write(dedent("""\ [FlashAirMusic] mac-addr = AA:BB:CC:DD:EE:FF """)) monkeypatch.setenv('FAM_CONFIG', str(config_file)) actual = docoptcfg(DOCSTRING_FAM, ['run'], config_option='-c', env_prefix='FAM_') expected = EXPECTED_FAM.copy() expected['--config'] = str(config_file) expected['--mac-addr'] = 'AA:BB:CC:DD:EE:FF' assert actual == expected
def test_override(monkeypatch, tmpdir, set_arg, set_env, set_file): """Test source overrides. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. :param bool set_arg: Set value in command line arguments. :param bool set_env: Set value in environment variables. :param bool set_file: Set value in config file. """ config_file = tmpdir.join("config.ini") config_file.write( dedent( """\ [FlashAirMusic] quiet = true {0} """ ).format("ffmpeg-bin = ffmpeg_file" if set_file else "") ) monkeypatch.setenv("FAM_CONFIG", str(config_file)) monkeypatch.setenv("FAM_VERBOSE", "true") if set_env: monkeypatch.setenv("FAM_FFMPEG_BIN", "ffmpeg_env") argv = ["run", "-m", "00:11:22:33:44:55"] + (["--ffmpeg-bin", "ffmpeg_arg"] if set_arg else []) actual = docoptcfg(DOCSTRING_FAM, argv, config_option="-c", env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--config"] = str(config_file) expected["--mac-addr"] = "00:11:22:33:44:55" expected["--quiet"] = True expected["--verbose"] = True if set_arg: expected["--ffmpeg-bin"] = "ffmpeg_arg" elif set_env: expected["--ffmpeg-bin"] = "ffmpeg_env" elif set_file: expected["--ffmpeg-bin"] = "ffmpeg_file" assert actual == expected
def test_config_section_is_missing_from_default_config_file(tmpdir): """Test not failing if config section is missing from default config file. :param tmpdir: pytest fixture. """ config_file = tmpdir.ensure('config.ini') config_file.write(dedent("""\ [foobar] bar=baz """)) config_file_path = str(config_file) docstring = DOCSTRING_DEFAULT_CONFIGFILE.replace( '/skdjfgksdhfgsdfgjshdf.ini', config_file_path) expected = EXPECTED_DEFAULT_CONFIGFILE.copy() expected['--config'] = config_file_path actual = docoptcfg(docstring, argv=['--foo', 'bar', '1'], ignore_missing_default_config=True, config_option='--config') assert actual == expected
def test(monkeypatch, set_config, set_verbose): """Test with env variables. :param monkeypatch: pytest fixture. :param str set_config: Set FAM_CONFIG to this value if not None. :param str set_verbose: Set FAM_VERBOSE to this value if not None. """ monkeypatch.setenv("FAM_HELP", "True") monkeypatch.setenv("FAM_VERSION", "True") expected = EXPECTED_FAM.copy() if set_config is not None: expected["--config"] = str(set_config) monkeypatch.setenv("FAM_CONFIG", set_config) if set_verbose is not None: if set_verbose.strip().lower() in ("true", "yes", "on", "1"): expected["--verbose"] = True monkeypatch.setenv("FAM_VERBOSE", set_verbose) actual = docoptcfg(DOCSTRING_FAM, ["run"], env_prefix="FAM_") assert actual == expected
def test(monkeypatch, set_config, set_verbose): """Test with env variables. :param monkeypatch: pytest fixture. :param str set_config: Set FAM_CONFIG to this value if not None. :param str set_verbose: Set FAM_VERBOSE to this value if not None. """ monkeypatch.setenv('FAM_HELP', 'True') monkeypatch.setenv('FAM_VERSION', 'True') expected = EXPECTED_FAM.copy() if set_config is not None: expected['--config'] = str(set_config) monkeypatch.setenv('FAM_CONFIG', set_config) if set_verbose is not None: if set_verbose.strip().lower() in ('true', 'yes', 'on', '1'): expected['--verbose'] = True monkeypatch.setenv('FAM_VERBOSE', set_verbose) actual = docoptcfg(DOCSTRING_FAM, ['run'], env_prefix='FAM_') assert actual == expected
def test_config_file_in_env(monkeypatch, tmpdir): """Test specifying a config file using only env variables. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. """ config_file = tmpdir.join("config.ini") config_file.write( dedent( """\ [FlashAirMusic] mac-addr = AA:BB:CC:DD:EE:FF """ ) ) monkeypatch.setenv("FAM_CONFIG", str(config_file)) actual = docoptcfg(DOCSTRING_FAM, ["run"], config_option="-c", env_prefix="FAM_") expected = EXPECTED_FAM.copy() expected["--config"] = str(config_file) expected["--mac-addr"] = "AA:BB:CC:DD:EE:FF" assert actual == expected
def test_override(monkeypatch, tmpdir, set_arg, set_env, set_file): """Test source overrides. :param monkeypatch: pytest fixture. :param tmpdir: pytest fixture. :param bool set_arg: Set value in command line arguments. :param bool set_env: Set value in environment variables. :param bool set_file: Set value in config file. """ config_file = tmpdir.join('config.ini') config_file.write(dedent("""\ [FlashAirMusic] quiet = true {0} """).format('ffmpeg-bin = ffmpeg_file' if set_file else '')) monkeypatch.setenv('FAM_CONFIG', str(config_file)) monkeypatch.setenv('FAM_VERBOSE', 'true') if set_env: monkeypatch.setenv('FAM_FFMPEG_BIN', 'ffmpeg_env') argv = ['run', '-m', '00:11:22:33:44:55'] + (['--ffmpeg-bin', 'ffmpeg_arg'] if set_arg else []) actual = docoptcfg(DOCSTRING_FAM, argv, config_option='-c', env_prefix='FAM_') expected = EXPECTED_FAM.copy() expected['--config'] = str(config_file) expected['--mac-addr'] = '00:11:22:33:44:55' expected['--quiet'] = True expected['--verbose'] = True if set_arg: expected['--ffmpeg-bin'] = 'ffmpeg_arg' elif set_env: expected['--ffmpeg-bin'] = 'ffmpeg_env' elif set_file: expected['--ffmpeg-bin'] = 'ffmpeg_file' assert actual == expected
def test_multi_flag(monkeypatch, multi, set_flag): """Test with repeatable flag/boolean option. :param monkeypatch: pytest fixture. :param bool multi: Test with ... and without ... in docstring. :param str set_flag: Set MULTI_FLAG to this value if not None. """ monkeypatch.setattr("sys.argv", ["pytest", "1"]) docstring = DOCSTRING_MULTI if multi else DOCSTRING_NOT_MULTI expected = EXPECTED_MULTI.copy() if multi else EXPECTED_NOT_MULTI.copy() if set_flag is not None: monkeypatch.setenv("MULTI_FLAG", set_flag) if not multi and set_flag == "1": expected["--flag"] = True elif not multi: expected["--flag"] = False elif set_flag.isdigit(): expected["--flag"] = int(set_flag) else: expected["--flag"] = 0 actual = docoptcfg(docstring, env_prefix="MULTI_") assert actual == expected
def test_multi_flag(monkeypatch, multi, set_flag): """Test with repeatable flag/boolean option. :param monkeypatch: pytest fixture. :param bool multi: Test with ... and without ... in docstring. :param str set_flag: Set MULTI_FLAG to this value if not None. """ monkeypatch.setattr('sys.argv', ['pytest', '1']) docstring = DOCSTRING_MULTI if multi else DOCSTRING_NOT_MULTI expected = EXPECTED_MULTI.copy() if multi else EXPECTED_NOT_MULTI.copy() if set_flag is not None: monkeypatch.setenv('MULTI_FLAG', set_flag) if not multi and set_flag == '1': expected['--flag'] = True elif not multi: expected['--flag'] = False elif set_flag.isdigit(): expected['--flag'] = int(set_flag) else: expected['--flag'] = 0 actual = docoptcfg(docstring, env_prefix='MULTI_') assert actual == expected
def main(): arguments = docoptcfg(__doc__, env_prefix='GITLAB_') gitlab_token = arguments.get('--token') gitlab_group = arguments.get('--group') gitlab_config = arguments.get('--config') gitlab_host = arguments.get('--host') gitlab_server = arguments.get('--server') dry_run = arguments.get('--dry-run') verbose = arguments.get('--verbose') logging.basicConfig(level=(50 - verbose*10)) config = toml.load(gitlab_config) if gitlab_server is None: gitlab_server = config['gitlab_admin']['default_server'] if gitlab_host is None: gitlab_host = config['servers'][gitlab_server]['host'] if gitlab_token is None: gitlab_token = config['servers'][gitlab_server]['token'] if gitlab_group is None: gitlab_group = config['gitlab_admin']['default_group'] assert gitlab_host, "GITLAB_HOST not defined, export an ENV var or pass command line argument" assert gitlab_token, "GITLAB_TOKEN not defined, export an ENV var or pass command line argument" assert gitlab_group, "GITLAB_GROUP not defined, export an ENV var or pass command line argument" gl = gitlab.Gitlab('https://' + gitlab_host, gitlab_token, api_version=4, ssl_verify=SSL_VERIFY) group = gl.groups.get(gitlab_group) all_groups = gl.groups.list(all=True) sub_groups = recurse_subgroups(all_groups, group) for sg in sub_groups: for project in sg.projects.list(): apply_rules(project, config) for project in group.projects.list(): apply_rules(project, config, dry_run)
for project in project_list] project_zone_list = [ (project_name, zone, cache_dir, refresh_cache) for project_name, zone_list in pool_workers.map_async( get_project_zone_list, param_list).get(timeout) for zone in zone_list ] instance_list = [] for project_zone_instances in pool_workers.map_async( get_project_zone_instances, project_zone_list).get(timeout): instance_list.extend(project_zone_instances) inventory_json = get_inventory(instance_list) print(json.dumps(inventory_json, sort_keys=True, indent=2)) if __name__ == "__main__": log.basicConfig(filename='gce_googleapiclient.log', level=log.ERROR) try: ARGS = docoptcfg(__doc__, config_option='--config', env_prefix=ENV_PREFIX) except DocoptcfgFileError as exc: log.info('Failed reading: %s', str(exc)) ARGS = docoptcfg(__doc__, env_prefix=ENV_PREFIX) main(ARGS)
def main(): args = docoptcfg(__doc__, env_prefix="SLACKEMAILDIGEST_", config_option='--config') # process args tz_str = args['--timezone'] tz = pytz.timezone(tz_str) # for date, make naive timetuples, use calendar.timegm to convert them to # the proper timestamps (which are always UTC) if args['--date']: date = datetime.datetime.strptime(args['--date'], '%Y-%m-%d') date = tz.localize(date) else: now_utc = pytz.utc.localize(datetime.datetime.utcfromtimestamp(time.time())) now_tz = now_utc.astimezone(tz) yesterday_tz = now_tz - datetime.timedelta(days=1) date = yesterday_tz.replace(hour=0, minute=0, second=0, microsecond=0) start_ts = calendar.timegm(date.utctimetuple()) end_ts = calendar.timegm((date + datetime.timedelta(days=1)).utctimetuple()) # work-around docoptcfg not taking required arguments from a config file for required in ['--token', '--from', '--to']: if not args[required]: sys.exit("Must provide {}".format(required)) token = args['--token'] verbose = args['--verbose'] delivery = args['--delivery'] from_email = args['--from'] to = args['--to'] from_name = args['--from-name'] delay = int(args['--delay']) slack_channel = args['--channel'] invite_link = args['--invite-link'] if delivery not in delivery_methods: sys.exit("Unknown delivery method: %s" % (delivery,)) # scrape print("Fetching Slack messages for #%s from %s (%s) to %s (%s) " % ( slack_channel, pytz.utc.localize(datetime.datetime.utcfromtimestamp(start_ts)).astimezone(tz), pytz.utc.localize(datetime.datetime.utcfromtimestamp(start_ts)).astimezone(tz).strftime("%Z"), pytz.utc.localize(datetime.datetime.utcfromtimestamp(end_ts)).astimezone(tz), pytz.utc.localize(datetime.datetime.utcfromtimestamp(end_ts)).astimezone(tz).strftime("%Z"), ), file=sys.stderr) scraper = SlackScraper(token, verbose=verbose) scraper.set_invite_link(invite_link) team_id = scraper.get_team_id() channel_id = scraper.get_channel_id(slack_channel) hist = scraper.get_channel_history( slack_channel, oldest=start_ts, latest=end_ts, ) hist.sort(key=lambda msg: float(msg['ts'])) html_renderer = HTMLRenderer(scraper, tz) email_renderer = EmailRenderer(html_renderer) # render emails, replying to the last day's digest, and setting the last # id to be reply-able from the next day's digest emails = email_renderer.render_digest_emails( hist, date, team_id, channel_id, ) for email in emails: email['sender'] = ("%s <%s>" % (from_name, from_email)) if from_name else from_email email['to'] = to delivery_method = delivery_methods[delivery] print("Delivering in %d parts... via %s" % (len(emails), delivery_method.__name__), file=sys.stderr) for email in emails: delivery_method(args, email) for _ in progress.bar(range(delay), label="Waiting to send next message... "): time.sleep(1)
def test_none(): """Test when user doesn't specify a config file.""" expected = EXPECTED_FAM.copy() actual = docoptcfg(DOCSTRING_FAM, ['run'], config_option='--config') assert actual == expected
def main(): args = docoptcfg(__doc__, env_prefix="SLACKEMAILDIGEST_", config_option='--config') # process args tz_str = args['--timezone'] tz = pytz.timezone(tz_str) # for date, make naive timetuples, use calendar.timegm to convert them to # the proper timestamps (which are always UTC) if args['--date']: date = datetime.datetime.strptime(args['--date'], '%Y-%m-%d') date = tz.localize(date) else: now_utc = pytz.utc.localize( datetime.datetime.utcfromtimestamp(time.time())) now_tz = now_utc.astimezone(tz) yesterday_tz = now_tz - datetime.timedelta(days=1) date = yesterday_tz.replace(hour=0, minute=0, second=0, microsecond=0) start_ts = calendar.timegm(date.utctimetuple()) end_ts = calendar.timegm( (date + datetime.timedelta(days=1)).utctimetuple()) # work-around docoptcfg not taking required arguments from a config file for required in ['--token', '--from', '--to']: if not args[required]: sys.exit("Must provide {}".format(required)) token = args['--token'] verbose = args['--verbose'] delivery = args['--delivery'] from_email = args['--from'] to = args['--to'] from_name = args['--from-name'] delay = int(args['--delay']) slack_channel = args['--channel'] invite_link = args['--invite-link'] if delivery not in delivery_methods: sys.exit("Unknown delivery method: %s" % (delivery, )) # scrape print("Fetching Slack messages for #%s from %s (%s) to %s (%s) " % ( slack_channel, pytz.utc.localize( datetime.datetime.utcfromtimestamp(start_ts)).astimezone(tz), pytz.utc.localize(datetime.datetime.utcfromtimestamp( start_ts)).astimezone(tz).strftime("%Z"), pytz.utc.localize( datetime.datetime.utcfromtimestamp(end_ts)).astimezone(tz), pytz.utc.localize(datetime.datetime.utcfromtimestamp( end_ts)).astimezone(tz).strftime("%Z"), ), file=sys.stderr) scraper = SlackScraper(token, verbose=verbose) scraper.set_invite_link(invite_link) team_id = scraper.get_team_id() channel_id = scraper.get_channel_id(slack_channel) hist = scraper.get_channel_history( slack_channel, oldest=start_ts, latest=end_ts, ) hist.sort(key=lambda msg: float(msg['ts'])) html_renderer = HTMLRenderer(scraper, tz) email_renderer = EmailRenderer(html_renderer) # render emails, replying to the last day's digest, and setting the last # id to be reply-able from the next day's digest emails = email_renderer.render_digest_emails( hist, date, team_id, channel_id, ) for email in emails: email['sender'] = ( "%s <%s>" % (from_name, from_email)) if from_name else from_email email['to'] = to delivery_method = delivery_methods[delivery] print("Delivering in %d parts... via %s" % (len(emails), delivery_method.__name__), file=sys.stderr) for email in emails: delivery_method(args, email) for _ in progress.bar(range(delay), label="Waiting to send next message... "): time.sleep(1)
def test_errors(tmpdir): """Test error handling. :param tmpdir: pytest fixture. """ config_file = tmpdir.join('config.ini') argv = ['run', '-c', str(config_file)] # Test bad config_option value. with pytest.raises(DocoptcfgError): docoptcfg(DOCSTRING_FAM, argv, config_option='--config-file') # Test missing file. with pytest.raises(DocoptcfgFileError) as exc: docoptcfg(DOCSTRING_FAM, argv, config_option='-c') assert exc.value.message == 'Unable to read config file.' assert exc.value.FILE_PATH == str(config_file) assert 'No such file or directory' in exc.value.original_error # Test permission error. if os.name != 'nt': config_file.ensure().chmod(0o0244) with pytest.raises(DocoptcfgFileError) as exc: docoptcfg(DOCSTRING_FAM, argv, config_option='-c') assert exc.value.message == 'Unable to read config file.' assert exc.value.FILE_PATH == str(config_file) assert 'Permission denied' in exc.value.original_error # Test empty file. config_file.ensure().chmod(0o0644) with pytest.raises(DocoptcfgFileError) as exc: docoptcfg(DOCSTRING_FAM, argv, config_option='-c') assert exc.value.message == 'Section [FlashAirMusic] not in config file.' assert exc.value.FILE_PATH == str(config_file) assert exc.value.original_error is None # Test corrupt file. config_file.write('\x00\x00\x00\x00') with pytest.raises(DocoptcfgFileError) as exc: docoptcfg(DOCSTRING_FAM, argv, config_option='-c') assert exc.value.message == 'Unable to parse config file.' assert exc.value.FILE_PATH == str(config_file) assert 'File contains no section headers.' in exc.value.original_error # Test bad boolean. config_file.write('[FlashAirMusic]\nverbose = "test"') with pytest.raises(DocoptcfgFileError) as exc: docoptcfg(DOCSTRING_FAM, argv, config_option='-c') assert exc.value.message == 'Boolean option "verbose" invalid.' assert exc.value.FILE_PATH == str(config_file) assert 'Not a boolean' in exc.value.original_error