Assignment 1, CSC202, Spring 2017
1 Guidelines
2 Detailed Instructions
6.9.0.6

Assignment 1, CSC202, Spring 2017

Defining classes in Python is a little bit irritating; you have to write the init method, and the repr method, and the eq method. In this project, you’ll solve this problem, by writing your own code that generates this boilerplate automatically.

For instance, it should be possible to supply the class name "Plate" and the field names "diameter" and "material" and generate the text

class Plate:

    def __init__(self, diameter, material):

        self.diameter = diameter

        self.material = material

 

    def __eq__(self, other):

        return (type(other) == Plate

                and self.diameter == other.diameter

                and self.material == other.material

                )

 

    def __repr__(self):

        return "Plate({!r}, {!r})".format(self.diameter, self.material)

Let’s tackle this in small pieces.

1 Guidelines

For each item that asks you to develop a function, please follow the steps of the design recipe.

Please note that you are not just encouraged but more or less required to develop helper functions in several places below. It’s always all right to develop helper functions. Make sure to follow the design recipe for these helper functions, too.

Also, note that for the functions, data definitions, and classes whose names are provided, you’ll need to use the provided names in order to get credit; the grading scripts will be looking for precisely the names given here, and the same argument order (when applicable (ooh, a pun! "Applicable?" get it? Oh, never mind.)).

Next, please be sure to follow naming conventions; functions, arguments, and field names should be lower_case_with_underscores, and class names should be CamelCaseLikeThis.

Since this project asks you to write functions that generate text, we’ll be testing that they generate the right text. This means that we’ll be counting spaces; if your function has the wrong number of leading spaces, it won’t get full credit. Check this by copying and pasting from the text above.

Put your program in a single file. Call it "project1.py". You need to have 100% test case coverage in order to receive credit for this assignment, or feedback from the automatic grader. (If you follow the design recipe, this should be a piece of cake.)

Finally: this assignment does not require any value mutation. Don’t mutate values in this assignment.

2 Detailed Instructions

  1. Use this invitation link to create your own repo for the project, and clone it (it’s essentially empty, except for a "README" and a ".gitignore").

  2. Develop a data definition for a list of strings (StrList), just as we did in class.

  3. Develop a data definition for a ClassShape, which contains a name and a StrList of field names.

  4. We’re going to use StrLists to represent lists of fields, and also to represent lists of strings representing Python programs. Develop the join_lines function, that accepts a StrList representing the lines of code in a Python program, and joins them together into a single string with newlines in between and at the end . Use the + operator to append strings, and use the string "\n" to represent a newline. Follow the steps of the design recipe, and be sure to write tests before filling in the body.

  5. Next, we should tackle the __init__ method. This will involve two steps. First, we need to map the fields to the field assignment lines. Develop the fields_to_assignments function, that maps a StrList of field names to a StrList of lines, where each line is of the

    self.<field> = <field>

    form shown above. Be sure to add the appropriate amount of space to the beginning of each line (whitespace sensitivity doesn’t seem quite as nice when you’re generating code programmatically...). It would be reasonable to create a helper function to handle mapping a single field to a single line, if that’s helpful to you.

  6. The first line of the __init__ method has an additional twist, because the names of the fields must appear here, separated by commas. Develop the commasep function, that accepts a StrList of field names and returns a string where the elements are joined together with a ", " preceding each element. So, for instance, if you use the list

    Pair("abc", Pair("def", "mt"))

    , you should get back the string ", abc, def".

  7. Let’s put together the __init__ method. Develop the init_method function, that accepts a list of field names, and returns a StrList representing the lines of the __init__ method, as shown above. Note that if there are no fields in the class, the body of the __init__ method will need to contain a pass statement.

  8. Follow a similar development process to develop the eq_method function. Note that the __eq__ method needs to know about the name of the class; rather than passing the StrList of fields to this function, just pass in a ClassShape, which contains both the field names and the class’s name.

  9. Follow a similar development process to develop the repr_method function that accepts a ClassShape and returns a StrList of lines.

  10. We’re there! Develop the render_class function, that accepts a ClassShape and returns a single string containing the entire class definition. This function should call many of your other functions.