Coverage for magnetismi/cli.py: 0.00%

59 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-04 20:21:25 +00:00

1"""Command line interface for splice (Finnish liitos) contributions.""" 

2 

3import argparse 

4import datetime as dti 

5import sys 

6from typing import List, Union 

7 

8import magnetismi.magnetismi as api 

9from magnetismi import APP_ALIAS, APP_NAME, date_from_fractional_year 

10from magnetismi.model.cof import YEARS_COVERED 

11 

12DATE_FORMAT = '%Y-%m-%d' 

13 

14 

15def parse_request(argv: List[str]) -> Union[int, argparse.Namespace]: 

16 """DRY.""" 

17 parser = argparse.ArgumentParser( 

18 prog=APP_ALIAS, description=APP_NAME, formatter_class=argparse.RawTextHelpFormatter 

19 ) 

20 parser.add_argument( 

21 '--latitude', 

22 dest='lat_dd', 

23 type=float, 

24 required=True, 

25 help='geodetic latitude in decimal degrees inside [-180, +180]', 

26 ) 

27 parser.add_argument( 

28 '--longitude', 

29 dest='lon_dd', 

30 type=float, 

31 required=True, 

32 help='geodetic longitude in decimal degrees inside [-90, +90]', 

33 ) 

34 parser.add_argument( 

35 '--altitude', 

36 dest='alt_ft', 

37 type=float, 

38 default=0, 

39 help='altitude in feet inside [-3280.84, +2788714]. Optional (default: 0)', 

40 ) 

41 parser.add_argument( 

42 '--date', 

43 dest='date', 

44 default='', 

45 help=( 

46 'date for magentic calculation in YYYY-mm-dd or fractional year decimal format.' 

47 ' Optional\n(default: positional date value)' 

48 ), 

49 required=False, 

50 ) 

51 parser.add_argument( 

52 'date_pos', 

53 nargs='?', 

54 default='', 

55 help=( 

56 'date for magentic calculation in YYYY-mm-dd or fractional year decimal format.' 

57 ' Optional\n(default: empty for current date)' 

58 ), 

59 ) 

60 parser.add_argument( 

61 '--quiet', 

62 '-q', 

63 dest='quiet', 

64 default=False, 

65 action='store_true', 

66 help='work as quiet as possible - progress bar only if all well (default: False)', 

67 ) 

68 parser.add_argument( 

69 '--verbose', 

70 '-v', 

71 dest='verbose', 

72 default=False, 

73 action='store_true', 

74 help='work logging more information along the way (default: False)', 

75 ) 

76 if not argv: 

77 parser.print_help() 

78 return 0 

79 

80 options = parser.parse_args(argv) 

81 

82 if options.verbose and options.quiet: 

83 parser.error('you cannot be quiet and verbose at the same time') 

84 

85 if options.date: 

86 if '-' in options.date: 

87 try: 

88 options.date_in = dti.datetime.strptime(options.date, DATE_FORMAT).date() 

89 except ValueError as err: 

90 parser.error(f'requested date ({options.date}) does not parse as YYYY-mm-dd; error: {err}') 

91 else: 

92 try: 

93 options.date_in = date_from_fractional_year(float(options.date)) 

94 except ValueError as err: 

95 parser.error(f'requested date ({options.date}) does not parse as decimal fractional year; error: {err}') 

96 else: 

97 if options.date_pos: 

98 if '-' in options.date_pos: 

99 try: 

100 options.date_in = dti.datetime.strptime(options.date_pos, DATE_FORMAT).date() 

101 except ValueError as err: 

102 parser.error( 

103 f'requested (positional) date ({options.date_pos}) does not parse as YYYY-mm-dd; error: {err}' 

104 ) 

105 else: 

106 try: 

107 options.date_in = date_from_fractional_year(float(options.date_pos)) 

108 except ValueError as err: 

109 parser.error( 

110 f'requested (positional) date ({options.date_pos})' 

111 f' does not parse as decimal fractional year; error: {err}' 

112 ) 

113 else: 

114 options.date_in = dti.date.today() 

115 

116 if options.date_in.year not in YEARS_COVERED: 

117 parser.error(f'requested year ({options.date_in.year}) is outside of {YEARS_COVERED}') 

118 

119 if not -3280.84 <= options.alt_ft <= 2788714.0: 

120 parser.error( 

121 f'requested altitude ({options.alt_ft}) is outside of [-3280.84, +2788714] feet' 

122 ' and the model is only valid between the corresponding [-1, +850] km' 

123 ) 

124 

125 if not -90 <= options.lat_dd <= 90: 

126 parser.error(f'requested latitude ({options.lat_dd}) is outside of [-90, +90] degrees') 

127 

128 if not -180 <= options.lon_dd <= 180: 

129 parser.error(f'requested longitude ({options.lon_dd}) is outside of [-180, +180] degrees') 

130 

131 return options 

132 

133 

134def main(argv: Union[List[str], None] = None) -> int: 

135 """Delegate processing to functional module.""" 

136 argv = sys.argv[1:] if argv is None else argv 

137 options = parse_request(argv) 

138 if isinstance(options, int): 

139 return 0 

140 return api.calc(options)