Exercise: Refactoring - Extract Both CSV Formats Into Module

Requirement

Create a module userdb_csv.py to be imported from whatever program. That module will contain

Test Code

The following test (see pytest Introduction, By Example for how to use it) can better express the requirement,

# -*- encoding: utf-8 -*-

import userdb_csv

import pytest


def test_noheader(tmpdir):
    with open(tmpdir/'noheader.csv', 'w', encoding='cp1252') as f:
        f.writelines([
            '1;"Jörg;DI";Faschingbauer;19.6.1966\n',
            '2;Caro;Faschingbauer;25.4.1997\n',
            '3;Johanna;Faschingbauer;11.6.1995\n',
            '4;Philipp;Lichtenberger;6.4.1986\n',
            '5;Elizabeth II;Queen;1.1.1900\n',
        ])
            
    users = list(userdb_csv.read_csv_noheader(tmpdir/'noheader.csv'))

    assert users[0]['id'] == 1
    assert users[0]['firstname'] == 'Jörg;DI'
    assert users[0]['lastname'] == 'Faschingbauer'
    assert users[0]['birth'] == '19.6.1966'

    assert users[1]['id'] == 2
    assert users[1]['firstname'] == 'Caro'
    assert users[1]['lastname'] == 'Faschingbauer'
    assert users[1]['birth'] == '25.4.1997'

    assert users[2]['id'] == 3
    assert users[2]['firstname'] == 'Johanna'
    assert users[2]['lastname'] == 'Faschingbauer'
    assert users[2]['birth'] == '11.6.1995'

    assert users[3]['id'] == 4
    assert users[3]['firstname'] == 'Philipp'
    assert users[3]['lastname'] == 'Lichtenberger'
    assert users[3]['birth'] == '6.4.1986'

    assert users[4]['id'] == 5
    assert users[4]['firstname'] == 'Elizabeth II'
    assert users[4]['lastname'] == 'Queen'
    assert users[4]['birth'] == '1.1.1900'

def test_header(tmpdir):
    with open(tmpdir/'header.csv', 'w', encoding='cp1252') as f:
        f.writelines([
            'ID;First name;Last name;Date of Birth\n',
            '1;"Jörg;DI";Faschingbauer;19.6.1966\n',
            '2;Caro;Faschingbauer;25.4.1997\n',
            '3;Johanna;Faschingbauer;11.6.1995\n',
            '4;Philipp;Lichtenberger;6.4.1986\n',
            '5;Elizabeth II;Queen;1.1.1900\n',
        ])
            
    users = list(userdb_csv.read_csv_header(tmpdir/'header.csv'))

    assert users[0]['id'] == 1
    assert users[0]['firstname'] == 'Jörg;DI'
    assert users[0]['lastname'] == 'Faschingbauer'
    assert users[0]['birth'] == '19.6.1966'

    assert users[1]['id'] == 2
    assert users[1]['firstname'] == 'Caro'
    assert users[1]['lastname'] == 'Faschingbauer'
    assert users[1]['birth'] == '25.4.1997'

    assert users[2]['id'] == 3
    assert users[2]['firstname'] == 'Johanna'
    assert users[2]['lastname'] == 'Faschingbauer'
    assert users[2]['birth'] == '11.6.1995'

    assert users[3]['id'] == 4
    assert users[3]['firstname'] == 'Philipp'
    assert users[3]['lastname'] == 'Lichtenberger'
    assert users[3]['birth'] == '6.4.1986'

    assert users[4]['id'] == 5
    assert users[4]['firstname'] == 'Elizabeth II'
    assert users[4]['lastname'] == 'Queen'
    assert users[4]['birth'] == '1.1.1900'

Dependencies

