Coverage for arbejdstimer/cli.py: 100.00%

37 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-23 14:26 +0200

1"""Commandline API gateway for arbejdstimer.""" 

2import pathlib 

3import sys 

4 

5import typer 

6 

7import arbejdstimer 

8import arbejdstimer.arbejdstimer as at 

9 

10APP_NAME = 'Working hours (Danish arbejdstimer) or not?' 

11APP_ALIAS = 'arbejdstimer' 

12app = typer.Typer( 

13 add_completion=False, 

14 context_settings={'help_option_names': ['-h', '--help']}, 

15 no_args_is_help=True, 

16) 

17 

18TEMPLATE_EXAMPLE = """\ 

19{ 

20 "api": 1, 

21 "application": "arbejdstimer", 

22 "operator": "or", 

23 "holidays": [ 

24 { 

25 "label": "public holiday", 

26 "at": [ 

27 "2022-12-08" 

28 ] 

29 }, 

30 { 

31 "label": "some holidays 2022/2023", 

32 "at": [ 

33 "2022-12-23", 

34 "2023-01-02" 

35 ] 

36 } 

37 ], 

38 "working_hours": [8, 17] 

39} 

40""" 

41 

42 

43@app.callback(invoke_without_command=True) 

44def callback( 

45 version: bool = typer.Option( 

46 False, 

47 '-V', 

48 '--version', 

49 help='Display the arbejdstimer version and exit', 

50 is_eager=True, 

51 ) 

52) -> None: 

53 """ 

54 Working hours (Danish arbejdstimer) or not? 

55 

56 Given a configuration file detect if today is a work day and 

57 if at the time of request is a working hour. 

58 

59 Return code of 0 indicates work time, 1 no work time, and 2 usage error. 

60 

61 Additional help available per command adding the -h/--help option 

62 """ 

63 if version: 

64 typer.echo(f'{APP_NAME} version {arbejdstimer.__version__}') 

65 raise typer.Exit() 

66 

67 

68@app.command('template') 

69def app_template() -> int: 

70 """ 

71 Write a template of a JSON configuration to standard out and exit 

72 """ 

73 sys.stdout.write(TEMPLATE_EXAMPLE) 

74 return sys.exit(0) 

75 

76 

77@app.command('now') 

78def now( 

79 conf: str = typer.Option( 

80 '', 

81 '-c', 

82 '--config', 

83 help='Path to config file (default is $HOME/.arbejdstimer.json)', 

84 metavar='<configpath>', 

85 ), 

86 strict: bool = typer.Option( 

87 False, 

88 '-s', 

89 '--strict', 

90 help='Enforce presence of farming dates in configuration (default is false if not provided)', 

91 metavar='<bool>', 

92 ), 

93) -> int: 

94 """ 

95 Silently answer the question if now is a working hour (per return code 0 for yes, and 1 for no). 

96 """ 

97 command = 'now' 

98 config = conf if conf else pathlib.Path.home() / at.DEFAULT_CONFIG_NAME 

99 action = (command, '', str(config), bool(strict)) 

100 return sys.exit(at.main(action)) 

101 

102 

103def explain_enforce_defaults(conf: str = '', day: str = '', verbose: bool = False, strict: bool = False) -> int: 

104 """Until the root cause of https://github.com/tiangolo/typer/issues/106 remains unfixed.""" 

105 command = 'explain' 

106 if verbose: 

107 command += '_verbatim' 

108 config = conf if conf else pathlib.Path.home() / at.DEFAULT_CONFIG_NAME 

109 action = (command, day, str(config), strict) 

110 return sys.exit(at.main(action)) 

111 

112 

113@app.command('explain') 

114def explain( 

115 conf: str = typer.Option( 

116 '', 

117 '-c', 

118 '--config', 

119 help='Path to config file (default is $HOME/.arbejdstimer.json)', 

120 metavar='<configpath>', 

121 ), 

122 day: str = typer.Option( 

123 '', 

124 '-d', 

125 '--day', 

126 help='Day sought (default is today)', 

127 metavar='<date>', 

128 ), 

129 strict: bool = typer.Option( 

130 False, 

131 '-s', 

132 '--strict', 

133 help='Enforce presence of farming dates in configuration (default is false if not provided)', 

134 metavar='<bool>', 

135 ), 

136 verbose: bool = typer.Option( 

137 False, 

138 '-v', 

139 '--verbose', 

140 help='Be more verbatim providing the effective config values (default is false if not provided)', 

141 metavar='<bool>', 

142 ), 

143) -> int: 

144 """ 

145 Explain the answer to the question if now is a working hour 

146 (in addition to the return code 0 for yes, and 1 for no). 

147 """ 

148 return explain_enforce_defaults(conf, day, verbose, strict) 

149 

150 

151@app.command('version') 

152def app_version() -> None: 

153 """ 

154 Display the arbejdstimer version and exit 

155 """ 

156 callback(True)