├── .docker └── verify_hugo_checksum.sh ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── __init__.py ├── commands ├── __init__.py ├── author.py ├── cli.py ├── convert.py ├── create.py ├── dataset.py ├── preview.py ├── push.py ├── update.py └── util.py ├── config.py ├── constants.py ├── converters ├── __init__.py ├── ipynb.py └── rmd.py ├── journal ├── journal.toml ├── requirements.txt ├── setup.py └── templates ├── author.md ├── daily_log.md ├── dataset_template.md ├── knowledge_template.Rmd ├── knowledge_template.ipynb └── knowledge_template.md /.docker/verify_hugo_checksum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if ! sha256sum --ignore-missing --status -c "$1"; then 4 | echo "Invalid checksum detected for Hugo... exiting" 5 | exit 1 6 | fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | .cache.json 104 | .vscode -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3-slim 2 | 3 | LABEL maintainer="labs@duo.com" 4 | 5 | ARG hugoversion=0.57.2 6 | 7 | RUN apt-get update && \ 8 | apt-get install --no-install-recommends -y git wget ssh && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | # Install Hugo 12 | WORKDIR /opt/hugo 13 | COPY ./.docker/verify_hugo_checksum.sh . 14 | RUN wget -q https://github.com/gohugoio/hugo/releases/download/v${hugoversion}/hugo_${hugoversion}_Linux-64bit.tar.gz && \ 15 | wget -q https://github.com/gohugoio/hugo/releases/download/v${hugoversion}/hugo_${hugoversion}_checksums.txt && \ 16 | ./verify_hugo_checksum.sh hugo_${hugoversion}_checksums.txt && \ 17 | tar -C /usr/bin -xzf hugo_${hugoversion}_Linux-64bit.tar.gz hugo && \ 18 | rm -rf /opt/hugo 19 | 20 | # Setup the non privleged journal user 21 | RUN groupadd -g 999 journal && \ 22 | useradd -u 999 -m -g journal journal 23 | 24 | RUN mkdir /journal && \ 25 | chown journal:journal /journal && \ 26 | mkdir /opt/journal-cli && \ 27 | chown journal:journal /opt/journal-cli && \ 28 | touch /.journal.toml && \ 29 | chown journal:journal /.journal.toml 30 | 31 | # Install Journal CLI dependencies 32 | WORKDIR /opt/journal-cli 33 | COPY requirements.txt . 34 | RUN pip install -U -r requirements.txt 35 | 36 | # Finally, set up and install Journal 37 | USER journal 38 | ENV JOURNAL_PATH=/journal 39 | ENV JOURNAL_CONFIG=/.journal.toml 40 | ENV JOURNAL_DOCKER=1 41 | COPY . . 42 | ENTRYPOINT [ "./journal" ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Cisco Systems, Inc. and/or its affiliates 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # journal-cli 2 | 3 | A command-line client for Journal. You can find the command reference [here](https://duo-labs.github.io/journal/post/team/jwright/command_reference/). -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duo-labs/journal-cli/3b148463ba23a49f97ad17f65ac5d87f70d6b52c/__init__.py -------------------------------------------------------------------------------- /commands/__init__.py: -------------------------------------------------------------------------------- 1 | from commands.cli import cli 2 | from commands.convert import convert 3 | from commands.create import create 4 | from commands.preview import preview 5 | from commands.push import push 6 | from commands.update import update 7 | from commands.dataset import dataset 8 | from commands.author import author 9 | 10 | cli.add_command(author) 11 | cli.add_command(convert) 12 | cli.add_command(create) 13 | cli.add_command(preview) 14 | cli.add_command(push) 15 | cli.add_command(update) 16 | cli.add_command(dataset) 17 | -------------------------------------------------------------------------------- /commands/author.py: -------------------------------------------------------------------------------- 1 | import click 2 | import os 3 | import getpass 4 | 5 | from os import path 6 | from shutil import copyfile 7 | 8 | from config import config 9 | from commands.util import parse_template 10 | 11 | 12 | def load_author_template(): 13 | """ 14 | Finds path to the default author template. 15 | 16 | Returns: 17 | str -- Path to the default author template. 18 | """ 19 | return path.join(path.dirname(__file__), '../templates', 'author.md') 20 | 21 | 22 | def generate_author_path(username): 23 | """Returns a suitable path for a new author. 24 | 25 | Arguments: 26 | name {str} -- An author path in authors/ 27 | """ 28 | return path.join(config['journal_path'], 'content', 'authors', username) 29 | 30 | 31 | def generate_author_content_path(username): 32 | """Returns the path where posts will be stored for a given author. 33 | 34 | Arguments: 35 | username {str} -- The author's username 36 | """ 37 | return path.join(config['journal_path'], 'content', 'post', 'team', 38 | username) 39 | 40 | 41 | def create_author(username, name, avatar): 42 | """Creates a new author for the Journal instance. 43 | 44 | Arguments: 45 | username {str} -- The author's username 46 | name {str} -- The name of the author 47 | avatar {str} -- The filepath to an avatar image 48 | """ 49 | if not username: 50 | username = config['username'] 51 | click.secho('Setting up the author for {}'.format(username), fg='green') 52 | 53 | while not username: 54 | username = click.prompt("Username") 55 | author_path = generate_author_path(username) 56 | if path.exists(author_path): 57 | click.secho( 58 | 'An author already exists at {}'.format(author_path), fg='red') 59 | return 60 | 61 | while not name: 62 | name = click.prompt("Name") 63 | while not avatar: 64 | avatar = click.prompt("Path to avatar image") 65 | avatar = path.expanduser(avatar) 66 | if not path.exists(avatar): 67 | click.secho( 68 | 'The file at {} does not exist'.format(avatar), fg='yellow') 69 | avatar = None 70 | TEMPLATE_CONTEXT = {'username': username, 'name': name} 71 | 72 | _, avatar_extension = path.splitext(avatar) 73 | author_content_path = generate_author_content_path(username) 74 | author_md_path = path.join(author_path, '_index.md') 75 | author_avatar_path = path.join(author_path, 76 | 'avatar{}'.format(avatar_extension)) 77 | 78 | os.makedirs(author_path, exist_ok=True) 79 | os.makedirs(author_content_path, exist_ok=True) 80 | 81 | template_path = load_author_template() 82 | if not path.exists(template_path): 83 | click.secho( 84 | 'No author template found at {}'.format(template_path), fg='red') 85 | return 86 | 87 | output = parse_template(template_path, TEMPLATE_CONTEXT) 88 | with open(author_md_path, 'w') as author_file: 89 | author_file.write(output) 90 | copyfile(avatar, author_avatar_path) 91 | click.secho('Created author at {}'.format(author_path), fg='green') 92 | 93 | 94 | @click.command() 95 | @click.argument('username', required=False) 96 | @click.option('--name', required=False) 97 | @click.option('--avatar', type=click.Path(exists=True)) 98 | def author(username, name, avatar): 99 | """Creates a new author for the Journal instance. 100 | """ 101 | create_author(username, name, avatar) -------------------------------------------------------------------------------- /commands/cli.py: -------------------------------------------------------------------------------- 1 | import click 2 | 3 | 4 | @click.group() 5 | def cli(): 6 | pass 7 | -------------------------------------------------------------------------------- /commands/convert.py: -------------------------------------------------------------------------------- 1 | import click 2 | 3 | from os import path 4 | 5 | from constants import POST_DIRECTORY 6 | from converters import convert_file 7 | from commands.util import get_last_modified 8 | from config import config 9 | 10 | 11 | @click.command() 12 | @click.argument('filename', required=False) 13 | def convert(filename): 14 | """Converts a non-Markdown post into a format that's acceptable by Journal. 15 | 16 | It converts Jupyter notebooks to Markdown, extracting images and cleaning 17 | up output cells. 18 | 19 | It converts Rmd files to HTML, parsing out the body of the post into a 20 | separate file. 21 | """ 22 | # Get the file we need to work with, making sure it exists 23 | if not filename: 24 | filename = get_last_modified( 25 | path.join(config.get('journal_path'), POST_DIRECTORY)) 26 | elif not path.isabs(filename): 27 | filename = path.abspath( 28 | path.join(config.get('journal_path'), POST_DIRECTORY, filename)) 29 | 30 | if not path.exists(filename): 31 | click.secho('File "{}" not found'.format(filename), fg='red') 32 | return 33 | 34 | # Markdown is supported by default, so we don't need to convert it 35 | _, ext = path.splitext(filename.lower()) 36 | if ext == '.md': 37 | click.secho( 38 | 'Markdown is supported already - no conversion needed', fg='green') 39 | return 40 | 41 | try: 42 | converted_filename = convert_file(filename) 43 | click.secho( 44 | 'Converted post to {}'.format(converted_filename), fg='green') 45 | except Exception as e: 46 | click.secho(str(e), fg='red') -------------------------------------------------------------------------------- /commands/create.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import click 4 | 5 | from os import path 6 | from datetime import datetime 7 | 8 | from config import config 9 | from commands.author import create_author, generate_author_path 10 | from commands.util import launch_editor, parse_template, generate_post_path 11 | 12 | 13 | def load_template(filename, daily=False): 14 | """Loads the correct filepath to the template based on the provided filename. 15 | 16 | If the path to the template is relative, we will assume it's located in the 17 | templates/ directory. Otherwise, we'll return the absolute path since 18 | that's what was specified by the user in the configuraiton. 19 | 20 | Arguments: 21 | filename {str} -- [description] 22 | daily {bool} -- Whether or not this is a daily post 23 | """ 24 | template = '' 25 | if daily: 26 | template = config['templates'].get('daily_log') 27 | 28 | else: 29 | _, ext = path.splitext(filename.lower()) 30 | template = config['templates'].get(ext[1:]) 31 | 32 | if not path.isabs(template): 33 | template = path.abspath( 34 | path.join(path.dirname(__file__), '../templates', template)) 35 | return template 36 | 37 | 38 | @click.command() 39 | @click.argument('filename', required=False) 40 | @click.option( 41 | '--template', 42 | '-t', 43 | default=None, 44 | help='The template to use when creating the new post', 45 | type=click.Path()) 46 | def create(filename, template): 47 | """Creates a new Journal post. 48 | 49 | If no filename is specified, we'll create a daily post. If no template is 50 | specified, the default template for the provided filetype is used. 51 | """ 52 | TEMPLATE_CONTEXT = { 53 | 'now': datetime.utcnow, 54 | 'username': config['username'], 55 | } 56 | 57 | while not path.exists(generate_author_path(config['username'])): 58 | click.secho( 59 | 'Author {} does not exist. Let\'s create that author now'.format( 60 | config['username']), 61 | fg='yellow') 62 | create_author(config['username'], None, None) 63 | 64 | # Handle the default case of making a new daily post 65 | daily = False 66 | if not filename: 67 | filename = 'daily-log-{}.md'.format( 68 | datetime.now().strftime('%m-%d-%Y')) 69 | daily = True 70 | 71 | filepath = generate_post_path(filename) 72 | 73 | # Validate the filename to make sure it has a valid extension 74 | basename, ext = path.splitext(filename.lower()) 75 | if ext[1:] not in config['templates']: 76 | click.secho( 77 | 'Unknown extension found for file {}. Valid extensions are {}'. 78 | format( 79 | filename, ', '.join(extension 80 | for extension in config['templates'] 81 | if extension != 'daily_log')), 82 | fg='red') 83 | return 84 | 85 | TEMPLATE_CONTEXT['title'] = basename.replace('_', ' ').replace('-', ' ') 86 | 87 | if not template: 88 | template = load_template(filename, daily=daily) 89 | 90 | if not path.exists(template): 91 | click.secho( 92 | 'Error - Template "{}" not found.'.format(template), fg='red') 93 | 94 | output = parse_template(template, TEMPLATE_CONTEXT) 95 | if path.exists(filepath): 96 | click.secho( 97 | 'The file at "{}" already exists.'.format(filepath), fg='red') 98 | return 99 | 100 | # TODO: Make the directory if it doesn't exist 101 | 102 | with open(filepath, 'w') as output_file: 103 | output_file.write(output) 104 | 105 | click.secho('Post "{}" created.'.format(filepath), fg='green') 106 | 107 | if config['editor'].get('enabled'): 108 | launch_editor(filepath) 109 | sys.exit(0) -------------------------------------------------------------------------------- /commands/dataset.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import hashlib 4 | import io 5 | 6 | import click 7 | 8 | from os import path 9 | from datetime import datetime 10 | 11 | from config import config 12 | from commands.util import launch_editor, parse_template 13 | 14 | 15 | def load_dataset_template(): 16 | """ 17 | Finds path to the default dataset template. 18 | 19 | Returns: 20 | str -- Path to default dataset template. 21 | """ 22 | return path.join( 23 | path.dirname(__file__), '../templates', 'dataset_template.md') 24 | 25 | 26 | def check_pandas_installed(): 27 | import pkgutil 28 | return pkgutil.find_loader("pandas") 29 | 30 | 31 | def compute_md5(filename): 32 | try: 33 | md5 = hashlib.md5() 34 | with open(filename, "rb") as fh: 35 | while True: 36 | bytes = fh.read(io.DEFAULT_BUFFER_SIZE) 37 | if not bytes: 38 | break 39 | md5.update(bytes) 40 | return md5.hexdigest() 41 | except Exception as e: 42 | return '' 43 | 44 | 45 | AUTO_PARSE_EXTS = [".csv", ".tsv", ".json", ".xls", ".xlsx", ".parquet"] 46 | AUTO_PARSE_THRESHOLD = 100e6 47 | 48 | 49 | def auto_parse_schema(location): 50 | """ 51 | Attempts to automatically parse the file at location (if local) and extract a schema. 52 | This function will only parse files that have an extension in AUTO_PARSE_EXTS and are 53 | smaller than AUTO_PARSE_THRESHOLD bytes. 54 | 55 | The function returns a rendered YAML array if the schema was parsed successfully, None 56 | otherwise. 57 | 58 | TODO: The parsing is done by Pandas (using the various pd.read_* functions), and the schema 59 | is just a stringification of DataFrame.dtypes, which has several downsides (e.g. string columns 60 | have dtype 'object'). 61 | 62 | Returns: 63 | str -- A rendered YAML containing the schema, suitable for inclusion in the template. 64 | """ 65 | if not path.exists(location): 66 | return None 67 | if not check_pandas_installed(): 68 | click.secho("Pandas is not installed, skipping parsing.", fg="yellow") 69 | return None 70 | 71 | _, ext = path.splitext(location.lower()) 72 | if ext not in AUTO_PARSE_EXTS: 73 | click.secho( 74 | "Unrecognized extension {}, skipping parsing.".format(ext), 75 | fg="yellow") 76 | 77 | size = path.getsize(location) 78 | if size > AUTO_PARSE_THRESHOLD: 79 | click.secho("File is large, skipping parsing.") 80 | return None 81 | 82 | import pandas as pd 83 | 84 | try: 85 | if ext == ".csv": 86 | df = pd.read_csv(location, parse_dates=True, nrows=10) 87 | elif ext == ".tsv": 88 | df = pd.read_csv( 89 | location, delimiter='\t', parse_dates=True, nrows=10) 90 | elif ext == ".json": 91 | df = pd.read_json(location) 92 | elif ext == ".parquet": 93 | df = pd.read_parquet(location) 94 | elif ext == ".xls" or ext == ".xlsx": 95 | df = pd.read_excel(location) 96 | 97 | schema = [ 98 | "- {}: {} [No description]".format(field, str(kind)) 99 | for field, kind in df.dtypes.to_dict().items() 100 | ] 101 | 102 | click.secho( 103 | "{} fields automatically parsed. Please check schema for accuracy." 104 | .format(len(schema))) 105 | return "\n".join(schema) 106 | 107 | except Exception as e: 108 | print(e) 109 | click.secho("Pandas could not parse this file, skipping parsing.") 110 | return None 111 | 112 | 113 | def generate_dataset_path(name): 114 | """ 115 | Returns a suitable path for a new dataset. 116 | 117 | Arguments: 118 | name {str} -- Name of the dataset 119 | 120 | Returns: 121 | str -- A dataset path in datasets/ 122 | """ 123 | return path.join(config['journal_path'], 'content', 'datasets', name) 124 | 125 | 126 | @click.command() 127 | @click.argument('location', required=True) 128 | @click.argument('name', required=False) 129 | def dataset(location, name): 130 | """Add a new dataset to Journal. 131 | """ 132 | 133 | _, basename = path.split(location) 134 | stem, ext = path.splitext(basename.lower()) 135 | if not name: 136 | name = stem 137 | 138 | TEMPLATE_CONTEXT = { 139 | 'now': datetime.utcnow, 140 | 'location': location, 141 | 'format': ext[1:], 142 | 'name': name, 143 | 'username': config['username'], 144 | } 145 | 146 | dataset_path = generate_dataset_path(name) 147 | dataset_md_path = path.join(dataset_path, '_index.md') 148 | 149 | if path.exists(dataset_md_path): 150 | click.secho( 151 | 'A dataset already exist in {}.'.format(dataset_path), fg='red') 152 | return 153 | 154 | template = load_dataset_template() 155 | if not path.exists(template): 156 | click.secho( 157 | 'Error - Template "{}" not found.'.format(template), fg='red') 158 | return 159 | 160 | TEMPLATE_CONTEXT['schema'] = auto_parse_schema(location) 161 | TEMPLATE_CONTEXT['md5_hash'] = compute_md5(location) 162 | 163 | output = parse_template(template, TEMPLATE_CONTEXT) 164 | 165 | os.makedirs(dataset_path, exist_ok=True) 166 | 167 | with open(dataset_md_path, 'w') as output_file: 168 | output_file.write(output) 169 | 170 | click.secho( 171 | 'Dataset {} was created with path "{}".'.format(name, dataset_md_path), 172 | fg='green') 173 | 174 | if config['editor'].get('enabled'): 175 | launch_editor(dataset_md_path) 176 | sys.exit(0) -------------------------------------------------------------------------------- /commands/preview.py: -------------------------------------------------------------------------------- 1 | import click 2 | import subprocess 3 | 4 | from distutils.spawn import find_executable 5 | 6 | from config import config 7 | from .util import print_hugo_install_instructions, is_docker 8 | 9 | HUGO_COMMAND = 'hugo' 10 | 11 | 12 | @click.command() 13 | @click.option( 14 | '--drafts', '-D', default=True, help='Whether to render draft posts') 15 | def preview(drafts): 16 | """Launches Hugo's preview server to live reload pages. 17 | 18 | If the Hugo executable isn't found on the PATH, then we'll provide some 19 | installation instructions showing how best to install it. 20 | """ 21 | if not find_executable(HUGO_COMMAND): 22 | print_hugo_install_instructions() 23 | return 24 | command = ['hugo', 'server'] 25 | if drafts: 26 | command.append('-D') 27 | if is_docker(): 28 | command.extend(['--bind', '0.0.0.0']) 29 | try: 30 | cmd = subprocess.Popen(command, cwd=config['journal_path']) 31 | cmd.wait() 32 | except OSError as e: 33 | click.secho( 34 | 'Something went wrong when running "{}": {}'.format( 35 | ' '.join(cmd), e), 36 | fg='red') 37 | -------------------------------------------------------------------------------- /commands/push.py: -------------------------------------------------------------------------------- 1 | import git 2 | import json 3 | import click 4 | import subprocess 5 | 6 | try: 7 | from urllib.request import Request, urlopen 8 | except ImportError: 9 | from urllib2 import Request, urlopen 10 | 11 | from os import path 12 | from datetime import datetime 13 | 14 | from constants import FORTUNE_API_URL, POST_DIRECTORY 15 | from config import config 16 | from commands.util import get_last_modified 17 | from converters import convert_file 18 | 19 | 20 | def generate_commit_message(filename): 21 | """Returns a generic commit message. 22 | 23 | Arguments: 24 | filename {str} -- The absolute path to the added file 25 | 26 | Returns: 27 | str -- The generated commit message 28 | """ 29 | 30 | filename = path.basename(filename) 31 | return 'Update to {} from {} at {} UTC'.format(filename, 32 | config['username'], 33 | datetime.now()) 34 | 35 | 36 | def deploy_git(filepath): 37 | """Performs the traditional git merge/push dance. 38 | """ 39 | 40 | repo = git.Repo(config['journal_path']) 41 | static_path = path.join(config['journal_path'], 'static/images') 42 | # Commit the changes 43 | repo.index.add([filepath, static_path]) 44 | # List the files being committed 45 | for diff in repo.index.diff("HEAD"): 46 | click.secho('[+] Adding {}'.format(diff.a_path), fg='green') 47 | repo.index.commit(generate_commit_message(filepath)) 48 | # Pull the latest from upstream 49 | subprocess.check_output(['git', 'checkout', 'master'], 50 | cwd=config['journal_path']) 51 | subprocess.check_output(['git', 'pull', '--rebase'], 52 | cwd=config['journal_path']) 53 | subprocess.check_output(['git', 'push'], cwd=config['journal_path']) 54 | 55 | 56 | @click.command() 57 | @click.argument('filename', required=False) 58 | def push(filename): 59 | """Pushes the post to Journal. 60 | 61 | Push adds the note to the actual Git repo, and deploys it 62 | using the standard pull/merge/push Git workflow. 63 | 64 | By default, if the `filename` argument isn't provided, the last modified 65 | file is deployed. 66 | """ 67 | 68 | # Determine the correct filename to use based on the arguments 69 | if not filename: 70 | filename = get_last_modified( 71 | path.join(config.get('journal_path'), POST_DIRECTORY)) 72 | elif not path.isabs(filename): 73 | filename = path.abspath( 74 | path.join(config.get('journal_path'), POST_DIRECTORY, filename)) 75 | 76 | if not path.exists(filename): 77 | click.secho('Post "{}" not found'.format(filename), fg='red') 78 | return 79 | 80 | post_filepath = path.relpath( 81 | filename, path.join(config.get('journal_path'), POST_DIRECTORY)) 82 | 83 | # Before we do anything, let's confirm that this is what the user is 84 | # expecting to do. 85 | if not click.confirm( 86 | click.style('Push {}?'.format(post_filepath), fg='yellow')): 87 | return 88 | 89 | click.secho('Pushing to the Journal', fg='green') 90 | try: 91 | filename = convert_file(filename) 92 | deploy_git(filename) 93 | if not config.get('fortune', False): 94 | click.secho( 95 | 'Push successful! You should be good to go.', fg='green') 96 | else: 97 | # Let's get you a fortune cuz you just dropped KNOWLEDGE! 98 | request = Request( 99 | FORTUNE_API_URL, 100 | data=None, 101 | headers={ 102 | 'User-Agent': 103 | 'Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11' 104 | }) 105 | try: 106 | fortune = urlopen(request).read().decode('utf-8') 107 | except Exception as e: 108 | fortune = ":-( Lame, error getting your fortune. Guess it's not your lucky day. (%s)" % ( 109 | e) 110 | click.secho( 111 | "Push successful! Here's your fortune...\n\t'%s'" % 112 | (json.loads(fortune).strip()), 113 | fg='green') 114 | except Exception as e: 115 | click.secho('Error: {}'.format(e)) 116 | -------------------------------------------------------------------------------- /commands/update.py: -------------------------------------------------------------------------------- 1 | import click 2 | import subprocess 3 | 4 | from os import path 5 | 6 | from config import config 7 | 8 | 9 | @click.command() 10 | def update(): 11 | """Updates the journal CLI. 12 | 13 | The updates work by pulling the latest changes from Github. 14 | """ 15 | repo_path = path.abspath(path.join(path.dirname(__file__), '../')) 16 | try: 17 | subprocess.check_output(['git', 'pull', '--rebase'], cwd=repo_path) 18 | click.secho('journal client successfully updated!', fg='green') 19 | 20 | subprocess.check_output([ 21 | 'git', 'submodule', 'update', '--init', '--remote', '--recursive' 22 | ], 23 | cwd=config['journal_path']) 24 | click.secho('Journal theme successfully updated!', fg='green') 25 | except Exception as e: 26 | click.secho(str(e), fg='red') 27 | return -------------------------------------------------------------------------------- /commands/util.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import fnmatch 4 | import click 5 | import re 6 | 7 | from jinja2 import Environment, FileSystemLoader 8 | 9 | from config import config 10 | 11 | 12 | def datetimefilter(value, format='%Y-%m-%d'): 13 | """Simple Jinja2 filter to convert datetime values to the desired format 14 | 15 | Arguments: 16 | value {datetime.datetime} -- The datetime value 17 | 18 | Keyword Arguments: 19 | format {str} -- The datetime format string (default: {'%Y-%m-%d'}) 20 | 21 | Returns: 22 | str -- The datetime formatted according to the provided format string. 23 | """ 24 | 25 | return value.strftime(format) 26 | 27 | 28 | def get_last_modified(directory): 29 | """Returns the absolute path to the last modified file in the directory. 30 | 31 | Arguments: 32 | directory {str} -- The directory to search 33 | """ 34 | # Unfortunately, Python < 3.5 doesn't have the glob recursive operator 35 | # so, according to StackOverflow, the best approach is to use a mix of 36 | # os.walk and fnmatch.filter. Seems reasonable. 37 | valid_files = [] 38 | for root, _, files in os.walk(directory): 39 | # Get all the files in the directory that match one of the valid 40 | # extensions. 41 | for extension in config['templates']: 42 | if extension == 'daily_log': 43 | continue 44 | valid_files.extend( 45 | fnmatch.filter( 46 | [os.path.join(root, filename) for filename in files], 47 | '*{}'.format(extension))) 48 | 49 | return max(valid_files, key=os.path.getmtime) 50 | 51 | 52 | def launch_editor(filepath): 53 | """Launches an editor with the provided filepath 54 | 55 | Arguments: 56 | filepath {str} -- The file to open in the configured editor 57 | """ 58 | command = [config['editor'].get('command')] 59 | for arg in config['editor'].get('args'): 60 | command.append(arg.format(filepath)) 61 | try: 62 | cmd = subprocess.Popen(command) 63 | cmd.wait() 64 | except OSError: 65 | if config['editor'].get('command') == "code": 66 | click.secho( 67 | "The 'code' editor was specified in your config file but it doesn't seem to be setup, have a look here for instuctions on how to fix that: ", 68 | nl=False, 69 | fg='red') 70 | click.secho( 71 | "https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line" 72 | ) 73 | else: 74 | click.secho( 75 | 'Unknown editor "%s" specified, please check your configuration file' 76 | % (config['editor'].get('command')), 77 | fg='red') 78 | 79 | 80 | def parse_template(filepath, ctx): 81 | """Parses a Jinja template from the provided filepath and context 82 | 83 | Arguments: 84 | filepath {str} -- The filepath to the Jinja template 85 | ctx {dict} -- Context to send to the template 86 | """ 87 | # Setup the Jinja2 template environment 88 | env = Environment(loader=FileSystemLoader(os.path.dirname(filepath))) 89 | 90 | # Parse the Jinja2 template 91 | env.filters['strftime'] = datetimefilter 92 | j2_template = env.get_template(os.path.basename(filepath)) 93 | output = j2_template.render(ctx) 94 | return output 95 | 96 | 97 | def print_hugo_install_instructions(): 98 | """Prints out instructions on how to install Hugo 99 | """ 100 | click.secho( 101 | ''' 102 | It appears that Hugo isn't installed, which is needed to 103 | launch the preview server. 104 | 105 | If you have Homebrew, you can install Hugo using "brew install hugo". 106 | Otherwise, you can get the binary from here: 107 | 108 | https://gohugo.io/getting-started/installing/. 109 | 110 | After you have Hugo installed and can run "hugo -h" successfully, try 111 | running "journal preview" again. If you run into any issues, reach out on 112 | GitHub and we'll be happy to help.''', 113 | fg='yellow') 114 | 115 | 116 | def generate_image_path(post_slug, filename): 117 | """Returns the default namespaced images path for a file. 118 | 119 | By default, it's recommended to store images in 120 | static/images/team///, which is what this returns. 121 | 122 | Arguments: 123 | post_slug {str} -- The post slug to be used when building the path 124 | filename {str} -- The image filename 125 | 126 | Returns: 127 | str -- An absolute path to the images directory at 128 | static/images/team/// 129 | """ 130 | return os.path.join(config['journal_path'], 'static', 'images', 'team', 131 | config['username'], post_slug, filename) 132 | 133 | 134 | def generate_post_path(filename): 135 | """Returns the default namespaced project path for a file. 136 | 137 | If the filename starts with "daily-log", we assume it's a daily log and 138 | move it one subdirectory lower into the "daily" directory for backwards 139 | compatibility. 140 | 141 | Arguments: 142 | filename {str} -- The filename of the post 143 | 144 | Returns: 145 | str -- A project path namespaced under team// 146 | """ 147 | project_path = os.path.join(config['journal_path'], 'content', 'post', 148 | 'team/{}/'.format(config['username'])) 149 | if filename.startswith('daily-log'): 150 | project_path = os.path.join(project_path, 'daily') 151 | project_path = os.path.join(project_path, filename) 152 | return project_path 153 | 154 | 155 | def generate_slug(title): 156 | """Generates a filename slug from a title. 157 | 158 | This is the reverse of the typical slug -> title operation. 159 | 160 | Arguments: 161 | title {str} -- The post title 162 | """ 163 | slug = title.lower() 164 | # Convert special characters 165 | slug = re.sub('[^a-zA-Z0-9\-_\.]', '-', slug) 166 | # Trim the end 167 | slug = re.sub('[^a-zA-Z0-9]+$', '', slug) 168 | return slug 169 | 170 | def is_docker(): 171 | """Returns whether or not Journal is being executed in Docker""" 172 | return os.environ.get('JOURNAL_DOCKER', False) -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | from os import environ, path 2 | 3 | import click 4 | import getpass 5 | import toml 6 | import shutil 7 | import sys 8 | import subprocess 9 | 10 | import git 11 | 12 | from constants import JOURNAL_UPSTREAM 13 | 14 | SETUP_REPOSITORY_MESSAGE = """ 15 | It looks like this is your first time using Journal. 16 | 17 | To set things up, it's assumed you've already made a fork or clone 18 | of the Git repository at {}. 19 | 20 | What is the URL of your repository?""".format(JOURNAL_UPSTREAM) 21 | 22 | SETUP_JOURNAL_PATH_MESSAGE = """ 23 | Next, we'll get a local clone of this repository. This is where your 24 | posts will be stored. 25 | 26 | Where would you like this repository cloned to?""" 27 | 28 | SETUP_CONFIRMATION_MESSAGE = """ 29 | You're all set! You can create your first author using: 30 | 31 | journal author""" 32 | 33 | 34 | def load_default_config(): 35 | """Loads and returns the default configuration as a dict 36 | 37 | Returns: 38 | dict -- The loaded configuration 39 | """ 40 | config_file = path.abspath( 41 | path.join(path.dirname(__file__), 'journal.toml')) 42 | return toml.load(config_file) 43 | 44 | 45 | def setup_config(config_path, config): 46 | """Validates the configuration and fills in missing metadata. 47 | 48 | Arguments: 49 | content {dict} -- The initial loaded configuration 50 | """ 51 | # If the journal_path exists, then we're probably good. 52 | if config.get('journal_path'): 53 | return config 54 | 55 | # Then, we'll clone the repo 56 | click.secho(SETUP_REPOSITORY_MESSAGE, fg='green') 57 | journal_path = environ.get('JOURNAL_PATH', '') 58 | repo_url = environ.get('JOURNAL_REPO', '') 59 | while not repo_url: 60 | repo_url = click.prompt("Repository URL") 61 | config['upstream_repo'] = repo_url 62 | while not journal_path: 63 | journal_path = path.expanduser(click.prompt("Path")) 64 | dir_name, _ = path.split(journal_path) 65 | 66 | if not path.exists(dir_name): 67 | click.secho( 68 | 'Directory does not exist: {}'.format(journal_path), 69 | fg='yellow') 70 | journal_path = "" 71 | config['journal_path'] = journal_path 72 | try: 73 | # Check if we need to clone the repo - this catches the case where may 74 | # already have Journal cloned 75 | repo = git.Repo(config['journal_path']) 76 | if repo.remote().url != config['upstream_repo']: 77 | click.secho( 78 | 'Repository exists, but isn\'t pointing to {}'.format( 79 | config['upstream_repo']), 80 | fg='red') 81 | except Exception as e: 82 | try: 83 | click.secho( 84 | 'Cloning from {} to {}'.format(config['upstream_repo'], 85 | config['journal_path']), 86 | fg='green') 87 | # Using subprocess instead of GitPython to properly handle tracking 88 | # progress since this can take a bit of time. 89 | subprocess.check_output( 90 | ['git', 'clone', config['upstream_repo'], journal_path]) 91 | subprocess.check_output(['git', 'submodule', 'update', '--init'], 92 | cwd=config['journal_path']) 93 | except Exception as e: 94 | click.secho('Error cloning repo: {}'.format(e), fg='red') 95 | sys.exit(1) 96 | 97 | # Fallback to the correct username if not specified 98 | if not config.get('username'): 99 | config['username'] = environ.get('JOURNAL_USER', getpass.getuser()) 100 | 101 | # Save the config 102 | click.secho( 103 | 'Saving new configuration to: {}'.format(config_path), fg='green') 104 | with open(config_path, 'w') as config_output: 105 | config_output.write(toml.dumps(config)) 106 | 107 | click.secho(SETUP_CONFIRMATION_MESSAGE, fg='green') 108 | return config 109 | 110 | 111 | def load_config(config_path=None): 112 | if config_path is None: 113 | config_path = environ.get( 114 | 'JOURNAL_CONFIG', path.join(path.expanduser('~'), '.journal.toml')) 115 | 116 | if not path.exists(config_path): 117 | click.secho( 118 | 'Configuration not found at "{}"'.format(config_path), fg='yellow') 119 | shutil.copy( 120 | path.abspath(path.join(path.dirname(__file__), 'journal.toml')), 121 | config_path) 122 | 123 | with open(config_path) as f: 124 | return setup_config(config_path, toml.load(f)) 125 | 126 | 127 | config = load_config() 128 | -------------------------------------------------------------------------------- /constants.py: -------------------------------------------------------------------------------- 1 | JOURNAL_UPSTREAM = "https://github.com/duo-labs/journal" 2 | FORTUNE_API_URL = "https://helloacm.com/api/fortune/" 3 | POST_DIRECTORY = 'content/post/' -------------------------------------------------------------------------------- /converters/__init__.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | import click 4 | 5 | from .ipynb import IpynbConverter 6 | from .rmd import RmdConverter 7 | 8 | CONVERTERS = {'.ipynb': IpynbConverter, '.rmd': RmdConverter} 9 | 10 | 11 | class ConversionError(Exception): 12 | """A generic error for known conversion errors""" 13 | pass 14 | 15 | 16 | def convert_file(filepath): 17 | """Applies the correct converter depending on the filetype. 18 | 19 | Arguments: 20 | filepath {str} -- The absolute path to the file that needs to be 21 | converted 22 | 23 | Returns: 24 | str -- The converted filename to be used for further operations (like 25 | pushing) 26 | """ 27 | _, ext = path.splitext(filepath.lower()) 28 | if ext == '.md': 29 | return filepath 30 | if ext not in CONVERTERS: 31 | raise ConversionError( 32 | "We don't have a way to convert {} files yet".format(ext)) 33 | try: 34 | converter_cls = CONVERTERS[ext] 35 | converter = converter_cls(filepath) 36 | return converter.convert() 37 | except Exception as e: 38 | raise ConversionError('Error converting {}: {}'.format(filepath, e)) 39 | -------------------------------------------------------------------------------- /converters/ipynb.py: -------------------------------------------------------------------------------- 1 | from os import path, makedirs 2 | 3 | import click 4 | 5 | from config import config 6 | from commands.util import generate_image_path, generate_post_path 7 | 8 | IPYNB_TEMPLATE = ''' 9 | {%- extends 'markdown.tpl' -%} 10 | 11 | {% block data_text scoped %} 12 | ```ipynb-output 13 | {{ output.data['text/plain']}} 14 | ``` 15 | {% endblock data_text %} 16 | 17 | {% block stream %} 18 | ```ipynb-output 19 | {{ output.text}} 20 | ``` 21 | {% endblock stream %} 22 | ''' 23 | 24 | 25 | class IpynbConverter: 26 | def __init__(self, filepath): 27 | self.filepath = filepath 28 | self.post_slug, _ = path.splitext(path.basename(self.filepath)) 29 | 30 | def save_image(self, image_name, content): 31 | """Saves an image to the correct directory 32 | 33 | Arguments: 34 | image_name {str} -- The filename of the image 35 | content {bytes} -- The raw image bytes 36 | """ 37 | image_path = generate_image_path(self.post_slug, image_name) 38 | makedirs(path.dirname(image_path), exist_ok=True) 39 | click.secho('Saving image to {}'.format(image_path), fg='green') 40 | with open(image_path, 'wb') as image_output: 41 | image_output.write(content) 42 | 43 | def convert(self): 44 | """Converts a Jupyter notebook for use in Journal. 45 | 46 | Specifically, this function: 47 | """ 48 | import nbformat 49 | from traitlets.config import Config 50 | from nbconvert import MarkdownExporter 51 | 52 | notebook = nbformat.read(self.filepath, as_version=4) 53 | # Determine the static folder path and configure the Config 54 | c = Config() 55 | c.ExtractOutputPreprocessor.output_filename_template = path.join( 56 | '/images', 'team', config['username'], self.post_slug, 57 | '{unique_key}_{cell_index}_{index}{extension}') 58 | exporter = MarkdownExporter(config=c, raw_template=IPYNB_TEMPLATE) 59 | post, images = exporter.from_notebook_node(notebook) 60 | for image_path, content in images['outputs'].items(): 61 | image_name = path.basename(image_path) 62 | self.save_image(image_name, content) 63 | new_filename = '{}.md'.format(self.post_slug) 64 | post_path = generate_post_path(new_filename) 65 | click.secho('Saving post content to {}'.format(post_path), fg='green') 66 | with open(post_path, 'w') as output: 67 | output.write(post) 68 | return post_path -------------------------------------------------------------------------------- /converters/rmd.py: -------------------------------------------------------------------------------- 1 | from os import path, makedirs 2 | from datetime import datetime 3 | 4 | import yaml 5 | import click 6 | import sys 7 | import os 8 | import shutil 9 | 10 | from commands.util import generate_image_path, generate_post_path, generate_slug 11 | from config import config 12 | 13 | YAML_WHITELIST = ['authors', 'author', 'title', 'tags', 'date', 'draft'] 14 | YAML_BOUNDARY = '---' 15 | 16 | 17 | class RmdConverter: 18 | """A converter for [name].rmd files. 19 | 20 | This converter works by assuming that another file in the same directory 21 | exists called [name]_blogdown.html. We take that HTML file, copy the 22 | front matter from the Rmd file into it, and move it to the correct location. 23 | 24 | Next, we copy over any images in the [name]_files/ directory into the 25 | correct location in Journal. We then update links to those images within 26 | the HTML file to point to the right location, making sure that the images 27 | will load correctly. 28 | 29 | (TODO) Missing some images in the test files? 30 | 31 | (TODO) Finally, we copy over the Rmd file itself into the static folder, 32 | creating a link between the two. 33 | """ 34 | 35 | def __init__(self, filepath): 36 | """Creates a new instance of the RmdConverter 37 | 38 | Arguments: 39 | filename {str} -- The absolute path to the Rmd file to convert. 40 | """ 41 | self.filepath = filepath 42 | self.source_folder = path.abspath(path.dirname(self.filepath)) 43 | # Filename serves as a predictable prefix which is the same across the 44 | # [prefix].Rmd file, the [prefix]_blogdown.html file, and the 45 | # [prefix]_files/ folder. 46 | self.filename, _ = path.splitext(path.basename(self.filepath)) 47 | self.rmd_file = path.join(self.source_folder, 48 | '{}.Rmd'.format(self.filename)) 49 | self.blogdown_file = path.join( 50 | self.source_folder, '{}_blogdown.html'.format(self.filename)) 51 | 52 | def copy_images(self, post_slug): 53 | """Copies the figures and images into Journal 54 | 55 | This is a pretty naive approach right now. It just looks for files in 56 | the top-level report_files/figure-html/ directory and copies those 57 | over to the static images directory. 58 | 59 | It's possible we'll need to adjust this later. 60 | 61 | Arguments: 62 | post_slug {str} -- The post slug used when creating the 63 | destination filename 64 | """ 65 | image_source_directory = path.join('{}_files'.format(self.filename), 66 | 'figure-html') 67 | for dirpath, _, images in os.walk( 68 | path.join(self.source_folder, image_source_directory)): 69 | for image in images: 70 | image_destination = generate_image_path(post_slug, image) 71 | image_path = path.abspath(path.join(dirpath, image)) 72 | makedirs(path.dirname(image_destination), exist_ok=True) 73 | shutil.copy(image_path, image_destination) 74 | 75 | def load_front_matter(self): 76 | """Loads the front matter from the Rmd file 77 | """ 78 | raw_yaml = '' 79 | with open(self.rmd_file, 'r') as rmd: 80 | for line in rmd.readlines(): 81 | # Check if this is the ending tag 82 | if line.strip() == YAML_BOUNDARY: 83 | if raw_yaml: 84 | break 85 | raw_yaml += line 86 | front_matter = yaml.load(raw_yaml) 87 | # Trim the YAML to only the keys Hugo is known to support 88 | front_matter = { 89 | k: v 90 | for (k, v) in front_matter.items() if k in YAML_WHITELIST 91 | } 92 | # Manually fix the conversion to an authors array if only the author 93 | # key is provided. 94 | if not front_matter.get('authors') and front_matter.get('author'): 95 | front_matter['authors'] = [front_matter['author']] 96 | del front_matter['author'] 97 | return front_matter 98 | 99 | def validate(self): 100 | """Validates that the correct files are available before attempting 101 | the converstion. 102 | """ 103 | for filename in [self.rmd_file, self.blogdown_file]: 104 | if not path.exists(path.join(self.source_folder, filename)): 105 | click.secho('Missing file: {}'.format(filename), fg='red') 106 | sys.exit(1) 107 | 108 | def generate_blogdown_html(self, img_dir): 109 | from bs4 import BeautifulSoup 110 | with open(self.blogdown_file, 'r') as html: 111 | soup = BeautifulSoup(html.read(), "html.parser") 112 | files_dir = '{}_files'.format(self.filename) 113 | # Update links to images to point to the new path 114 | for img in soup.find_all('img'): 115 | if not img['src'].startswith(files_dir): 116 | continue 117 | img['src'] = img['src'].replace( 118 | '{}/figure-html/'.format(files_dir), '') 119 | img['src'] = path.join(img_dir, img['src']) 120 | return str(soup) 121 | 122 | def convert(self): 123 | """Converts an Rmd file for Journal. 124 | """ 125 | self.validate() 126 | # Generate the slug from the title in the metadata 127 | front_matter = self.load_front_matter() 128 | front_matter['date'] = datetime.now().strftime('%Y-%m-%dT%H:%M:%S') 129 | if not front_matter.get('title'): 130 | click.secho( 131 | 'Invalid front matter in Rmd file: missing "title" field', 132 | fg='red') 133 | sys.exit(1) 134 | post_slug = generate_slug(front_matter['title']) 135 | post_filename = '{}.html'.format(post_slug) 136 | post_path = generate_post_path(post_filename) 137 | # Copy the image assets 138 | self.copy_images(post_slug) 139 | img_html_src_dir = path.join('/images', 'team', config['username'], 140 | post_slug) 141 | with open(post_path, 'w') as post: 142 | # Copy the metadata 143 | post.write('---\n{}---'.format( 144 | yaml.dump(front_matter, default_flow_style=False))) 145 | # Generate the HTML, adjusting the image paths to point to the right 146 | # location 147 | html = self.generate_blogdown_html(img_html_src_dir) 148 | post.write(html) 149 | return post_path 150 | -------------------------------------------------------------------------------- /journal: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from commands.cli import cli 4 | 5 | if __name__ == '__main__': 6 | cli() 7 | -------------------------------------------------------------------------------- /journal.toml: -------------------------------------------------------------------------------- 1 | # Default settings for the KR client 2 | 3 | # This is the username used in template values. It defaults to your 4 | # actual username, so you probably don't need to change this. 5 | # E.g. "jwright" 6 | username='' 7 | 8 | # This is the upstream repo which holds the posts 9 | upstream_repo='' 10 | 11 | # This is the path on the filesystem containing the cloned upstream_repo 12 | journal_path='' 13 | 14 | # If you'd like a random fortune after you'v pushed a new post 15 | # and shared your knowledge with the world. High-5 you 16 | fortune=true 17 | 18 | # If you want to use custom templates, you can change these here. You'll 19 | # want to include the absolute path to the template 20 | [templates] 21 | md='knowledge_template.md' 22 | html='knowledge_template.html' 23 | ipynb='knowledge_template.ipynb' 24 | Rmd='knowledge_template.Rmd' 25 | daily_log='daily_log.md' 26 | 27 | # When a new post is created, you have the option to open it in an editor 28 | [editor] 29 | command='code' 30 | args=['-a', '{}'] 31 | enabled=true -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | alembic==0.9.9 2 | attrs==19.1.0 3 | beautifulsoup4==4.7.1 4 | bleach==3.3.0 5 | blinker==1.4 6 | click==6.7 7 | colorama==0.3.9 8 | decorator==4.3.2 9 | defusedxml==0.5.0 10 | entrypoints==0.3 11 | enum34==1.1.6 12 | Flask==2.3.2 13 | Flask-Login==0.4.1 14 | Flask-Mail==0.9.1 15 | Flask-Migrate==2.1.1 16 | Flask-Principal==0.4.0 17 | Flask-SQLAlchemy==2.3.2 18 | future==0.18.3 19 | gitdb2==2.0.3 20 | GitPython==3.1.41 21 | gunicorn==22.0.0 22 | inflection==0.3.1 23 | ipython-genutils==0.2.0 24 | itsdangerous==0.24 25 | Jinja2>=2.10.1 26 | jsonschema==3.0.1 27 | jupyter-core==4.11.2 28 | Mako==1.2.2 29 | Markdown==2.6.11 30 | MarkupSafe==1.0 31 | mistune==2.0.3 32 | nbconvert==6.5.1 33 | nbformat==4.4.0 34 | pandas==1.4.4 35 | pandocfilters==1.4.2 36 | Pygments==2.15.0 37 | pyrsistent==0.14.11 38 | python-dateutil==2.7.2 39 | python-editor==1.0.3 40 | PyYAML==5.4 41 | six==1.11.0 42 | smmap2==2.0.3 43 | soupsieve==1.9 44 | SQLAlchemy>=1.3.0 45 | tabulate==0.8.2 46 | testpath==0.4.2 47 | toml==0.9.4 48 | traitlets==4.3.2 49 | webencodings==0.5.1 50 | Werkzeug==3.0.3 51 | yapf==0.26.0 52 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | setup( 4 | name='journal', 5 | version='0.1', 6 | packages=find_packages(), 7 | install_requires=[ 8 | 'alembic', 'blinker', 'click', 'colorama', 'enum34', 'Flask', 9 | 'Flask-Login', 'Flask-Mail', 'Flask-Migrate', 'Flask-Principal', 10 | 'Flask-SQLAlchemy', 'future', 'gitdb2', 'GitPython', 'gunicorn', 11 | 'inflection', 'itsdangerous', 'Jinja2', 'knowledge_repo', 'Mako', 12 | 'Markdown', 'MarkupSafe', 'Pygments', 'python-dateutil', 13 | 'python-editor', 'PyYAML', 'six', 'smmap2', 'SQLAlchemy', 'tabulate', 14 | 'toml', 'Werkzeug', 'wheel' 15 | ], 16 | entry_points=''' 17 | [console_scripts] 18 | journal=journal:cli 19 | ''', 20 | package_data={'journal': ['templates/*', 'journal.toml']}) 21 | -------------------------------------------------------------------------------- /templates/author.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: "{{username}}" 3 | name: "{{name}}" 4 | --- -------------------------------------------------------------------------------- /templates/daily_log.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: {{username}}'s Daily Log - {{ now() | strftime('%m/%d')}} 3 | authors: 4 | - {{username}} 5 | tags: 6 | - daily 7 | date: {{ now() | strftime('%Y-%m-%dT%H:%M:%S') }} 8 | --- 9 | 10 | 11 | ### What I Want to Get Done Today: 12 | 13 | 14 | 15 | 16 | ### Raw Notes: 17 | -------------------------------------------------------------------------------- /templates/dataset_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: {{name | title}} 3 | authors: 4 | - {{username}} 5 | tags: 6 | - knowledge 7 | date: {{ now() | strftime('%Y-%m-%dT%H:%M:%S') }} 8 | 9 | location: {{ location }} 10 | format: {{ format }} 11 | deprecated: false 12 | md5_hash: {{ md5_hash }} 13 | 14 | sources: 15 | - database: Redshift 16 | - dataset: another_dataset 17 | 18 | schema: 19 | {{schema}} 20 | --- 21 | A short description of the dataset. 22 | 23 | 24 | 25 | # Content 26 | Describe the content of this dataset. 27 | 28 | # Procedure 29 | Describe how this dataset was generated. 30 | 31 | -------------------------------------------------------------------------------- /templates/knowledge_template.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: {{title | title}} 3 | authors: 4 | - {{username}} 5 | tags: 6 | - knowledge 7 | date: {{ now() | strftime('%Y-%m-%dT%H:%M:%S') }} 8 | --- 9 | 10 | **Contents** 11 | 12 | [TOC] 13 | 14 | ### Motivation 15 | 16 | _NOTE: optimize in this section for **context setting**, as specifically as you can. For instance, this post is generally a set of standards for work in the repo. The specific motivation is to have least friction to current workflow while being able to painlessly aggregate it later._ 17 | 18 | The knowledge repo was created to consolidate research work that is currently scattered in emails, blogposts, and presentations, so that people didn't redo their work. 19 | 20 | ### This Section Says Exactly This Takeaway 21 | 22 | Here is some example code. 23 | 24 | ```{r} 25 | plot(density(runif(100)), lwd=2, main="100 uniforms") 26 | abline(h=0, v=0) 27 | ``` 28 | 29 | 30 | _NOTE: in graphs, optimize for being able to **stand alone**. As we aggregate and put things in presentations, we want to not have to recreate and add code to each plot to make it understandable without the entire post around it. When we compare this plot to other people's from other posts, will it be understandable without several paragraphs?_ 31 | 32 | 33 | ### Common Mistakes 34 | 35 | There are some requirements around how an R Markdown is developed to make the markdown render properly on the site. Here is a list of the ones that often lead to questions: 36 | 37 | - There should be one plot display call in each R block. The add_knowledge script currently gets confused if there are multiple plots in a given block: 38 | 39 | ```{r } 40 | ### My Header (treated as R comment, as it is in a code block) 41 | library(ggplot2) 42 | test_data <- data.frame(y1 = rnorm(100), y2 = runif(100), x = 1:100) 43 | ggplot(test_data, aes(y = y1, x = x)) + geom_line() 44 | ggplot(test_data, aes(y = y2, x = x)) + geom_line() 45 | ``` 46 | 47 | - Do not put markdown headers in R blocks. The knitr code will interpret the header #'s as R comments. This means that they will either be rendered properly as R comments within the block, or left out entirely if echo=FALSE 48 | 49 | ### Appendix 50 | 51 | Put all the stuff here that is not necessary for supporting the points above. Good place for documentation of paths not pursued without distraction. 52 | 53 | -------------------------------------------------------------------------------- /templates/knowledge_template.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "raw", 5 | "metadata": {}, 6 | "source": [ 7 | "---\n", 8 | "title: {{title | title}}\n", 9 | "authors:\n", 10 | "- {{username}}\n", 11 | "tags:\n", 12 | "- knowledge\n", 13 | "date: {{ now() | strftime('%Y-%m-%dT%H:%M:%S') }}\n", 14 | "---" 15 | ] 16 | }, 17 | { 18 | "cell_type": "raw", 19 | "metadata": {}, 20 | "source": [ 21 | "This is the notebook summary. It's recommmended to make this a couple of sentences (or paragraphs!) explaining a little bit about the notebook. Make sure to keep the tag below:\n", 22 | "" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "### Motivation" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "*NOTE: optimize in this section for **context setting**, as specifically as you can. For instance, this post is generally a set of standards for work in the repo. The specific motivation is to have least friction to current workflow while being able to painlessly aggregate it later.*\n", 37 | "\n", 38 | "The knowledge repo was created to consolidate research work that is currently scattered in emails, blogposts, and presentations, so that people didn't redo their work." 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "### This Section Says Exactly This Takeaway" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 17, 51 | "metadata": { 52 | "collapsed": false 53 | }, 54 | "outputs": [ 55 | { 56 | "data": { 57 | "text/plain": [ 58 | "" 59 | ] 60 | }, 61 | "execution_count": 17, 62 | "metadata": {}, 63 | "output_type": "execute_result" 64 | }, 65 | { 66 | "data": { 67 | "image/png": "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\nQmCC\n", 68 | "text/plain": [ 69 | "" 70 | ] 71 | }, 72 | "metadata": {}, 73 | "output_type": "display_data" 74 | } 75 | ], 76 | "source": [ 77 | "import pandas as pd\n", 78 | "import numpy as np\n", 79 | "import matplotlib\n", 80 | "from matplotlib import pyplot as plt\n", 81 | "\n", 82 | "\n", 83 | "%matplotlib inline\n", 84 | "\n", 85 | "x = np.linspace(0, 3*np.pi, 500)\n", 86 | "plot_df = pd.DataFrame()\n", 87 | "plot_df[\"x\"] = x\n", 88 | "plot_df[\"y\"] = np.sin(x**2)\n", 89 | "\n", 90 | "\n", 91 | "plot_df.plot('x', 'y', \n", 92 | " color='lightblue',\n", 93 | " figsize=(15,10))\n", 94 | "plt.title(\"Put enough labeling in your graph to be understood on its own\", size=25)\n", 95 | "plt.xlabel('you definitely need axis labels', size=20)\n", 96 | "plt.ylabel('both of them', size=20)" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "*NOTE: in graphs, optimize for being able to **stand alone**. When aggregating and putting things in presentations, you won't have to recreate and add code to each plot to make it understandable without the entire post around it. Will it be understandable without several paragraphs?*" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "### Putting Big Bold Headers with Clear Takeaways Will Help Us Aggregate Later" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "### Appendix" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "Put all the stuff here that is not necessary for supporting the points above. Good place for documentation without distraction." 125 | ] 126 | } 127 | ], 128 | "metadata": { 129 | "hide_input": false, 130 | "kernelspec": { 131 | "display_name": "Python 2", 132 | "language": "python", 133 | "name": "python2" 134 | }, 135 | "language_info": { 136 | "codemirror_mode": { 137 | "name": "ipython", 138 | "version": 2 139 | }, 140 | "file_extension": ".py", 141 | "mimetype": "text/x-python", 142 | "name": "python", 143 | "nbconvert_exporter": "python", 144 | "pygments_lexer": "ipython2", 145 | "version": "2.7.10" 146 | } 147 | }, 148 | "nbformat": 4, 149 | "nbformat_minor": 0 150 | } 151 | -------------------------------------------------------------------------------- /templates/knowledge_template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: {{title | title}} 3 | authors: 4 | - {{username}} 5 | tags: 6 | - knowledge 7 | date: {{ now() | strftime('%Y-%m-%dT%H:%M:%S') }} 8 | --- 9 | 10 | ### Example Header: 11 | 12 | Have fun writing! 13 | 14 | 15 | --------------------------------------------------------------------------------