diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pyssg/arg_parser.py | 50 | ||||
-rw-r--r-- | src/pyssg/builder.py | 32 | ||||
-rw-r--r-- | src/pyssg/configuration.py | 151 | ||||
-rw-r--r-- | src/pyssg/page.py | 34 | ||||
-rw-r--r-- | src/pyssg/parser.py | 18 | ||||
-rw-r--r-- | src/pyssg/plt/default.ini | 22 | ||||
-rw-r--r-- | src/pyssg/plt/index.html | 6 | ||||
-rw-r--r-- | src/pyssg/plt/page.html | 4 | ||||
-rw-r--r-- | src/pyssg/plt/rss.xml | 18 | ||||
-rw-r--r-- | src/pyssg/plt/sitemap.xml | 2 | ||||
-rw-r--r-- | src/pyssg/plt/tag.html | 4 | ||||
-rw-r--r-- | src/pyssg/pyssg.py | 85 | ||||
-rw-r--r-- | src/pyssg/utils.py | 28 |
13 files changed, 204 insertions, 250 deletions
diff --git a/src/pyssg/arg_parser.py b/src/pyssg/arg_parser.py index 4ee7d57..90fb8c1 100644 --- a/src/pyssg/arg_parser.py +++ b/src/pyssg/arg_parser.py @@ -3,21 +3,40 @@ from argparse import ArgumentParser, Namespace def get_parsed_arguments() -> Namespace: parser = ArgumentParser(prog='pyssg', - description='''Static Site Generator that reads - Markdown files and creates HTML files.\nIf - [-c]onfig file is provided (or exists in default - location) all other options are ignored.\nFor - datetime formats see: + description='''Static Site Generator that parses + Markdown files into HTML files. For datetime + formats see: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes''') parser.add_argument('-v', '--version', action='store_true', help='''print program version''') parser.add_argument('-c', '--config', - default='$XDG_CONFIG_HOME/pyssg/pyssgrc', + # don't give a default here, as it would seem like + # --config was passed + # default='$XDG_CONFIG_HOME/pyssg/config.ini', type=str, - help='''config file (path) to read from; defaults to - 'pyssgrc' first, then - '$XDG_CONFIG_HOME/pyssg/pyssgrc' ''') + help='''config file (path) to read from; if not passed, + '$XDG_CONFIG_HOME/pyssg/config.ini' is used''') + parser.add_argument('--copy-default-config', + action='store_true', + help='''copies the default config to path specified in + --config flag''') + parser.add_argument('-i', '--init', + action='store_true', + help='''initializes the directory structures and copies + over default templates''') + parser.add_argument('-b', '--build', + action='store_true', + help='''generates all HTML files by parsing MD files + present in source directory and copies over manually + written HTML files''') + parser.add_argument('-f', '--force', + action='store_true', + help='''force building all pages and not only the + updated ones''') + # really not needed, too much bloat and case scenarios to check for, + # instead, just read from config file or default config file + """ parser.add_argument('-s', '--src', default='src', type=str, @@ -68,17 +87,6 @@ def get_parsed_arguments() -> Namespace: help='''date format used for the separator between page entries in a list; defaults to '%%B %%Y' ('March 2021', for example)''') - parser.add_argument('-i', '--init', - action='store_true', - help='''initializes the dir structure, templates, - as well as the 'src' and 'dst' directories''') - parser.add_argument('-b', '--build', - action='store_true', - help='''generates all html files and passes over - existing (handmade) ones''') - parser.add_argument('-f', '--force', - action='store_true', - help='''force building all pages and not only the - updated ones''') + """ return parser.parse_args() diff --git a/src/pyssg/builder.py b/src/pyssg/builder.py index 84494da..130062e 100644 --- a/src/pyssg/builder.py +++ b/src/pyssg/builder.py @@ -4,8 +4,8 @@ from copy import deepcopy from operator import itemgetter from jinja2 import Environment, Template from markdown import Markdown +from configparser import ConfigParser -from .configuration import Configuration from .database import Database from .parser import MDParser from .page import Page @@ -13,11 +13,11 @@ from .discovery import get_file_list, get_dir_structure class Builder: - def __init__(self, config: Configuration, + def __init__(self, config: ConfigParser, env: Environment, db: Database, md: Markdown): - self.config: Configuration = config + self.config: ConfigParser = config self.env: Environment = env self.db: Database = db self.md: Markdown = md @@ -33,15 +33,19 @@ class Builder: def build(self) -> None: - self.dirs = get_dir_structure(self.config.src, ['templates']) - self.md_files = get_file_list(self.config.src, ['.md'], ['templates']) - self.html_files = get_file_list(self.config.src, ['.html'], ['templates']) + self.dirs = get_dir_structure(self.config.get('path', 'src'), + ['templates']) + self.md_files = get_file_list(self.config.get('path', 'src'), + ['.md'], + ['templates']) + self.html_files = get_file_list(self.config.get('path', 'src'), + ['.html'], + ['templates']) self.__create_dir_structure() self.__copy_html_files() - parser: MDParser = MDParser(self.config.src, - self.md_files, + parser: MDParser = MDParser(self.md_files, self.config, self.db, self.md) @@ -69,7 +73,7 @@ class Builder: # for the dir structure, # doesn't matter if the dir already exists try: - os.makedirs(os.path.join(self.config.dst, d)) + os.makedirs(os.path.join(self.config.get('path', 'dst'), d)) except FileExistsError: pass @@ -79,18 +83,18 @@ class Builder: dst_file: str = None for f in self.html_files: - src_file = os.path.join(self.config.src, f) - dst_file = os.path.join(self.config.dst, f) + src_file = os.path.join(self.config.get('path', 'src'), f) + dst_file = os.path.join(self.config.get('path', 'dst'), f) # only copy files if they have been modified (or are new) - if self.db.update(src_file, remove=f'{self.config.src}/'): + if self.db.update(src_file, remove=f'{self.config.get("path", "src")}/'): shutil.copy2(src_file, dst_file) def __render_articles(self) -> None: article_vars: dict = deepcopy(self.common_vars) # check if only updated should be created - if self.config.force: + if self.config.getboolean('other', 'force'): for p in self.all_pages: article_vars['page'] = p self.__render_template("page.html", @@ -132,5 +136,5 @@ class Builder: template: Template = self.env.get_template(template_name) content: str = template.render(**template_vars) - with open(os.path.join(self.config.dst, file_name), 'w') as f: + with open(os.path.join(self.config.get('path', 'dst'), file_name), 'w') as f: f.write(content) diff --git a/src/pyssg/configuration.py b/src/pyssg/configuration.py index 5a09a7a..dd6bfaa 100644 --- a/src/pyssg/configuration.py +++ b/src/pyssg/configuration.py @@ -1,133 +1,42 @@ -from typing import Union +import sys from importlib.metadata import version +from importlib.resources import path as rpath from datetime import datetime, timezone +from configparser import ConfigParser -class Configuration: - def __init__(self, path: str): - self.path: str = path - # config file specific - self.src: str = None - self.dst: str = None - self.plt: str = None - self.url: str = None - self.static_url: str = None - self.default_image_url: str = None - self.title: str = None - self.dformat: str = None - self.l_dformat: str = None - self.lsep_dformat: str = None - self.force: bool = None +DEFAULT_CONFIG_PATH = '$XDG_CONFIG_HOME/pyssg/config.ini' +VERSION = version('pyssg') - # other - self.version: str = version('pyssg') - self.dformat_rss: str = '%a, %d %b %Y %H:%M:%S GMT' - self.dformat_sitemap: str = '%Y-%m-%d' - self.run_date_rss = datetime.now(tz=timezone.utc).strftime(self.dformat_rss) - self.run_date_sitemap = \ - datetime.now(tz=timezone.utc).strftime(self.dformat_sitemap) +def __check_well_formed_config(config: ConfigParser) -> None: + default_config: ConfigParser = ConfigParser() + with rpath('pyssg.plt', 'default.ini') as p: + default_config.read(p) - def read(self): - try: - lines: list[str] = None - with open(self.path, 'r') as f: - lines = f.readlines() + for section in default_config.sections(): + if not config.has_section(section): + print(f'config does not have section "{section}"') + sys.exit(1) + for option in default_config.options(section): + if not config.has_option(section, option): + print(f'config does not have option "{option}" in section "{section}"') + sys.exit(1) - opts: dict[str, Union[str, bool]] = dict() - for l in lines: - kv: list[str] = l.split('=', 1) - if len(kv) != 2: - raise Exception('wrong config syntax') - k: str = kv[0].strip().lower() - v_temp: str = kv[1].strip() - # check if value should be a boolean true - v: Union[str, bool] = v_temp\ - if v_temp.lower() not in ['true', '1', 'yes']\ - else True +def get_parsed_config(path: str) -> ConfigParser: + config: ConfigParser = ConfigParser() + config.read(path) - opts[k] = v + __check_well_formed_config(config) - try: - self.src = opts['src'] - except KeyError: pass + # set other required options + config.set('fmt', 'rss_date', '%%a, %%d %%b %%Y %%H:%%M:%%S GMT') + config.set('fmt', 'sitemap_date', '%%Y-%%m-%%d') + config.set('info', 'version', VERSION) + config.set('info', 'rss_run_date', datetime.now( + tz=timezone.utc).strftime(config.get('fmt', 'rss_date'))) + config.set('info', 'sitemap_run_date', datetime.now( + tz=timezone.utc).strftime(config.get('fmt', 'sitemap_date'))) - try: - self.dst = opts['dst'] - except KeyError: pass - - try: - self.plt = opts['plt'] - except KeyError: pass - - try: - self.url = opts['url'] - except KeyError: pass - - try: - self.static_url = opts['static_url'] - except KeyError: pass - - try: - self.default_image_url = opts['default_image_url'] - except KeyError: pass - - try: - self.title = opts['title'] - except KeyError: pass - - try: - self.dformat = opts['date_format'] - except KeyError: pass - - try: - self.l_dformat = opts['list_date_format'] - except KeyError: pass - - try: - self.lsep_dformat = opts['list_sep_date_format'] - except KeyError: pass - - try: - # if the parser above didn't read a boolean true, then take it - # as a false anyways - self.force = opts['force'] if opts['force'] is True else False - except KeyError: pass - - except OSError: pass - - - def fill_missing(self, opts: dict[str, Union[str, bool]]) -> None: - if self.src is None: - self.src = opts['src'] - - if self.dst is None: - self.dst = opts['dst'] - - if self.plt is None: - self.plt = opts['plt'] - - if self.url is None: - self.url = opts['url'] - - if self.static_url is None: - self.static_url = opts['static_url'] - - if self.default_image_url is None: - self.default_image_url = opts['default_image_url'] - - if self.title is None: - self.title = opts['title'] - - if self.dformat is None: - self.dformat = opts['date_format'] - - if self.l_dformat is None: - self.l_dformat = opts['list_date_format'] - - if self.lsep_dformat is None: - self.lsep_dformat = opts['list_sep_date_format'] - - if self.force is None: - self.force = opts['force'] + return config diff --git a/src/pyssg/page.py b/src/pyssg/page.py index 6b83d39..784749c 100644 --- a/src/pyssg/page.py +++ b/src/pyssg/page.py @@ -1,6 +1,6 @@ from datetime import datetime, timezone -from .configuration import Configuration +from configparser import ConfigParser class Page: @@ -10,14 +10,14 @@ class Page: mtime: float, html: str, meta: dict, - config: Configuration): + config: ConfigParser): # initial data self.name: str = name self.ctimestamp: float = ctime self.mtimestamp: float = mtime self.content: str = html self.meta: dict = meta - self.config: Configuration = config + self.config: ConfigParser = config # data from self.meta self.title: str = '' @@ -66,23 +66,23 @@ class Page: # dates self.cdatetime = datetime.fromtimestamp(self.ctimestamp, tz=timezone.utc) - self.cdate = self.cdatetime.strftime(self.config.dformat) - self.cdate_list = self.cdatetime.strftime(self.config.l_dformat) - self.cdate_list_sep = self.cdatetime.strftime(self.config.lsep_dformat) - self.cdate_rss = self.cdatetime.strftime(self.config.dformat_rss) + self.cdate = self.cdatetime.strftime(self.config.get('fmt', 'date')) + self.cdate_list = self.cdatetime.strftime(self.config.get('fmt', 'list_date')) + self.cdate_list_sep = self.cdatetime.strftime(self.config.get('fmt', 'list_sep_date')) + self.cdate_rss = self.cdatetime.strftime(self.config.get('fmt', 'rss_date')) self.cdate_sitemap = \ - self.cdatetime.strftime(self.config.dformat_sitemap) + self.cdatetime.strftime(self.config.get('fmt', 'sitemap_date')) # only if file/page has been modified if self.mtimestamp != 0.0: self.mdatetime = datetime.fromtimestamp(self.mtimestamp, tz=timezone.utc) - self.mdate = self.mdatetime.strftime(self.config.dformat) - self.mdate_list = self.mdatetime.strftime(self.config.l_dformat) - self.mdate_list_sep = self.mdatetime.strftime(self.config.lsep_dformat) - self.mdate_rss = self.mdatetime.strftime(self.config.dformat_rss) + self.mdate = self.mdatetime.strftime(self.config.get('fmt', 'date')) + self.mdate_list = self.mdatetime.strftime(self.config.get('fmt', 'list_date')) + self.mdate_list_sep = self.mdatetime.strftime(self.config.get('fmt', 'list_sep_date')) + self.mdate_rss = self.mdatetime.strftime(self.config.get('fmt', 'rss_date')) self.mdate_sitemap = \ - self.mdatetime.strftime(self.config.dformat_sitemap) + self.mdatetime.strftime(self.config.get('fmt', 'sitemap_date')) # not always contains tags try: @@ -91,17 +91,17 @@ class Page: for t in tags_only: self.tags.append((t, - f'{self.config.url}/tag/@{t}.html')) + f'{self.config.get("url", "main")}/tag/@{t}.html')) except KeyError: pass - self.url = f'{self.config.url}/{self.name.replace(".md", ".html")}' + self.url = f'{self.config.get("url", "main")}/{self.name.replace(".md", ".html")}' try: self.image_url = \ - f'{self.config.static_url}/{self.meta["image_url"][0]}' + f'{self.config.get("url", "static")}/{self.meta["image_url"][0]}' except KeyError: self.image_url = \ - f'{self.config.static_url}/{self.config.default_image_url}' + f'{self.config.get("url", "static")}/{self.config.get("url", "default_image")}' # if contains open graph elements try: diff --git a/src/pyssg/parser.py b/src/pyssg/parser.py index f2d23eb..2888fcb 100644 --- a/src/pyssg/parser.py +++ b/src/pyssg/parser.py @@ -1,24 +1,21 @@ import os from operator import itemgetter -from datetime import datetime from markdown import Markdown +from configparser import ConfigParser from .database import Database -from .configuration import Configuration from .page import Page # parser of md files, stores list of pages and tags class MDParser: - def __init__(self, src: str, - files: list[str], - config: Configuration, + def __init__(self, files: list[str], + config: ConfigParser, db: Database, md: Markdown): - self.src: str = src self.files: list[str] = files - self.config: Configuration = config + self.config: ConfigParser = config self.db: Database = db self.md: Markdown = md @@ -32,12 +29,13 @@ class MDParser: self.all_pages = [] self.updated_pages = [] self.all_tags = [] - all_tag_names: list[str] = [] + # not used, not sure why i had this + # all_tag_names: list[str] = [] for f in self.files: - src_file: str = os.path.join(self.src, f) + src_file: str = os.path.join(self.config.get('path', 'src'), f) # get flag if update is successful - updated: bool = self.db.update(src_file, remove=f'{self.src}/') + updated: bool = self.db.update(src_file, remove=f'{self.config.get("path", "src")}/') content: str = self.md.reset().convert(open(src_file).read()) page: Page = Page(f, diff --git a/src/pyssg/plt/default.ini b/src/pyssg/plt/default.ini index 2700d28..ab4eac1 100644 --- a/src/pyssg/plt/default.ini +++ b/src/pyssg/plt/default.ini @@ -1,14 +1,16 @@ -[dir_paths] +[path] src=src dst=dst plt=plt -[urls] -url=https://example.com -static_url=https://static.example.com -default_image_url=/images/default.png -[formats] -date_format=%%a, %%b %%d, %%Y @ %%H:%%M %%Z -list_date_format=%%b %%d -list_sep_date_format=%%B %%Y +[url] +main=https://example.com +static=https://static.example.com +default_image=/images/default.png +[fmt] +date=%%a, %%b %%d, %%Y @ %%H:%%M %%Z +list_date=%%b %%d +list_sep_date=%%B %%Y [info] -title=Example site
\ No newline at end of file +title=Example site +[other] +force=False
\ No newline at end of file diff --git a/src/pyssg/plt/index.html b/src/pyssg/plt/index.html index e06efdb..09ca786 100644 --- a/src/pyssg/plt/index.html +++ b/src/pyssg/plt/index.html @@ -2,11 +2,11 @@ <html lang="en"> <head> <meta charset="utf-8"> - <base href="{{config.static_url}}"> - <title>Index -- {{config.title}}</title> + <base href="{{config.get('url', 'static')}}"> + <title>Index -- {{config.get('info', 'title')}}</title> </head> <body> - <h1>Index -- {{config.title}}</h1> + <h1>Index -- {{config.get('info', 'title')}}</h1> <p>Some text here.</p> <p>Tags: diff --git a/src/pyssg/plt/page.html b/src/pyssg/plt/page.html index 2fc3943..15663fa 100644 --- a/src/pyssg/plt/page.html +++ b/src/pyssg/plt/page.html @@ -2,8 +2,8 @@ <html lang="{{page.lang}}"> <head> <meta charset="utf-8"> - <base href="{{config.static_url}}"> - <title>{{page.title}} -- {{config.title}}</title> + <base href="{{config.get('url', 'static')}}"> + <title>{{page.title}} -- {{config.get('info', 'title')}}</title> </head> <body> <h1>{{page.title}}</h1> diff --git a/src/pyssg/plt/rss.xml b/src/pyssg/plt/rss.xml index 42020d7..be6ddf0 100644 --- a/src/pyssg/plt/rss.xml +++ b/src/pyssg/plt/rss.xml @@ -3,24 +3,24 @@ xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"> <channel> - <title>{{config.title}}</title> - <link>{{config.url}}</link> - <atom:link href="{{config.url}}/rss.xml" rel="self" type="application/rss+xml"/> + <title>{{config.get('info', 'title')}}</title> + <link>{{config.get('url', 'main')}}</link> + <atom:link href="{{config.get('url', 'main')}}/rss.xml" rel="self" type="application/rss+xml"/> <description>Short site description.</description> <language>en-us</language> <category>Blog</category> <copyright>Copyright 2021 Somebody</copyright> <managingEditor>some@one.com (Sombody)</managingEditor> <webMaster>some@one.com (Sombody)</webMaster> - <pubDate>{{config.run_date_rss}}</pubDate> - <lastBuildDate>{{run_date_rss}}</lastBuildDate> - <generator>pyssg v{{config.version}}</generator> + <pubDate>{{config.get('info', 'rss_run_date')}}</pubDate> + <lastBuildDate>{{config.get('info', 'rss_run_date')}}</lastBuildDate> + <generator>pyssg v{{config.get('info', 'version')}}</generator> <docs>https://validator.w3.org/feed/docs/rss2.html</docs> <ttl>30</ttl> <image> - <url>{{config.static_url}}/images/blog.png</url> - <title>{{config.title}}</title> - <link>{{config.url}}</link> + <url>{{config.get('url', 'static')}}/images/blog.png</url> + <title>{{config.get('info', 'title')}}</title> + <link>{{config.get('url', 'main')}}</link> </image> {%for p in all_pages%} <item> diff --git a/src/pyssg/plt/sitemap.xml b/src/pyssg/plt/sitemap.xml index 26ee5c1..af1212a 100644 --- a/src/pyssg/plt/sitemap.xml +++ b/src/pyssg/plt/sitemap.xml @@ -14,7 +14,7 @@ {%for t in all_tags%} <url> <loc>{{t[1]}}</loc> - <lastmod>{{config.run_date_sitemap}}</lastmod> + <lastmod>{{config.get('info', 'sitemap_run_date')}}</lastmod> <changefreq>daily</changefreq> <priority>0.5</priority> </url> diff --git a/src/pyssg/plt/tag.html b/src/pyssg/plt/tag.html index d856ce4..ffd1956 100644 --- a/src/pyssg/plt/tag.html +++ b/src/pyssg/plt/tag.html @@ -2,8 +2,8 @@ <html lang="en"> <head> <meta charset="utf-8"> - <base href="{{config.static_url}}"> - <title>Posts filtered by {{tag[0]}} -- {{config.title}}</title> + <base href="{{config.get('url', 'static')}}"> + <title>Posts filtered by {{tag[0]}} -- {{config.get('info', 'title')}}</title> </head> <body> <h1>Posts filtered by {{tag[0]}}</h1> diff --git a/src/pyssg/pyssg.py b/src/pyssg/pyssg.py index e694565..9b82231 100644 --- a/src/pyssg/pyssg.py +++ b/src/pyssg/pyssg.py @@ -1,7 +1,8 @@ import os -import shutil -from importlib.resources import path +import sys +from importlib.resources import path as rpath from typing import Union +from configparser import ConfigParser from jinja2 import Environment, FileSystemLoader from markdown import Markdown @@ -9,61 +10,65 @@ from yafg import YafgExtension from MarkdownHighlight.highlight import HighlightExtension from markdown_checklist.extension import ChecklistExtension +from .utils import create_dir, copy_file, sanity_check_path from .arg_parser import get_parsed_arguments -from .configuration import Configuration +from .configuration import get_parsed_config, DEFAULT_CONFIG_PATH, VERSION from .database import Database from .builder import Builder def main() -> None: - opts: dict[str, Union[str, bool]] = vars(get_parsed_arguments()) - conf_path: str = opts['config'] - conf_path = os.path.expandvars(conf_path) - - - config: Configuration = None - if os.path.exists('pyssgrc'): - config = Configuration('pyssgrc') - else: - config = Configuration(conf_path) - - config.read() - config.fill_missing(opts) - - if opts['version']: - print(f'pyssg v{config.version}') - return - - if opts['init']: - try: - os.mkdir(config.src) - os.makedirs(os.path.join(config.dst, 'tag')) - os.mkdir(config.plt) - except FileExistsError: - pass - - # copy basic template files + args: dict[str, Union[str, bool]] = vars(get_parsed_arguments()) + if not len(sys.argv) > 1: + print(f'pyssg v{VERSION} - no arguments passed, --help for more') + sys.exit(0) + + if args['version']: + print(f'pyssg v{VERSION}') + sys.exit(0) + + config_path: str = args['config'] if args['config'] else DEFAULT_CONFIG_PATH + config_path = os.path.normpath(os.path.expandvars(config_path)) + sanity_check_path(config_path) + config_dir, _ = os.path.split(config_path) + + if args['copy_default_config']: + create_dir(config_dir) + with rpath('pyssg.plt', 'default.ini') as p: + copy_file(p, config_path) + sys.exit(0) + + if not os.path.exists(config_path): + print(f'''config file does't exist in path "{config_path}"; make sure + the path is correct; use --copy-default-config to if you + haven't already''') + sys.exit(1) + + config: ConfigParser = get_parsed_config(config_path) + + if args['init']: + create_dir(config.get('path', 'src')) + create_dir(os.path.join(config.get('path', 'dst'), 'tag'), True) + create_dir(config.get('path', 'plt')) files: list[str] = ('index.html', 'page.html', 'tag.html', 'rss.xml', 'sitemap.xml') for f in files: - plt_file: str = os.path.join(config.plt, f) - with path('pyssg.plt', f) as p: - if not os.path.exists(plt_file): - shutil.copy(p, plt_file) - - return + plt_file: str = os.path.join(config.get('path', 'plt'), f) + with rpath('pyssg.plt', f) as p: + copy_file(p, plt_file) + sys.exit(0) - if opts['build']: + if args['build']: # start the db - db: Database = Database(os.path.join(config.src, '.files')) + db: Database = Database(os.path.join(config.get('path', 'src'), '.files')) db.read() # the autoescape option could be a security risk if used in a dynamic # website, as far as i can tell - env: Environment = Environment(loader=FileSystemLoader(config.plt), + env: Environment = Environment(loader=FileSystemLoader(config.get('path', 'plt')), autoescape=False, trim_blocks=True, lstrip_blocks=True) @@ -92,4 +97,4 @@ def main() -> None: builder.build() db.write() - return + sys.exit(0) diff --git a/src/pyssg/utils.py b/src/pyssg/utils.py new file mode 100644 index 0000000..8e5d90e --- /dev/null +++ b/src/pyssg/utils.py @@ -0,0 +1,28 @@ +import os +import sys +import shutil + + +def create_dir(path: str, p: bool=False) -> None: + try: + if p: + os.makedirs(path) + else: + os.mkdir(path) + print(f'created directory "{path}"') + except FileExistsError: + print(f'directory "{path}" already exists') + + +def copy_file(src: str, dst: str) -> None: + if not os.path.exists(dst): + shutil.copy(src, dst) + print(f'copied file "{src}" to "{dst}"') + else: + print(f'"{dst}" already exists') + + +def sanity_check_path(path: str) -> None: + if '$' in path: + print(f'"$" character found in path: "{path}"; could be due to non-existant env var.') + sys.exit(1) |