Rework a bunch of scripts into a single website script
This commit is contained in:
		
							parent
							
								
									f83c6ebbe5
								
							
						
					
					
						commit
						a9f52aad98
					
				
					 12 changed files with 275 additions and 92 deletions
				
			
		
							
								
								
									
										86
									
								
								scripts/convert_page.py
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										86
									
								
								scripts/convert_page.py
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
Convert a Hugo content page from a single page to a bundle and vice versa.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import os.path
 | 
			
		||||
 | 
			
		||||
def parse_args(argv, *a, **kw):
 | 
			
		||||
    parser = argparse.ArgumentParser(*a, **kw)
 | 
			
		||||
    parser.add_argument('page_path', metavar='PATH', help='Path to page or bundle to convert')
 | 
			
		||||
    args = parser.parse_args(argv)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
def path_is_page(path):
 | 
			
		||||
    if not os.path.isfile(path):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    _, extension = os.path.splitext(path)
 | 
			
		||||
    if extension not in ['.md']:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def path_is_page_bundle(path):
 | 
			
		||||
    if not os.path.isdir(path):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    contents = os.listdir(path)
 | 
			
		||||
    if 'index.md' not in contents:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def can_convert_page_bundle_to_page(path):
 | 
			
		||||
    contents = os.listdir(path)
 | 
			
		||||
    if len(contents) != 1:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    if 'index.md' not in contents:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def convert_page_to_bundle(path) -> bool:
 | 
			
		||||
    dirname = os.path.dirname(path)
 | 
			
		||||
    name, extension = os.path.splitext(path)
 | 
			
		||||
 | 
			
		||||
    bundle_path = os.path.join(dirname, name)
 | 
			
		||||
    index_path = os.path.join(dirname, 'index' + extension)
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        print(f'Creating {bundle_path} ... ', end='')
 | 
			
		||||
        os.mkdir(bundle_path)
 | 
			
		||||
        print('OK')
 | 
			
		||||
    except FileExistsError as e:
 | 
			
		||||
        print(f'\nCannot create {bundle_path}: directory already exists')
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        print(f'Moving {path} -> {index_path} ... ', end='')
 | 
			
		||||
        os.rename(path, index_path)
 | 
			
		||||
        print('OK')
 | 
			
		||||
    except:
 | 
			
		||||
        print(f'\nCannot move page file to new index path {index_path}')
 | 
			
		||||
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = parse_args(argv[1:], prog=argv[0])
 | 
			
		||||
 | 
			
		||||
    page_path = args.page_path
 | 
			
		||||
    if path_is_page(page_path):
 | 
			
		||||
        print(f'{page_path} is a page')
 | 
			
		||||
        convert_page_to_bundle(page_path)
 | 
			
		||||
    elif path_is_page_bundle(page_path):
 | 
			
		||||
        print(f'{page_path} is a page bundle')
 | 
			
		||||
        if not can_convert_page_bundle_to_page(page_path):
 | 
			
		||||
            print(f'Cannot convert bundle {page_path} to page')
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import sys
 | 
			
		||||
    result = main(sys.argv)
 | 
			
		||||
    sys.exit(0 if not result else result)
 | 
			
		||||
							
								
								
									
										12
									
								
								scripts/erynwells_me/blog.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								scripts/erynwells_me/blog.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
import datetime
 | 
			
		||||
import os.path as osp
 | 
			
		||||
from typing import Optional
 | 
			
		||||
from . import paths
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def post_path(name, *, year: Optional[int] = None):
 | 
			
		||||
    if not year:
 | 
			
		||||
        year = datetime.date.today().year
 | 
			
		||||
    return osp.join(paths.content_path(), 'blog', str(year), name)
 | 
			
		||||
							
								
								
									
										1
									
								
								scripts/erynwells_me/scripting/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								scripts/erynwells_me/scripting/__init__.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
from .command import Command
 | 
			
		||||
							
								
								
									
										24
									
								
								scripts/erynwells_me/scripting/command.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								scripts/erynwells_me/scripting/command.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
class Command:
 | 
			
		||||
    def __init__(self) -> None:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def name(self) -> str:
 | 
			
		||||
        class_name = self.__class__.__name__
 | 
			
		||||
        if class_name.endswith('Command'):
 | 
			
		||||
            trimmed_class_name = class_name.removesuffix('Command')
 | 
			
		||||
            hyphenated_name = re.sub(r'\B([A-Z])', r'-\1', trimmed_class_name)
 | 
			
		||||
            return hyphenated_name.lower()
 | 
			
		||||
        return class_name.lower()
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def help(self) -> str:
 | 
			
		||||
        return ''
 | 
			
		||||
 | 
			
		||||
    def add_arguments(self, _: argparse.ArgumentParser):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
							
								
								
									
										88
									
								
								scripts/erynwells_me/weeknotes.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								scripts/erynwells_me/weeknotes.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,88 @@
 | 
			
		|||
#!/usr/bin/env python3.12
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import datetime
 | 
			
		||||
