[SOLVED] EECS485 P1: Templated Static Site Generator

30 $

SKU: [Solved] EECS485 P1: Templated Static Site Generator Category: Tag:

index

Introduction

An Instagram clone implemented with a templated static site generator. This is the first of an EECS 485 three project sequence: a static site generator from templates, server-side dynamic pages, and client-side dynamic pages.

The learning goals of this project include HTML, CSS, templates, Python programming, and basic shell scripting. It is also a “readiness test” that will give you an idea of what EECS 485 will be like.

Write a Python program that takes as input HTML templates, JSON data and misc. static files (like images and CSS) and generates as output a web site of static content. Then, use your new tool to build a non-interactive website. Jekyll and Pelican are two examples of open source static site generators.

Here’s a preview of what your finished project will look like. insta485generator is the name of the Python program you will write. insta485 is an input directory containing HTML templates, JSON data and misc. static files (like images and CSS). insta485/html is an output directory containing generated static HTML files.

$ insta485generator insta485

$ cd insta485/html/

$ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …

Then you will navigate to http://localhost:8000 and see the non-interactive website that you created.

If you’re new to HTML, CSS and Python, here are some helpful resources:

W3 Schools Beginner’s Guide to HTML

W3 Schools CSS

Python 3 Tutorial

This spec will walk you through these parts:

  1. Setting up your computer
  2. Hand coded HTML
  3. Creating Python starter files
  4. insta485generator specification
  5. Static Templated Insta485 specification
  6. Submitting and grading
  7. FAQ

Setting up your computer

We’ll walk you through setting up your operating system, Python virtual environment and version control.

Operating System

Set up your computer for local development using the Operating System Tutorial.

You should now have a folder for your project. Your folder location might be different.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

Version Control

Set up version control using the Version control tutorial.

After you’re done, you should have a local repository with a “clean” status and your local repository should be connected to a remote GitLab repository.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ git status

On branch master

Your branch is up-to-date with ‘origin/master’.

nothing to commit, working tree clean

$ git remote -v origin https://gitlab.eecs.umich.edu/awdeorio/p1-insta485-static.git (fetch) origin https://gitlab.eecs.umich.edu/awdeorio/p1-insta485-static.git (push) You should have a .gitignore file (instructions).

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ head .gitignore

This is a sample .gitignore file that’s useful for EECS 485 projects.

Python virtual environment

Create a Python virtual environment for project 1 using the Python Virtual Environment Tutorial.

You should now have Python tools installed locally.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ ls env

$ source env/bin/activate

$ which python

/Users/awdeorio/src/eecs485/p1-insta485-static/env/bin/python

$ which pip

/Users/awdeorio/src/eecs485/p1-insta485-static/env/bin/pip

Python debugger

Learn how to use the Python debugger, pdb using the Python Debugging Tutorial.

Browser tutorial

Learn about the developer tools built into your browser with the Browser Tutorial.

Starter files

Download and unpack the starter files.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ wget https://eecs485staff.github.io/p1-insta485-static/starter_files.tar.gz $ tar -xvzf starter_files.tar.gz

Move the starter files to your project directory and remove the original starter_files/ directory.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ mv starter_files/* .

$ rm -rf starter_files starter_files.tar.gz You should see these files.

$ tree

.

├── VERSION

├── hello

│ ├── config.json

│ └── templates

│ └── index.html

├── hello_css

│ ├── config.json

│ ├── static

│ │ └── css

│ │ └── style.css

│ └── templates

│ └── index.html

├── insta485

│ ├── config.json │ └── static

│ └── uploads

│ └── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

├── setup.py └── tests

└── util.py

VERSION Version of the starter files
hello/ Sample input for insta485generator
hello_css/ Sample input for insta485generator
insta485/ Static templated Insta485 goes here
insta485/config.json Data for future Insta485 templates
insta485/static/uploads/ Sample images for Insta485
setup.py insta485generator python package configuration
tests/ Public unit tests

Before making any changes to the clean starter files, it’s a good idea to make a commit to your Git repository.

Hand coded HTML

Once you have your computer set up, you’ll write two HTML files by hand: html/index.html and html/u/awdeorio/index.html . This will give you practice with HTML and CSS, which you’ll later

generate using Python code.

For those developing locally, navigate to your project’s root directory. Also, remember to activate your Python virtual environment every time you begin a coding sessions (AKA start a new shell).

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ source env/bin/activate

Create a directory layout using mkdir . The image logo.png is optional; you can style your website however you like. Here are some commands to get you started.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ mkdir html/

$ mkdir html/css/

$ mkdir html/images/

$ mkdir html/u/

$ mkdir html/u/awdeorio/

$ mkdir html/uploads/

$ touch html/css/style.css # touch creates empty files

$ touch html/index.html

$ touch html/u/awdeorio/index.html

$ cp insta485/static/uploads/* html/uploads/

Add the initial file structure to the git repo.

Here are the files you should have when you are done.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ tree html/ html/

├── css

│ └── style.css

├── images

├── index.html

├── u

│ └── awdeorio

│ └── index.html

└── uploads

├── 122a7d27ca1d7420a1072f695d9290fad4501a41.jpg

├── 2ec7cf8ae158b3b1f40065abfb33e81143707842.jpg

├── 505083b8b56c97429a728b68f31b0b2a089e5113.jpg

├── 5ecde7677b83304132cb2871516ea50032ff7a4f.jpg

├── 73ab33bd357c3fd42292487b825880958c595655.jpg

├── 9887e06812ef434d291e4936417d125cd594b38a.jpg

├── ad7790405c539894d25ab8dcf0b79eed3341e109.jpg

└── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

Start your two HTML files ( html/index.html and html/u/awdeorio/index.html ) like this. Edit HTML files with a text editor.

<!DOCTYPE html>

<html lang=”en”>

Hello world!

</html>

Run a test server and browse to http://localhost:8000/ where you will see “hello world”. Again, recall that this is a static file server, which serves copies of files from the server’s file system. In this example, the file is a plain text file containing HTML.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ cd html/

$ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …

Keep up your good git habits by committing files when you’ve completed each small task.

Continue working on html/index.html . When you’re done, the page should have the following content, although yours might look different. For example, a logo is not required. To be clear: there are no autograder tests for your CSS layout. You can make it look however you want. What you must include is the text, images, and links shown in the screenshot below. For details on what links to include, see the All pages and Index sections. You may have to reference your

config.json file to figure out what URLs some links may lead to (it’s okay if some lead to

nowhere for this hand-coded portion). Don’t forget to git add and git commit when you’re done.

Next, code html/u/awdeorio/index.html . When you’re done, the page should have the following content, although yours might have different styling. Again, we’re not requiring any particular

CSS styling. See the /u/<user_url_slug>/ section for more details about the links to include. Don’t forget to git add and git commit when you’re done.

All HTML should be W3C HTML5 compliant. Here’s how to check yours at the command line.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static $ html5validator –root html/

Test

Run the public autograder testcases on your hand coded HTML.

$ pytest -v tests/test_handcoded_html.py tests/test_handcoded_index.py tests/test_handcode

========================== 12 passed in 3.76 seconds ===========================

Creating the Python starter files

This section will help you get your Python files set up.

Our program will be called insta485generator . The following steps will help you to create a Python package for it. (More info in the Python documentation on modules, especially the section on packages.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ mkdir insta485generator/

$ cd insta485generator/

All Packages must have an __init__.py file. Our starter package is simple, so it won’t do anything. Create the file insta485generator/__init__.py (be sure to include the 2 underscores before and after init) and add a comment like this to it:

“””A static site generator.”””

Now within the insta485generator directory, create a new file called __main__.py . Our main function will go in insta485generator/__main__.py . We have given you the skeleton code below.

“””Build static HTML site from directory of HTML templates and plain files.”””

def main():

“””Top level command line interface.””” print(“Hello world!”)

if __name__ == “__main__”: main()

Now, try running it:

$ python3 insta485generator/__main__.py Hello world!

Next, we’ll install our package into our development environment. Double-check that the development environment is still active. If it’s not, then activate it with source env/bin/activate .

$ echo $VIRTUAL_ENV

/Users/awdeorio/src/p1-insta485-static/solution/awdeorio/env

The setup.py file provided with the starter files describes how your package should be installed. We’ve included some libraries that will be helpful later. You are not allowed to add any additional dependencies other than the ones that we specify. More info about setup scripts and Python entry points.

At this point, we’ve got these files (excluding env , __pycache__ and html ):

$ tree insta485generator –matchdirs -I __pycache__ insta485generator ├── __init__.py

└── __main__.py

We can now use pip to install insta485generator package using setup.py . We’ll install in editable mode so that we won’t have to reinstall when we make changes to our Python source code. Again, be sure that your virtual envirnment is active.

$ echo $VIRTUAL_ENV

/Users/awdeorio/src/p1-insta485-static/solution/awdeorio/env

$ pip install -e .

Running setup.py develop for insta485generator Successfully installed … insta485generator …

Because of the entry point in setup.py ( ‘insta485generator =

insta485generator.__main__:main’ ), there’s now an executable that calls our insta485generator package’s main() function!

$ insta485generator Hello world!

How did it do that? When you activate your virtual environment with source env/bin/activate , your shell’s PATH environment variable is temporarily modified to include programs installed to ./env/bin/ . Prove it to yourself:

$ echo $PATH

/Users/awdeorio/src/p1-insta485-static/solution/awdeorio/env/bin:/usr/local/bin:/usr/local $ which insta485generator

/Users/awdeorio/src/p1-insta485-static/solution/awdeorio/env/bin/insta485generator

When you get this working, it may be a good point to commit to git

### `pytest` utility

Learn how to use the Python `pytest` unit test utility using the [`pytest` Tutorial](setup Now you can continue developing `insta485generator` by adding code to `insta485generator/_

# `insta485generator` specification

We will now begin implementing the functionality for our insta485generator. We will modify

  • Handle command line arguments using the [click library](https://click.palletsprojects.c
  • Render the provided templates and write them to output files and create all the necessa
  • Copy over a static directory if it is provided
  • Handle errors

The inputs to `insta485generator` are templated HTML files with data in JSON format. The

We have provided two examples to help you get your `insta485generator` working. We recomme

The command line utility supports the following options. Hint: use the [click library](ht

“`console

$ insta485generator

Usage: insta485generator [OPTIONS] INPUT_DIR

Try “insta485generator –help” for help.

Error: Missing argument “INPUT_DIR”.

$ insta485generator –help

Usage: insta485generator [OPTIONS] INPUT_DIR

Templated static website generator.

Options:

-v, –verbose Print more output.

–help Show this message and exit.

The configuration for one website is an input directory containing a data file ( config.json ), a templates/ directory and an optional static/ directory. Templates are rendered and written to

output files, and static files are copied without modification.

We will now walk through the hello example. The hello/ example is provided with the starter files.

$ tree hello/

.

├── config.json

└── templates

└── index.html

A configuration file (e.g., hello/config.json ) is a JSON string with a list of dictionaries. Each dictionary contains a url , the name of a template file and a context dictionary. The template file is rendered using the context dictionary. Hint: Python has a built in JSON library.

[

{

“url”: “/”,

“template”: “index.html”,

“context”: {

“words”: [

“hello”,

“world”

]

}

}

]

Templates use jinja2 syntax, for example hello/templates/index.html below. Hint: check out the Jinja2 library.

<!DOCTYPE html>

<html lang=”en”>

<head><title>Hello world</title></head>

<body>

{% for word in words %}

{{word}}

{% endfor %}

</body>

</html>

Running insta485generator INPUT_DIR renders templates, copying the results to an output directory. The output directory is ${INPUT_DIR}/html , where ${INPUT_DIR} is the command line argument INPUT_DIR .

After you finish insta485generator , it will render templates and create directories like this example.

$ tree hello hello

├── config.json

└── templates

└── index.html

$ insta485generator hello

$ tree hello hello

├── config.json

├── html

│ └── index.html └── templates

└── index.html

Output files rendered from templates no longer contain any template code, for example hello/html/index.html . The algorithm for an output filename is os.path.join(input_dir,

“html”, url.lstrip(“/”), “index.html”) where input_dir is the command line argument INPUT_DIR and url is the URL read from the config.json file.

<!DOCTYPE html>

<html lang=”en”>

<head><title>Hello world</title></head>

<body> hello world

</body>

Finally, serve up the newly created site and browse to http://localhost:8000/.

$ cd hello/html/

$ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …

We’ve published the test_hello autograder testcase. After copying the test directory from the starter files to your working directory, you can run it yourself like this:

$ pytest -v tests/test_hello.py

============================= test session starts ==============================

::TestHello::test_files PASSED [ 50%] ::TestHello::test_index PASSED [100%]

=========================== 2 passed in 0.59 seconds ===========================

More examples

Here’s an example of the –verbose option. The position of the option doesn’t matter.

$ rm -rf hello/html

$ insta485generator hello –verbose

Rendered index.html -> hello/html/index.html

Here’s a slightly more complicated example with a static CSS style file. The hello_css/ example is provided with the starter files.

$ tree hello_css hello_css ├── config.json

├── static

│ └── css

│ └── style.css

└── templates

└── index.html

This is the config file hello_css/config.json :

[

{

“url”: “/”,

“template”: “index.html”,

“context”: {

“words”: [

“hello”,

“world”

]

}

}

]

Here’s hello_css/templates/index.html :

<!DOCTYPE html>

<html lang=”en”>

<head>

<title>Hello world</title>

<link rel=”stylesheet” type=”text/css” href=”/css/style.css”>

</head>

<body>

{% for word in words %}

<div class=”important”>{{word}}</div>

{% endfor %}

</body>

</html>

And hello_css/static/css/style.css :

body {

background: pink;

}

div.important { font-weight: bold; font-size: 1000%;

}

Build and list output files

$ insta485generator -v hello_css

Copied hello_css/static/ -> hello_css/html/

Rendered index.html -> hello_css/html/index.html

$ tree hello_css/html hello_css/html ├── css

│ └── style.css └── index.html

We’ve published the test_hello_css autograder testcase. You can run it yourself like this:

$ pytest -v tests/test_hello_css.py

============================= test session starts ==============================

::TestHelloCSS::test_css_dir PASSED [ 33%]

::TestHelloCSS::test_files PASSED [ 66%] ::TestHelloCSS::test_index PASSED [100%]

=========================== 3 passed in 0.59 seconds ===========================

A few notes about the jinja2 library

We’d like to save you a bit of frustration getting the jinja2 library working the same way our instruction solution works. First, in order to make template inheritance work correctly, you’ll need to use the FileSystemLoader . Second, we’re going to enable auto escaping for security reasons.

Here’s how we configured out template environment in our instructor solution:

template_env = jinja2.Environment(

loader=jinja2.FileSystemLoader(template_dir), autoescape=jinja2.select_autoescape([‘html’, ‘xml’]), )

Python code style

Verify that your Python code conforms the PEP 8 Style Guide for Python. Check for common Python errors and additional style guidelines using Pylint. Confirm that internal documentation (comments) conforms to the PEP 257 Docstring Conventions.

$ pip install pycodestyle pydocstyle pylint

$ pycodestyle setup.py insta485generator

$ pylint –disable=no-value-for-parameter setup.py insta485generator

No config file found, using default configuration

——————————————————————– Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)

$ pydocstyle setup.py insta485generator

HINT test your style frequently. It’s hard to fix the style of a large code base with many errors. Later, we’ll automate these tests with a script ( insta485test ). Remember when you were first learning to code in C/C++? Did you ever see a classmate code their entire project, and then say “OK, now all I have to do is compile it!”. Bad idea! Just like C/C++ compilation, check your code in small increments.

Test

Run the public autograder testcases on your insta485generator .

$ pytest tests/test_hello.py tests/test_hello_css.py

=========================== 5 passed in 1.14 seconds ===========================

Static Templated Insta485 specification

In this part of the project, you will write HTML template files that you can render using insta485generator to create a non-interactive Instagram clone. First, this section will help you

create skeleton files. Then, in the URLs section, we’ll describe each page in detail and provide a screen shot.

First, set up the directory structure using mkdir and the provided starter files. Use your handcoded HTML files earlier in the project as a starting point. Put the HTML files in

insta485/templates/index.html and insta485/templates/user.html . When you’re done, you

should have a new directory called insta485 that looks like this:

$ tree insta485 insta485

├── config.json

├── static

│ ├── css

│ │ └── style.css

│ ├── images

│ │ └── logo.png

│ └── uploads

│ ├── 122a7d27ca1d7420a1072f695d9290fad4501a41.jpg

│ ├── 2ec7cf8ae158b3b1f40065abfb33e81143707842.jpg

│ ├── 505083b8b56c97429a728b68f31b0b2a089e5113.jpg

│ ├── 5ecde7677b83304132cb2871516ea50032ff7a4f.jpg

│ ├── 73ab33bd357c3fd42292487b825880958c595655.jpg

│ ├── 9887e06812ef434d291e4936417d125cd594b38a.jpg

│ ├── ad7790405c539894d25ab8dcf0b79eed3341e109.jpg │ └── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

└── templates

├── index.html

└── user.html

A few things to note. First, images/logo.png is optional. You are welcome to create any logo you want, or to omit it and use plain text. Second, remember that everything inside insta485/static/ will be copied to insta485/html/ by insta485generator . Also note that the config.json should come from the starter code, you do not have to write this by hand.

Use insta485generator to render the templates and copy the static files. Yea, yea, our HTML files don’t have any Jinja2 syntax in them, but they’re still valid template files!

$ rm -rf ‘insta485/html’

$ insta485generator insta485

Error_Jinja: jinja2 template following.html

TemplateNotFound: following.html

We’re getting an error because the provided insta485/config.json contains configurations for URLs that we haven’t written templates for. Let’s create a temporary configuration that’s shorter. First back up the old one.

$ cp -v insta485/config.json insta485/config.json.bak

‘insta485/config.json’ -> ‘insta485/config.json.bak’

Then, edit insta485/config.json so that it only contains configurations for URLs that use the index.html and user.html templates. Be careful, JSON doesn’t allow trailing commas!

[

{

“url”: “/”,

“template”: “index.html”,

“context”: {

“logname”: “awdeorio”, “posts”: [

]

} }, …

{

“url”: “/u/michjc/”,

“template”: “user.html”, “context”: {

}

}

]

Now, try running insta485generator again. Start a development server and you’ll see the rendered templates, which at this point are just copies of your hand coded HTML files.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ rm -rf insta485/html

$ insta485generator insta485 -v

Copied insta485/static/ -> insta485/html/

Rendered index.html -> insta485/html/index.html

Rendered user.html -> insta485/html/u/awdeorio/index.html

Rendered user.html -> insta485/html/u/jflinn/index.html Rendered user.html -> insta485/html/u/jag/index.html

Rendered user.html -> insta485/html/u/michjc/index.html

$ cd insta485/html/

$ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …

$ cd ../../

Utility scripts

During development, we’re going to be regenerating this website a lot. Web developers often use short shell scripts to make their lives easier. First, complete the Shell Scripting Tutorial.

Write a script to clean up the automatically generated insta485/html/ directory, build the static site using insta485generator , and start a development server on port 8000. We’ll give you the solution here for bin/insta485run . Create a folder called bin and copy the following code into a file called insta485run (note no file extension).

#!/bin/bash

# # insta485run

# # Clean, build and start server

#

# Andrew DeOrio <[email protected]>

# Stop on errors, print commands # See https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ set -Eeuo pipefail

set -x # Clean

rm -rf insta485/html

# Build

insta485generator insta485

# Serve cd insta485/html python3 -m http.server 8000

Now, make the script executable so you can use it like a command.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ chmod +x bin/insta485run

$ ./bin/insta485run

+ rm -rf insta485/html/css insta485/html/index.html insta485/html/u

+ insta485generator insta485

+ cd insta485/html

+ python3 -m http.server 8000

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) …

Check for shell script pitfalls.

insta485test script

Write another script called bin/insta485test that does the following things in this order:

  1. Stops on errors and prints commands
  2. Runs all unit tests using pytest tests/
  3. Runs pycodestyle insta485generator
  4. Runs pydocstyle insta485generator
  5. Runs pylint –disable=no-value-for-parameter setup.py insta485generator
  6. Cleans up a previous insta485/html directory
  7. Builds a new insta485/html directory using insta485generator
  8. Validates hand-coded HTML in html/ using html5validator ( html5validator –ignore

JAVA_TOOL_OPTIONS –root html )

  1. Validates generated HTML in insta485/html/ using html5validator ( html5validator -ignore JAVA_TOOL_OPTIONS –root insta485/html )

Progress so far

Here’s a complete list of the files in our project up to this point. Note that it excludes env and

__pycache__ . This will differ from your final tree because it is missing the templates we will create in the next step.

$ pwd

/Users/awdeorio/src/eecs485/p1-insta485-static

$ tree –matchdirs -I ‘env|__pycache__|*.egg-info’

.

├── bin

│ ├── insta485run

│ └── insta485test

├── html

│ ├── css

│ │ └── style.css

│ ├── images

│ │ └── logo.png

│ ├── index.html

│ ├── u

│ │ └── awdeorio

│ │ └── index.html

│ └── uploads

│ ├── 122a7d27ca1d7420a1072f695d9290fad4501a41.jpg

│ ├── 2ec7cf8ae158b3b1f40065abfb33e81143707842.jpg

│ ├── 505083b8b56c97429a728b68f31b0b2a089e5113.jpg

│ ├── 5ecde7677b83304132cb2871516ea50032ff7a4f.jpg

│ ├── 73ab33bd357c3fd42292487b825880958c595655.jpg

│ ├── 9887e06812ef434d291e4936417d125cd594b38a.jpg

│ ├── ad7790405c539894d25ab8dcf0b79eed3341e109.jpg

│ └── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

├── insta485

│ ├── config.json

│ ├── config.json.bak

│ ├── html

│ │ ├── css

│ │ │ └── style.css

│ │ ├── images

│ │ │ └── logo.png

│ │ ├── index.html

│ │ ├── u

│ │ │ ├── awdeorio

│ │ │ │ └── index.html │ │ │ ├── jag

│ │ │ │ └── index.html │ │ │ ├── jflinn

│ │ │ │ └── index.html │ │ │ └── michjc

│ │ │ └── index.html

│ │ └── uploads

│ │ ├── 122a7d27ca1d7420a1072f695d9290fad4501a41.jpg

│ │ ├── 2ec7cf8ae158b3b1f40065abfb33e81143707842.jpg

│ │ ├── 505083b8b56c97429a728b68f31b0b2a089e5113.jpg

│ │ ├── 5ecde7677b83304132cb2871516ea50032ff7a4f.jpg

│ │ ├── 73ab33bd357c3fd42292487b825880958c595655.jpg

│ │ ├── 9887e06812ef434d291e4936417d125cd594b38a.jpg

│ │ ├── ad7790405c539894d25ab8dcf0b79eed3341e109.jpg

│ │ └── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

│ ├── static

│ │ ├── css

│ │ │ └── style.css

│ │ ├── images

│ │ │ └── logo.png

│ │ └── uploads

│ │ ├── 122a7d27ca1d7420a1072f695d9290fad4501a41.jpg

│ │ ├── 2ec7cf8ae158b3b1f40065abfb33e81143707842.jpg

│ │ ├── 505083b8b56c97429a728b68f31b0b2a089e5113.jpg

│ │ ├── 5ecde7677b83304132cb2871516ea50032ff7a4f.jpg

│ │ ├── 73ab33bd357c3fd42292487b825880958c595655.jpg

│ │ ├── 9887e06812ef434d291e4936417d125cd594b38a.jpg

│ │ ├── ad7790405c539894d25ab8dcf0b79eed3341e109.jpg │ │ └── e1a7c5c32973862ee15173b0259e3efdb6a391af.jpg

│ └── templates

│ ├── index.html

│ └── user.html

├── insta485generator

│ ├── __init__.py

│ └── __main__.py

├── setup.py

└── tests

├── test_hello.py

└── test_hello_css.py

URLs

Now, write templates for each type of URL. You are welcome to add extra files, for example, if you’d like to use template inheritance. Style the pages any way you like.

List of URLs and templates:

/ -> index.html

/u/<user_url_slug>/ -> user.html

/u/<user_url_slug>/followers/ -> followers.html /u/<user_url_slug>/following/ -> following.html

/p/<postid_slug>/ -> post.html

/explore/ -> explore.html

All pages

Include a link to / in the upper left hand corner.

Include a link to /explore/ and /u/<logged_in_user>/ in the upper right hand corner.

Include <title>insta485</title> . Nothing else should be in the <title> section

Index /

screenshot

All posts from other users that the logged in user is following (including their own). The logged in user is specified by logname in config.json . The posts are in the order that they appear in the JSON config file. For each post:

Link to the post detail page /p/<postid_slug>/ by clicking on the timestamp.

Link to the post owner’s page /u/<user_url_slug>/ by clicking on their username or profile picture.

Time since the post was created

Number of likes, using correct English

Comments, with owner’s username, in the order that they appear in the JSON config file.

Link to the comment owner’s page /u/<user_url_slug>/ by clicking on their username. Actual image corresponding to the post.

Here’s an example of correct English for number of likes “0 likes”, “1 like”, “2 likes”. The same plural rules apply to number of posts, likes, and followers. Following is always the same “0 following”, “1 following”, “2 following”.

/u/<user_url_slug>/

screenshot 1, screenshot 2, screenshot 3, screenshot 4

Be sure to include

username ( user_url_slug )

Relationship

“following” if the logged in user is following user_url_slug

“not following” if the logged in user is not following user_url_slug

Blank if logged in user == user_url_slug

Number of posts, with correct English

Number of followers, with correct English

Link to /u/<user_url_slug/followers/ Number following

Link to /u/<user_url_slug/following/

Name

A small image for each post

Clicking on the image links to /p/<postid_url_slug>/

/u/<user_url_slug>/followers/ screenshot

List the users that are following user_url_slug . For each, include:

Icon

Username, with link to /u/<username>/

Relationship to logged in user

“following” if logged in user is following username

“not following” if logged in user is not following username Blank if logged in user == username

/u/<user_url_slug>/following/ screenshot

List the users that user_url_slug is following. For each, include:

Icon

Username, with link to /u/<username>/

Relationship to logged in user

“following” if logged in user is following username

“not following” if logged in user is not following username Blank if logged in user == username

/explore/ screenshot

This page lists all users that the logged in user is not following and includes:

Icon

Username with link to /u/<user_url_slug/

/p/<postid_url_slug>/

screenshot 1, screenshot 2, screenshot 3, screenshot 4

This page shows one post. Include the same information for this one post as is shown on the main page / .

Test

Run the public autograder testcases on your insta485 .

$ pytest tests/test_followers.py tests/test_following.py tests/test_generated_html.py test

========================== 17 passed in 5.59 seconds ===========================

Error messages

Catch all jinja, json, and FilenotFound exceptions and print sensible error messages (make sure the error message starts with ‘Error_’). Then, exit non-zero. Here’s an example:

$ pwd/

/Users/awdeorio/src/eecs485/p1-insta485-static

$ insta485generator insta485

Error_JSON: failed to parse insta485/config.json Expecting value: line 370 column 1 (char 8976)

$ echo $?

1

Make sure the errors begin as described:

For all jinja related exceptions, the error begins with Error_Jinja For all json related exceptions, the error begins with Error_JSON

For all FileNotFound related exceptions, the error begins with Error_FileNotFound

Note: in the bash shell, echo $? prints the exit code (return value) of the previous command.

You should handle the case in which the output directory already has files in it. The example below shows how the program should behave in this case.

$ rm -rf hello/html

$ insta485generator hello

$ insta485generator hello

Error_Output_Dir: output directory already contains files: hello/html

Submitting and grading

Run the published autograder test cases locally.

$ pytest tests/

========================== 38 passed in 12.67 seconds ==========================

Submit a tarball to the autograder, which is linked from https://eecs485.org. Include the disable-copyfile flag only on macOS.

$ tar

–disable-copyfile

–exclude ‘*__pycache__*’

–exclude ‘insta485/html’

-czvf submit.tar.gz

bin html insta485 insta485generator setup.py

The autograder will run pip install -e YOUR_SOLUTION . The exact library versions in the setup.py provided with the starter files is cached on the autograder, so be sure not to add extra

library dependencies to setup.py .

Avoid adding any large images to the tarball. The Autograder may throw an error in case the size of the tarball is greater than 5MB. Use the following command to verify the size of the tarball:

$ du -h submit.tar.gz

2.1M submit.tar.gz

Direct link to the Fall 2019 Project 1 autograder: https://autograder.io/web/project/404.

Rubric

This is an approximate rubric. Note than we cannot give additional information about what the private testcases do. To maximize points, make sure that you are following all directions in the spec. Note that the public tests cases do not test everything that your program must do.

Test Value
Public unit tests 50%
Public Python and HTML style 10%
Hidden unit tests run after the deadline 40%

FAQ

Can I use Python2?

No. You can check your version of your default Python like this:

$ python –version Python 2.7.13

After activating a virtual environment, the default python executable may change. For example:

$ python3 -m venv env

$ source env/bin/activate

$ python –version Python 3.6.1

Can I disable any code style checks?

Do not disable any code style check from any code style tool ( pycodestyle , pydocstyle , pylint ).

Can I spawn new processes?

When writing insta485generator , do not use any code that spawns a new process. The autograder will fail if new processes are spawned. Examples of Python snippets that spawn a new process: os.system() , sh.ls() , subprocess.check_call() . If you’re uncertain whether a new process is being spawned, please ask!

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] EECS485 P1: Templated Static Site Generator
30 $