UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ Lab 17

# Getting Started

• Make a directory `~/cs2613/labs/L17`
• Download Work.zip and unzip in your newly created directory.

# Higher order functions

Time
25 minutes
Activity
Assemble given pieces
• Complete Exercise 3.5. Note that you are given an initial version of `fileparse.py` containing a function `parse_csv` in Exercise 3.4 just above. Make sure that your modified function passes the following test.
```def test_portfolio():
portfolio = parse_csv('Data/portfolio.csv', types=[str, int, float])
assert portfolio == [{'price': 32.2, 'name': 'AA', 'shares': 100},
{'price': 91.1, 'name': 'IBM', 'shares': 50},
{'price': 83.44, 'name': 'CAT', 'shares': 150},
{'price': 51.23, 'name': 'MSFT', 'shares': 200},
{'price': 40.37, 'name': 'GE', 'shares': 95},
{'price': 65.1, 'name': 'MSFT', 'shares': 50},
{'price': 70.44, 'name': 'IBM', 'shares': 100}]

def test_shares():
shares_held = parse_csv('Data/portfolio.csv', select=['name', 'shares'], types=[str, int])
assert shares_held == [{'name': 'AA', 'shares': 100}, {'name': 'IBM', 'shares': 50},
{'name': 'CAT', 'shares': 150}, {'name': 'MSFT', 'shares': 200},
{'name': 'GE', 'shares': 95}, {'name': 'MSFT', 'shares': 50},
{'name': 'IBM', 'shares': 100}]
```
• Question for your journal: what is the type of the argument `types`?

# Refactoring a function

Time
35 minutes
Activity
Refactor function to add feature
• Complete Exercise 3.6. You only need to write a few lines of code, but you will need to make several blocks of code conditional on `has_headers`. Be careful when re-indenting code, remember Python is picky about indentation.

• Make sure the following test (and your previous tests) pass

```def test_tuple():
prices = parse_csv('Data/prices.csv', types=[str,float], has_headers=False)
assert prices == [('AA', 9.22), ('AXP', 24.85), ('BA', 44.85), ('BAC', 11.27),
('C', 3.72), ('CAT', 35.46), ('CVX', 66.67), ('DD', 28.47),
('DIS', 24.22), ('GE', 13.48), ('GM', 0.75), ('HD', 23.16),
('HPQ', 34.35), ('IBM', 106.28), ('INTC', 15.72), ('JNJ', 55.16),
('JPM', 36.9), ('KFT', 26.11), ('KO', 49.16), ('MCD', 58.99),
('MMM', 57.1), ('MRK', 27.58), ('MSFT', 20.89), ('PFE', 15.19),
('PG', 51.94), ('T', 24.79), ('UTX', 52.61), ('VZ', 29.26),
('WMT', 49.74), ('XOM', 69.35)]
```

# Raising exceptions

Time
20 minutes
Activity
• Complete Exercise 3.8. This only needs a few lines of code added to your solution to 3.6.

• Question for your journal: where should the added error check go, and why?

• Here we need to do something new, to write a test that checks for an exception

```def test_exception():
with pytest.raises(RuntimeError) as e_info:
prices = parse_csv('Data/prices.csv', select=['name','price'], has_headers=False)
```
• Question for your journal: does the exception here need to be `RuntimeError`? Why or why not?

# Modules

Time
20 minutes
Activity
Refactor existing code to to reuse a function.
• This is a modified version of Exercise 3.12.

• Update your report2.py so that it does not directly import import `csv`, but rather `read_portfolio` calls `parse_csv` from `fileparse.py`.

• Use an appropriate import statement for `parse_csv`, do not copy that code into `report2.py`

• make sure that the existing tests continue to pass, along with the following.

```def test_prices():
• Question for your journal, what is the name of the new feature used to construct `prices`?