import os
 | 
			
		||||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Optional
 | 
			
		||||
from . import blog
 | 
			
		||||
from .dates import next_sunday_noon
 | 
			
		||||
from .scripting import Command
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class WeeknotesCommand(Command):
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def weeknotes_filename(year: str, week: str) -> str:
 | 
			
		||||
        return f'weeknotes-{year}w{week}.md'
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def weeknotes_path(*, week_number: Optional[int] = None):
 | 
			
		||||
        if week_number:
 | 
			
		||||
            year = datetime.datetime.now().year
 | 
			
		||||
            week_number_str = str(week_number)
 | 
			
		||||
        else:
 | 
			
		||||
            next_sunday = next_sunday_noon()
 | 
			
		||||
            year = next_sunday.year
 | 
			
		||||
            week_number_str = next_sunday.strftime('%V')
 | 
			
		||||
 | 
			
		||||
        return blog.post_path(WeeknotesCommand.weeknotes_filename(
 | 
			
		||||
            str(year),
 | 
			
		||||
            week_number_str
 | 
			
		||||
        ))
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def help(self) -> str:
 | 
			
		||||
        return 'Work with weeknotes posts'
 | 
			
		||||
 | 
			
		||||
    def add_arguments(self, parser: argparse.ArgumentParser):
 | 
			
		||||
        commands = parser.add_subparsers(title='Weeknotes', required=True)
 | 
			
		||||
 | 
			
		||||
        convert_command = commands.add_parser(
 | 
			
		||||
            'convert',
 | 
			
		||||
            help='Convert a post from a single file to a page bundle and vice versa'
 | 
			
		||||
        )
 | 
			
		||||
        convert_command.set_defaults(handler=self.handle_convert_command)
 | 
			
		||||
 | 
			
		||||
        edit_command = commands.add_parser(
 | 
			
		||||
            'edit',
 | 
			
		||||
            help="Edit the current week's weeknotes post"
 | 
			
		||||
        )
 | 
			
		||||
        edit_command.add_argument(
 | 
			
		||||
            '--editor', '-e',
 | 
			
		||||
            default=os.environ.get('EDITOR', 'nvim'),
 | 
			
		||||
        )
 | 
			
		||||
        edit_command.add_argument('--week', '-w')
 | 
			
		||||
        edit_command.set_defaults(handler=self.handle_edit_command)
 | 
			
		||||
 | 
			
		||||
        show_command = commands.add_parser(
 | 
			
		||||
            'show',
 | 
			
		||||
            aliases=['print'],
 | 
			
		||||
            help="Print a path to the current week's weeknotes post",
 | 
			
		||||
        )
 | 
			
		||||
        show_command.add_argument('--week', '-w')
 | 
			
		||||
        show_command.add_argument('--date', action='store_true')
 | 
			
		||||
        show_command.set_defaults(handler=self.handle_show_command)
 | 
			
		||||
 | 
			
		||||
    def handle_convert_command(self, _: argparse.Namespace):
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    def handle_edit_command(self, args: argparse.Namespace):
 | 
			
		||||
        path = WeeknotesCommand.weeknotes_path(week_number=args.week)
 | 
			
		||||
        subprocess.run(
 | 
			
		||||
            f'{args.editor} "{path}"',
 | 
			
		||||
            stdin=sys.stdin,
 | 
			
		||||
            stdout=sys.stdout,
 | 
			
		||||
            stderr=sys.stderr,
 | 
			
		||||
            env=os.environ,
 | 
			
		||||
            shell=True,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def handle_show_command(self, args: argparse.Namespace):
 | 
			
		||||
        if args.date:
 | 
			
		||||
            if args.week:
 | 
			
		||||
                raise NotImplementedError('Cannot print date with specified week number')
 | 
			
		||||
            print(next_sunday_noon().isoformat())
 | 
			
		||||
        else:
 | 
			
		||||
            print(WeeknotesCommand.weeknotes_path(week_number=args.week))
 | 
			
		||||
							
								
								
									
										26
									
								
								scripts/upload-asset.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								scripts/upload-asset.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
Upload a static asset to a server.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
def parse_args(argv, *a, **kw):
 | 
			
		||||
    parser = argparse.ArgumentParser(*a, **kw)
 | 
			
		||||
    parser.add_argument('file', metavar='FILE', nargs='+')
 | 
			
		||||
    parser.add_argument('destination', metavar='DEST')
 | 
			
		||||
    args = parser.parse_args(argv)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = parse_args(argv[1:], prog=argv[0])
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import sys
 | 
			
		||||
    result = main(sys.argv)
 | 
			
		||||
    sys.exit(0 if not result else result)
 | 
			
		||||
							
								
								
									
										38
									
								
								scripts/website
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										38
									
								
								scripts/website
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
'''
 | 
			
		||||
A Python interface to my personal website, Erynwells.me.
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
from typing import List
 | 
			
		||||
from erynwells_me.scripting import Command
 | 
			
		||||
from erynwells_me.weeknotes import WeeknotesCommand
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
COMMANDS: List[Command] = [
 | 
			
		||||
    WeeknotesCommand(),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_args(commands: List[Command], argv, *a, **kw):
 | 
			
		||||
    parser = argparse.ArgumentParser(*a, **kw)
 | 
			
		||||
 | 
			
		||||
    subcommands = parser.add_subparsers(title='Subcommands', required=True)
 | 
			
		||||
    for command in commands:
 | 
			
		||||
        subcommand_parser = subcommands.add_parser(command.name, help=command.help)
 | 
			
		||||
        command.add_arguments(subcommand_parser)
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args(argv)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = parse_args(COMMANDS, argv[1:], prog=argv[0])
 | 
			
		||||
    args.handler(args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import sys
 | 
			
		||||
    sys.exit(main(sys.argv))
 | 
			
		||||
| 
						 | 
				
			
			@ -1,92 +0,0 @@
 | 
			
		|||
#!/usr/bin/env python3.12
 | 
			
		||||
# Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import datetime
 | 
			
		||||
import os.path
 | 
			
		||||
import subprocess
 | 
			
		||||
from typing import Optional
 | 
			
		||||
from website.dates import next_sunday_noon
 | 
			
		||||
from website.paths import content_path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def weeknotes_path(*, week_number: Optional[int] = None):
 | 
			
		||||
    if week_number:
 | 
			
		||||
        year = datetime.datetime.now().year
 | 
			
		||||
        week_number_str = str(week_number)
 | 
			
		||||
    else:
 | 
			
		||||
        next_sunday = next_sunday_noon()
 | 
			
		||||
        year = next_sunday.year
 | 
			
		||||
        week_number_str = next_sunday.strftime('%V')
 | 
			
		||||
 | 
			
		||||
    weeknotes_filename = f'weeknotes-{year}w{week_number_str}.md'
 | 
			
		||||
    return os.path.join(content_path(), 'blog', str(year), weeknotes_filename)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def parse_args(argv, *a, **kw):
 | 
			
		||||
    parser = argparse.ArgumentParser(*a, **kw)
 | 
			
		||||
    commands = parser.add_subparsers(title='Commands', required=True)
 | 
			
		||||
 | 
			
		||||
    convert_command = commands.add_parser(
 | 
			
		||||
        'convert',
 | 
			
		||||
        help='Convert a post from a single file to a page bundle and vice versa'
 | 
			
		||||
    )
 | 
			
		||||
    convert_command.set_defaults(handler=handle_convert_command)
 | 
			
		||||
 | 
			
		||||
    edit_command = commands.add_parser(
 | 
			
		||||
        'edit',
 | 
			
		||||
        help="Edit the current week's weeknotes post"
 | 
			
		||||
    )
 | 
			
		||||
    edit_command.add_argument(
 | 
			
		||||
        '--editor', '-e',
 | 
			
		||||
        default=os.environ.get('EDITOR', 'nvim'),
 | 
			
		||||
    )
 | 
			
		||||
    edit_command.add_argument('--week', '-w')
 | 
			
		||||
    edit_command.set_defaults(handler=handle_edit_command)
 | 
			
		||||
 | 
			
		||||
    show_command = commands.add_parser(
 | 
			
		||||
        'show',
 | 
			
		||||
        aliases=['print'],
 | 
			
		||||
        help="Print a path to the current week's weeknotes post",
 | 
			
		||||
    )
 | 
			
		||||
    show_command.add_argument('--week', '-w')
 | 
			
		||||
    show_command.add_argument('--date', action='store_true')
 | 
			
		||||
    show_command.set_defaults(handler=handle_show_command)
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args(argv)
 | 
			
		||||
    return args
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def handle_convert_command(args):
 | 
			
		||||
    raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def handle_edit_command(args):
 | 
			
		||||
    path = weeknotes_path(week_number=args.week)
 | 
			
		||||
    subprocess.run(
 | 
			
		||||
        f'{args.editor} "{path}"',
 | 
			
		||||
        stdin=sys.stdin,
 | 
			
		||||
        stdout=sys.stdout,
 | 
			
		||||
        stderr=sys.stderr,
 | 
			
		||||
        env=os.environ,
 | 
			
		||||
        shell=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def handle_show_command(args):
 | 
			
		||||
    if args.date:
 | 
			
		||||
        if args.week:
 | 
			
		||||
            raise NotImplementedError('Cannot print date with specified week number')
 | 
			
		||||
        print(next_sunday_noon().isoformat())
 | 
			
		||||
    else:
 | 
			
		||||
        print(weeknotes_path(week_number=args.week))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main(argv):
 | 
			
		||||
    args = parse_args(argv[1:], prog=argv[0])
 | 
			
		||||
    args.handler(args)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    import sys
 | 
			
		||||
    result = main(sys.argv)
 | 
			
		||||
    sys.exit(0 if not result else result)
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue