GitBucket
4.21.2
Toggle navigation
Snippets
Sign in
Files
Branches
1
Releases
Issues
1
Pull requests
Labels
Priorities
Milestones
Wiki
Forks
nigel.stanger
/
Handbook
Browse code
Moved load_config() into config.py
master
1 parent
1e0e841
commit
8017dba37330925c4f3cf90d4d2b2c4efce5d9b3
Nigel Stanger
authored
on 26 Nov 2019
Patch
Showing
3 changed files
calendar/teachingdates/config/__init__.py
calendar/teachingdates/config/cli.py
calendar/teachingdates/config/config.py
Ignore Space
Show notes
View
calendar/teachingdates/config/__init__.py
from .cli import parse_command_line, PROG from .config import load_config, parse_config from .errors import LectureStyleError, PaperError, PeriodError
from .cli import parse_command_line, PROG from .config import parse_config from .errors import LectureStyleError, PaperError, PeriodError
Ignore Space
Show notes
View
calendar/teachingdates/config/cli.py
import argparse import datetime from teachingdates import PROG from .config import load_config def parse_command_line(): """Parse command-line arguments. Example command lines: generate_dates --style calendar --format latex --year 2020 --period S1 --paper INFO201 generate_dates --style lecture --format xml --period S2 --paper INFO202 """ format_map = { "t": "text", "text": "text", "l": "latex", "latex": "latex", "x": "xml", "xml": "xml", } style_map = { "c": "calendar", "calendar": "calendar", "l": "lecture", "lecture": "lecture", "i": "iso", "iso": "iso", } parser = argparse.ArgumentParser(prog=PROG, description="") parser.add_argument( "--config", "-c", default=None, dest="config_file", help="file name of the configuration file " "[default '~/.config/{prog}/config.yml']".format(prog=PROG)) parser.add_argument( "--debug", "-d", action='store_true', help="enable debugging output") parser.add_argument( "--format", "-f", default="latex", choices=["text", "t", "latex", "l", "xml", "x"], help="output format [default 'latex']") parser.add_argument( "--output", "-o", type=argparse.FileType("w", encoding="UTF-8"), help="file name to write the output to; existing " "files of the same name will be overwritten!") parser.add_argument( "--paper", "-p", default=None, help="paper code (e.g., INFO201) [required for 'lecture' style, " "ignored otherwise]") parser.add_argument( "--style", "-s", default="calendar", choices=["calendar", "c", "lecture", "l", "iso", "i"], help="output style: 'calendar' for teaching calendars in course " "outlines, 'lecture' for individual lecture dates, or 'iso'" "for dates across the entire ISO-8601 year [default 'calendar']") parser.add_argument( "--teaching-period", "-t", default=None, choices=["SS", "S1", "S2", "FY"], dest="period", help="teaching period [required]") parser.add_argument( "--year", "-y", type=int, default=datetime.date.today().year, help=("the year to generate dates for [default {y}]".format( y=datetime.date.today().year))) args = parser.parse_args() # normalise format and style args.format = format_map[args.format] args.style = style_map[args.style] # Load the default config if none is explicitly specified. args.config_file, args.config = load_config(file=args.config_file) if not args.config: parser.exit(2, "{prog}: error: failed to load configuration " "from '{f}'\n".format(prog=PROG, f=args.config_file)) if args.style == "calendar": # --paper is irrelevant if args.paper: print("{prog}: warning: --paper/-p is ignored for " "'calendar' style".format(prog=PROG)) # --teaching-period is required if not args.period: parser.exit(2, "{prog}: error: --teaching-period/-t " "is required for 'calendar' style\n".format(prog=PROG)) elif args.style == "iso": # both --paper and --teaching-period are irrelevant if args.paper or args.period: print("{prog}: warning: --paper/-p and " "--teaching-period/-t are ignored for 'iso' " "style".format(prog=PROG)) elif args.style == "lecture": # both --paper and --teaching-period are required if not args.paper: parser.exit(2, message="{prog}: error: -paper/-p and " "--teaching-period/-t are required for 'lecture' " "style\n".format(prog=PROG)) # --teaching-period must be specified if --style is "calendar" or "lecture" else: pass return args
import argparse import datetime import importlib.resources as pkg_resources from os import mkdir from pathlib import Path from shutil import copyfile import yaml from teachingdates import PROG CONFIG_FILENAME = "config.yml" CONFIG_DIR = Path.home().joinpath(".config", PROG) CONFIG_FILE = CONFIG_DIR.joinpath(CONFIG_FILENAME) def load_config(file=None): """Load the configuration file. If no file is specified, try the default configuration in ~/.config. If that doesn't exist, copy the default configuration from teachingdates.config. """ cfg = None if not file: file = CONFIG_FILE if not CONFIG_FILE.exists(): CONFIG_DIR.mkdir(exist_ok=True) configmgr = pkg_resources.path( "teachingdates.config", CONFIG_FILENAME) with configmgr as f: copyfile(f, CONFIG_FILE) print("{prog}: created new configuration file at " "'{f}'".format(prog=PROG, f=str(CONFIG_FILE))) try: with open(file) as f: cfg = yaml.safe_load(f.read()) except FileNotFoundError as e: print("{prog}: error: no such file '{f}'".format(prog=PROG, f=file)) return file, cfg def parse_command_line(): """Parse command-line arguments. Example command lines: generate_dates --style calendar --format latex --year 2020 --period S1 --paper INFO201 generate_dates --style lecture --format xml --period S2 --paper INFO202 """ format_map = { "t": "text", "text": "text", "l": "latex", "latex": "latex", "x": "xml", "xml": "xml", } style_map = { "c": "calendar", "calendar": "calendar", "l": "lecture", "lecture": "lecture", "i": "iso", "iso": "iso", } parser = argparse.ArgumentParser(prog=PROG, description="") parser.add_argument( "--config", "-c", default=None, dest="config_file", help="file name of the configuration file " "[default '~/.config/{prog}/config.yml']".format(prog=PROG)) parser.add_argument( "--debug", "-d", action='store_true', help="enable debugging output") parser.add_argument( "--format", "-f", default="latex", choices=["text", "t", "latex", "l", "xml", "x"], help="output format [default 'latex']") parser.add_argument( "--output", "-o", type=argparse.FileType("w", encoding="UTF-8"), help="file name to write the output to; existing " "files of the same name will be overwritten!") parser.add_argument( "--paper", "-p", default=None, help="paper code (e.g., INFO201) [required for 'lecture' style, " "ignored otherwise]") parser.add_argument( "--style", "-s", default="calendar", choices=["calendar", "c", "lecture", "l", "iso", "i"], help="output style: 'calendar' for teaching calendars in course " "outlines, 'lecture' for individual lecture dates, or 'iso'" "for dates across the entire ISO-8601 year [default 'calendar']") parser.add_argument( "--teaching-period", "-t", default=None, choices=["SS", "S1", "S2", "FY"], dest="period", help="teaching period [required]") parser.add_argument( "--year", "-y", type=int, default=datetime.date.today().year, help=("the year to generate dates for [default {y}]".format( y=datetime.date.today().year))) args = parser.parse_args() # normalise format and style args.format = format_map[args.format] args.style = style_map[args.style] # Load the default config if none is explicitly specified. args.config_file, args.config = load_config(file=args.config_file) if not args.config: parser.exit(2, "{prog}: error: failed to load configuration " "from '{f}'\n".format(prog=PROG, f=args.config_file)) if args.style == "calendar": # --paper is irrelevant if args.paper: print("{prog}: warning: --paper/-p is ignored for " "'calendar' style".format(prog=PROG)) # --teaching-period is required if not args.period: parser.exit(2, "{prog}: error: --teaching-period/-t " "is required for 'calendar' style\n".format(prog=PROG)) elif args.style == "iso": # both --paper and --teaching-period are irrelevant if args.paper or args.period: print("{prog}: warning: --paper/-p and " "--teaching-period/-t are ignored for 'iso' " "style".format(prog=PROG)) elif args.style == "lecture": # both --paper and --teaching-period are required if not args.paper: parser.exit(2, message="{prog}: error: -paper/-p and " "--teaching-period/-t are required for 'lecture' " "style\n".format(prog=PROG)) # --teaching-period must be specified if --style is "calendar" or "lecture" else: pass return args
Ignore Space
Show notes
View
calendar/teachingdates/config/config.py
import importlib.resources as pkg_resources from pathlib import Path from shutil import copyfile import yaml from teachingdates import PROG from .errors import LectureStyleError, PaperError, PeriodError CONFIG_FILENAME = "config.yml" CONFIG_DIR = Path.home().joinpath(".config", PROG) CONFIG_FILE = CONFIG_DIR.joinpath(CONFIG_FILENAME) def load_config(file=None): """Load a configuration file. If no file is specified, try the default configuration in ~/.config. If that doesn't exist, copy the default configuration from teachingdates.config. """ cfg = None if not file: file = CONFIG_FILE if not CONFIG_FILE.exists(): CONFIG_DIR.mkdir(exist_ok=True) configmgr = pkg_resources.path( "teachingdates.config", CONFIG_FILENAME) with configmgr as f: copyfile(f, CONFIG_FILE) print("{prog}: created new configuration file at " "'{f}'".format(prog=PROG, f=str(CONFIG_FILE))) try: with open(file) as f: cfg = yaml.safe_load(f.read()) except FileNotFoundError as e: print("{prog}: error: no such file '{f}'".format(prog=PROG, f=file)) return file, cfg def parse_config(config, args): """Validate and filter the top-level configuration. Returns separate references to the period configuration and the paper configuration, as applicable. (Yes, the period configuration includes the paper configuration, but it may also include other papers, so it's more convenient to return a separate reference for the specified paper.) The configuration file will normally contain specifications for several teaching periods and papers. We don't need all of this: usually we're only interested in one teaching period and one paper (if relevant). """ period_config = paper_config = None # this is all irrelevant if we're going ISO style if args.style != "iso": if args.period not in config.keys(): raise PeriodError() period_config = config[args.period] # raises KeyError if source key is missing period_config["name"] and period_config["weeks"] # papers are irrelevant in "calendar" style if args.style == "lecture": if "papers" in period_config.keys(): if args.paper in period_config["papers"].keys(): paper_config = period_config["papers"][args.paper] # we expect at least a "lectures" entry paper_config["lectures"] else: raise PaperError() else: raise LectureStyleError() return period_config, paper_config
from .errors import LectureStyleError, PaperError, PeriodError def parse_config(config, args): """Validate and filter the top-level configuration. Returns separate references to the period configuration and the paper configuration, as applicable. (Yes, the period configuration includes the paper configuration, but it may also include other papers, so it's more convenient to return a separate reference for the specified paper.) The configuration file will normally contain specifications for several teaching periods and papers. We don't need all of this: usually we're only interested in one teaching period and one paper (if relevant). """ period_config = paper_config = None # this is all irrelevant if we're going ISO style if args.style != "iso": if args.period not in config.keys(): raise PeriodError() period_config = config[args.period] # raises KeyError if source key is missing period_config["name"] and period_config["weeks"] # papers are irrelevant in "calendar" style if args.style == "lecture": if "papers" in period_config.keys(): if args.paper in period_config["papers"].keys(): paper_config = period_config["papers"][args.paper] # we expect at least a "lectures" entry paper_config["lectures"] else: raise PaperError() else: raise LectureStyleError() return period_config, paper_config
Show line notes below