cluster_python Python Programming: From Absolute Beginner to Advanced Productivity cluster_python_basics Python: The Language Fundamentals cluster_python_exercises Exercises cluster_python_exercises_userdb User Database (Exercise Series) cluster_python_misc Python: Miscellaneous Topics cluster_python_advanced Python: More Language Features python_basics_python_0130_syntax_etc Syntax etc. python_basics_python_0120_helloworld Hello World python_basics_python_0130_syntax_etc->python_basics_python_0120_helloworld python_basics_python_0200_sequential_types Sequential Datatypes python_basics_python_0150_datatypes_overview_compound Compound Datatypes python_basics_python_0200_sequential_types->python_basics_python_0150_datatypes_overview_compound python_basics_python_0193_while while Loops python_basics_python_0170_if The if Statement python_basics_python_0193_while->python_basics_python_0170_if python_basics_python_0160_boolean Boolean python_basics_python_0193_while->python_basics_python_0160_boolean python_basics_python_0110_blahblah Blahblah python_basics_python_0320_strings_methods Miscellaneous String Methods python_basics_python_0300_strings More About Strings python_basics_python_0320_strings_methods->python_basics_python_0300_strings python_basics_python_0139_commandline_argv Commandline Arguments (sys.argv) python_basics_python_0139_commandline_argv->python_basics_python_0130_syntax_etc python_basics_python_0125_running Running Python Programs python_basics_python_0139_commandline_argv->python_basics_python_0125_running python_basics_python_0250_refs_flat_deep_copy References, (Im)mutability python_basics_python_0250_refs_flat_deep_copy->python_basics_python_0150_datatypes_overview_compound python_basics_python_0140_variables Variables python_basics_python_0250_refs_flat_deep_copy->python_basics_python_0140_variables python_basics_python_0150_datatypes_overview Datatypes python_basics_python_0250_refs_flat_deep_copy->python_basics_python_0150_datatypes_overview python_basics_python_0120_helloworld->python_basics_python_0110_blahblah python_basics_python_0500_files File I/O python_basics_python_0220_for for Loops python_basics_python_0500_files->python_basics_python_0220_for python_misc_encoding Encoding python_basics_python_0500_files->python_misc_encoding python_basics_python_0170_if->python_basics_python_0160_boolean python_basics_python_0300_strings->python_basics_python_0200_sequential_types python_basics_python_0300_strings->python_basics_python_0250_refs_flat_deep_copy python_basics_python_0300_strings->python_basics_python_0150_datatypes_overview python_basics_python_0150_datatypes_overview_compound->python_basics_python_0150_datatypes_overview python_basics_python_0270_functions Functions python_basics_python_0270_functions->python_basics_python_0140_variables python_basics_python_0270_functions->python_basics_python_0150_datatypes_overview python_basics_python_0140_variables->python_basics_python_0130_syntax_etc python_basics_python_0150_datatypes_overview->python_basics_python_0140_variables python_basics_python_0220_for->python_basics_python_0200_sequential_types python_basics_python_0220_for->python_basics_python_0193_while python_basics_python_0160_boolean->python_basics_python_0150_datatypes_overview python_basics_python_0125_running->python_basics_python_0120_helloworld python_exercises_userdb_csvdictreader_function Exercise: Refactoring - Extract CSV Reading Into Function (csv.dictreader) python_exercises_userdb_csvdictreader_function->python_basics_python_0270_functions python_exercises_userdb_csvdictreader Exercise: Read CSV File (csv.dictreader) python_exercises_userdb_csvdictreader_function->python_exercises_userdb_csvdictreader python_exercises_userdb_userdb_module Exercise: Refactoring - Extract Both CSV Formats Into Module python_exercises_userdb_userdb_module->python_exercises_userdb_csvdictreader_function python_exercises_userdb_csvreader Exercise: Read CSV File (csv.reader) python_exercises_userdb_userdb_module->python_exercises_userdb_csvreader python_advanced_modules Modules and Packages python_exercises_userdb_userdb_module->python_advanced_modules python_exercises_userdb_csvreader->python_basics_python_0139_commandline_argv python_misc_csv CSV Files python_exercises_userdb_csvreader->python_misc_csv python_exercises_userdb_csvdictreader->python_basics_python_0139_commandline_argv python_exercises_userdb_csvdictreader->python_exercises_userdb_csvreader python_exercises_userdb_csvdictreader->python_misc_csv python_misc_csv->python_basics_python_0500_files python_misc_csv->python_basics_python_0150_datatypes_overview_compound python_misc_csv->python_basics_python_0220_for python_misc_encoding->python_basics_python_0320_strings_methods python_misc_encoding->python_basics_python_0150_datatypes_overview