├── 1261_06_Code ├── 1261_06_01_empty_object.py ├── 1261_06_15_stupid_adding_integer.py ├── 1261_06_04_dict_stocks.py ├── 1261_06_03_named_tuple.py ├── 1261_06_20_collect_remaining_links.py ├── 1261_06_21_print_collected_links.py ├── 1261_06_08_defaultdict_custom_function.py ├── 1261_06_07_defaultdict_frequency.py ├── 1261_06_06_setdefault_frequency.py ├── 1261_06_02_pass_tuple_to_function.py ├── case_study_serve │ ├── taichi.html │ ├── contact.html │ ├── blog.html │ ├── index.html │ ├── hobbies.html │ └── esme.html ├── 1261_06_14_oop_pairs.py ├── 1261_06_18_normalize_url.py ├── 1261_06_09_list_tuple_frequency.py ├── 1261_06_12_set_operations.py ├── 1261_06_10_object_comparison.py ├── 1261_06_11_song_artist_set.py ├── 1261_06_17_link_parser.py ├── 1261_06_13_set_operations2.py ├── 1261_06_05_random_key_dict.py ├── 1261_06_16_dictsorted.py ├── 1261_06_19_visited_links_sets.py ├── link_collector.py └── 1261_06_22_dict_link_collector.py ├── 1261_02_Code ├── 1261_2_01-basic_class.py ├── 1261_2_08-initialization_defaults.py ├── 1261_2_10-database_module-level-global.py ├── 1261_2_02-instantiate_basic_class.py ├── 1261_2_04-first_method.py ├── 1261_2_05-invoking_method_statically.py ├── 1261_2_03_attributes.py ├── 1261_2_11-database_module-level-global-initializer.py ├── 1261_2_19-findnote_str.py ├── 1261_2_12-main-example.py ├── 1261_2_20-notebook_modify_sanity_check.py ├── 1261_2_07-initialization_function.py ├── 1261_2_17-notebook_findnote_method.py ├── 1261_2_14-name_mangling.py ├── 1261_2_13-class_in_function.py ├── 1261_2_06-methods_with_arguments.py ├── 1261_2_15-note_object.py ├── 1261_2_09-docstrings.py ├── 1261_2_16-notebook_first.py ├── menu.py ├── 1261_2_18-notebook_menu.py └── notebook.py ├── 1261_11_Code ├── test_simplepytest.py ├── 1261_11_06_simplestpytest.py ├── 1261_11_15_pytest_skipifmark.py ├── 1261_11_07_class_pytest.py ├── 1261_11_14_pytest_importorskip.py ├── 1261_11_13_pytest_simple_skip.py ├── 1261_11_16_coverage_unittest.py ├── 1261_11_01_simplest_unittest.py ├── 1261_11_11_echo_server.py ├── 1261_11_02_assertraises_python31.py ├── 1261_11_09_funcargs.py ├── 1261_11_10_funcarg_finalizer.py ├── 1261_11_04_test_stats.py ├── stats.py ├── 1261_11_03_stats.py ├── 1261_11_05_skipping_tests.py ├── 1261_11_12_pytest_echo.py ├── 1261_11_08_setup_teardown.py └── casestudy │ ├── vigenere_cipher.py │ ├── vigenere_cipher1.py │ └── test_vigenere_cipher.py ├── 1261_03_Code ├── 1261_3_01_inheriting_from_object.py ├── 1261_3_26_rudimentary_agent.py ├── 1261_3_08_send_mail.py ├── 1261_3_10_friend_address_holder.py ├── 1261_3_09_send_mail_multi.py ├── 1261_3_02_simple_contact_class_to_inherit_from.py ├── 1261_3_24_house_rental.py ├── 1261_3_05_dictionary_long_name.py ├── 1261_3_20_validation_function.py ├── 1261_3_11_friend_multi.py ├── 1261_3_17_ducktype_flac.py ├── 1261_3_07_friend_overrides_init_super.py ├── 1261_3_06_friend_overrides_init.py ├── 1261_3_03_contact_inherit_supplier.py ├── 1261_3_27_type_map.py ├── 1261_3_04_contact_list_inheritance.py ├── 1261_3_16_polymorphic_audio.py ├── 1261_3_15_friend_multi_super.py ├── 1261_3_25_remaining_subclasses.py ├── 1261_3_14_contrived_diamond_super.py ├── 1261_3_18_property.py ├── 1261_3_12_contrived_diamond.py ├── 1261_3_28_add_property.py ├── 1261_3_21_apartment_nice_prompt.py ├── 1261_3_22_house.py ├── 1261_3_19_apartment_ugly_prompt.py ├── 1261_3_23_purchase_and_rental.py └── final_case_study.py ├── README.md ├── 1261_10_Code ├── 1261_10_07_unlabelled_kw.py ├── 1261_10_17_bytearray_replace.py ├── 1261_10_18_bytearray_index.py ├── 1261_10_19_file_as_ascii.py ├── 1261_10_21_with.py ├── 1261_10_02_format_empty.py ├── 1261_10_14_format_datetime.py ├── 1261_10_03_format_position.py ├── 1261_10_15_encode_bytes.py ├── 1261_10_04_format_some_positions_broken.py ├── 1261_10_20_write.py ├── 1261_10_01_string_creation.py ├── 1261_10_11_no_format.py ├── 1261_10_16_decode_unicode.py ├── 1261_10_12_currency_format.py ├── 1261_10_05_brace_escape.py ├── 1261_10_23_stringio.py ├── 1261_10_13_tabular.py ├── 1261_10_06_format_kw_args.py ├── 1261_10_08_tuple_dict_format.py ├── 1261_10_09_tuple_in_dict_format.py ├── 1261_10_22_context_manager.py ├── 1261_10_24_basic_pickling.py ├── 1261_10_10_object_formatting.py ├── 1261_10_26_json_objects.py └── 1261_10_25_state_pickling.py ├── 1261_08_Code ├── 1261_08_10_decorator_syntax.py ├── 1261_08_01_canonical_iterator.py ├── 1261_08_03_simple_client.py ├── 1261_08_06_calling_decorated_sockets.py ├── 1261_08_16_singleton_using_new.py ├── 1261_08_02_simple_socket.py ├── 1261_08_19_template_abstract_noimple.py ├── 1261_08_14_simple_xml_to_parse.xml ├── 1261_08_04_logging_decorator.py ├── 1261_08_09_logging_decorator.py ├── 1261_08_11_observer_core.py ├── 1261_08_05_gzip_decorator.py ├── 1261_08_18_create_database_for_template.py ├── 1261_08_20_template_abstract_implemented.py ├── 1261_08_12_observer_observing.py ├── 1261_08_13_strategy_tile.py ├── 1261_08_21_template_concretes.py ├── 1261_08_15_xml_states.py ├── 1261_08_17_xml_singletonstates.py └── oldsing ├── 1261_05_Code ├── 1261_05_09_property_decorator_get.py ├── 1261_05_27_string_property.py ├── 1261_05_16_average_property.py ├── 1261_05_12_property_decorator_get_set.py ├── 1261_05_13_read_only_setattr.py ├── 1261_05_14_read_only_getattribute.py ├── 1261_05_05_python_pretty_as_python.py ├── 1261_05_04_pytho_ugly_as_java.py ├── 1261_05_01_distances_no_objects.py ├── 1261_05_06_setting_name_in_method.py ├── 1261_05_15_cache_getter.py ├── 1261_05_07_setting_name_property.py ├── 1261_05_11_property_decorator_arguments.py ├── 1261_05_08_property_arguments.py ├── 1261_05_28_Character_class.py ├── 1261_05_20_scaleimage_inheritance.py ├── 1261_05_24_most_basic_document.py ├── 1261_05_02_distances_by_object.py ├── 1261_05_25_document_cursor.py ├── 1261_05_03_object_polygon_init.py ├── 1261_05_19_zipreplace_inheritance.py ├── 1261_05_18_zipprocessor.py ├── 1261_05_23_zipreplace_composition.py ├── zip_processor.py ├── 1261_05_21_zipprocessor_composition.py ├── 1261_05_26_document_using_cursor.py ├── 1261_05_17_zipsearch.py ├── Document.py └── 1261_05_29_document_with_character.py ├── 1261_07_Code ├── 1261_07_04_tdf_contact.txt ├── 1261_07_08_list_comp_exclude.py ├── 1261_07_20_link_downloader_vararg.py ├── 1261_07_07_list_comp_converter.py ├── 1261_07_06_for_loop_converter.py ├── 1261_07_18_bad_kw_default.py ├── .1261_07_32_mailing_list_defaultdict_set.py.swp ├── 1261_07_33_mailing_list_get_emails.py ├── 1261_07_03_enumerate_max_min.py ├── 1261_07_32_mailing_list_defaultdict_set.py ├── 1261_07_02_enumerate_line_numbers.py ├── 1261_07_27_add_function_to_object.py ├── 1261_07_34_send_mailing.py ├── 1261_07_15_log_delete_warnings_loop.py ├── 1261_07_13_log_processor.py ├── 1261_07_19_link_downloader.py ├── 1261_07_14_log_delete_warning_expression.py ├── 1261_07_23_unpacking_arguments.py ├── 1261_07_05_tdf_processor.py ├── 1261_07_17_log_delete_warnings_generator.py ├── 1261_07_09_tdf_list_comp.py ├── 1261_07_21_kwarg_options.py ├── 1261_07_01_reversible_objects.py ├── 1261_07_28_callable_repeat.py ├── 1261_07_29_send_email.py ├── 1261_07_12_log_file.log ├── 1261_07_10_set_comprehension.py ├── 1261_07_11_dict_comprehension.py ├── 1261_07_24_function_object.py ├── 1261_07_30_send_email_dict_headers.py ├── 1261_07_16_log_delete_warnings_object.py ├── timer.py ├── 1261_07_25_timer.py ├── 1261_07_22_all_arguments.py ├── 1261_07_26_timer_test.py └── mailing_list.py ├── 1261_04_Code ├── 1261_04_10_defining_an_exception.py ├── 1261_04_08_catch_as_keyword.py ├── 1261_04_02_exception_quits.py ├── 1261_04_05_catch_specific_exception.py ├── 1261_04_01_even_integers.py ├── 1261_04_04_try_except.py ├── 1261_04_11_exception_with_custom_args.py ├── 1261_04_03_method_calls_excepting.py ├── 1261_04_06_catch_multiple_exceptions.py ├── 1261_04_07_catch_multiple_different.py ├── 1261_04_12_handle_custom_exception.py ├── 1261_04_09_finally_and_else.py ├── 1261_04_13_branching_vs_exceptions.py ├── 1261_04_15_inventory_handling.py ├── 1261_04_14_inventory_mock_object.py ├── 1261_04_16_auth_user.py ├── 1261_04_17_authenticator.py ├── 1261_04_18_login.py ├── 1261_04_20_test_auth.py ├── auth.py └── 1261_04_19_authorizor.py ├── 1261_12_Code ├── 1267_12_03_tkinter_emptyframe.py ├── 1267_12_05_qt_emptyframe.py ├── 1267_12_11_basic_cherrypy.py ├── blog_templates │ ├── comment_form.html │ ├── add.html │ ├── base.html │ └── index.html ├── 1267_12_07_html_document.html ├── 1267_12_13_form_arguments.py ├── 1267_12_09_etree_write_html.py ├── 1267_12_01_sqlite.py ├── 1267_12_04_tkinter_dice.py ├── 1267_12_02_alchemy_intro.py ├── 1267_12_08_etree_read_html.py ├── 1267_12_12_multipage_cherrypy.py ├── 1267_12_04.5_tkinter_pack.py ├── 1267_12_06_rockpaper.py ├── 1267_12_10_lxml_xpath.py └── 1267_12_14_blog.py ├── 1261_09_Code ├── 1261_09_12_window_command_function.py ├── 1261_09_05_flyweight_factory.py ├── 1261_09_09_window_commands.py ├── 1261_09_01_age_calculator.py ├── 1261_09_03_age_calculator_adapt_date.py ├── 1261_09_16_composite_folder_methods.py ├── 1261_09_13_document_command_callable.py ├── 1261_09_02_age_calculator_adapted.py ├── 1261_09_06_flyweight_init.py ├── 1261_09_10_window_command_invokers.py ├── 1261_09_17_component_hierarchy.py ├── 1261_09_18_add_child.py ├── 1261_09_07_flyweight_check_serial.py ├── 1261_09_04_email_facade.py ├── 1261_09_08_car_class.py ├── 1261_09_11_window_command_commands.py ├── 1261_09_14_formatters.py └── 1261_09_15_formatter_factories.py └── .gitignore /1261_06_Code/1261_06_01_empty_object.py: -------------------------------------------------------------------------------- 1 | class MyObject: 2 | pass 3 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_01-basic_class.py: -------------------------------------------------------------------------------- 1 | class MyFirstClass: 2 | pass 3 | -------------------------------------------------------------------------------- /1261_11_Code/test_simplepytest.py: -------------------------------------------------------------------------------- 1 | def test_int_float(): 2 | assert 1 == 1.0 3 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_01_inheriting_from_object.py: -------------------------------------------------------------------------------- 1 | class MySubClass(object): 2 | pass 3 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_06_simplestpytest.py: -------------------------------------------------------------------------------- 1 | def test_int_float(): 2 | assert 1 == 1.0 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python-3-Object-Oriented-Programming 2 | ==================================== 3 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_07_unlabelled_kw.py: -------------------------------------------------------------------------------- 1 | print("{} {label} {}".format("x", "y", label="z")) 2 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_10_decorator_syntax.py: -------------------------------------------------------------------------------- 1 | @log_calls 2 | def test1(a,b,c): 3 | print("\ttest1 called") 4 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_17_bytearray_replace.py: -------------------------------------------------------------------------------- 1 | b = bytearray(b"abcdefgh") 2 | b[4:6] = b"\x15\xa3" 3 | print(b) 4 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_18_bytearray_index.py: -------------------------------------------------------------------------------- 1 | b = bytearray(b'abcdef') 2 | b[3] = ord(b'g') 3 | b[4] = 68 4 | print(b) 5 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_15_stupid_adding_integer.py: -------------------------------------------------------------------------------- 1 | class SillyInt(int): 2 | def __add__(self, num): 3 | return 0 4 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_19_file_as_ascii.py: -------------------------------------------------------------------------------- 1 | file = open('filename', encoding='ascii', errors='replace') 2 | print(file.read()) 3 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_21_with.py: -------------------------------------------------------------------------------- 1 | with open('filename') as file: 2 | for line in file: 3 | print(line, end='') 4 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_08-initialization_defaults.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x=0, y=0): 3 | self.move(x, y) 4 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_09_property_decorator_get.py: -------------------------------------------------------------------------------- 1 | class Foo: 2 | @property 3 | def foo(self): 4 | return "bar" 5 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_27_string_property.py: -------------------------------------------------------------------------------- 1 | @property 2 | def string(self): 3 | return "".join(self.characters) 4 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_04_dict_stocks.py: -------------------------------------------------------------------------------- 1 | stocks = {"GOOG": (613.30, 625.86, 610.50), 2 | "MSFT": (30.25, 30.70, 30.19)} 3 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_02_format_empty.py: -------------------------------------------------------------------------------- 1 | template = "Hello {}, you are currently {}." 2 | print(template.format('Dusty', 'writing')) 3 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_14_format_datetime.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | print("{0:%Y-%m-%d %I:%M%p }".format( 3 | datetime.datetime.now())) 4 | 5 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_01_canonical_iterator.py: -------------------------------------------------------------------------------- 1 | while not iterator.done(): 2 | item = iterator.next() 3 | # do something with the item 4 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_03_format_position.py: -------------------------------------------------------------------------------- 1 | template = "Hello {0}, you are {1}. Your name is {0}." 2 | print(template.format('Dusty', 'writing')) 3 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_15_encode_bytes.py: -------------------------------------------------------------------------------- 1 | characters = b'\x63\x6c\x69\x63\x68\xe9' 2 | print(characters) 3 | print(characters.decode("latin-1")) 4 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_10-database_module-level-global.py: -------------------------------------------------------------------------------- 1 | class Database: 2 | # the database implementation 3 | pass 4 | 5 | database = Database() 6 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_16_average_property.py: -------------------------------------------------------------------------------- 1 | class AverageList(list): 2 | @property 3 | def average(self): 4 | return sum(self) / len(self) 5 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_02-instantiate_basic_class.py: -------------------------------------------------------------------------------- 1 | class MyFirstClass: 2 | pass 3 | 4 | a = MyFirstClass() 5 | b = MyFirstClass() 6 | print(a) 7 | print(b) 8 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_04_tdf_contact.txt: -------------------------------------------------------------------------------- 1 | first last email 2 | john smith jsmith@example.com 3 | jane doan janed@example.com 4 | david neilson dn@example.com 5 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_04_format_some_positions_broken.py: -------------------------------------------------------------------------------- 1 | template = "Hello {}, you are {}. Your name is {0}." 2 | print(template.format('Dusty', 'writing')) 3 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_08_list_comp_exclude.py: -------------------------------------------------------------------------------- 1 | input_strings = ['1', '5', '28', '131', '3'] 2 | 3 | output_integers = [int(n) for n in input_strings if len(n) < 3] 4 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_10_defining_an_exception.py: -------------------------------------------------------------------------------- 1 | class InvalidWithdrawal(Exception): 2 | pass 3 | 4 | raise InvalidWithdrawal("You don't have $50 in your account") 5 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_20_link_downloader_vararg.py: -------------------------------------------------------------------------------- 1 | def get_pages(*links): 2 | for link in links: 3 | #download the link with urllib 4 | print(link) 5 | 6 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_04-first_method.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def reset(self): 3 | self.x = 0 4 | self.y = 0 5 | 6 | p = Point() 7 | p.reset() 8 | print(p.x, p.y) 9 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_08_catch_as_keyword.py: -------------------------------------------------------------------------------- 1 | try: 2 | raise ValueError("This is an argument") 3 | except ValueError as e: 4 | print("The exception arguments were", e.args) 5 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_20_write.py: -------------------------------------------------------------------------------- 1 | contents = "an oft-repeated cliché" 2 | file = open("filename", "w", encoding="ascii", errors="replace") 3 | file.write(contents) 4 | file.close() 5 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_03_tkinter_emptyframe.py: -------------------------------------------------------------------------------- 1 | import tkinter 2 | 3 | class EmptyFrame(tkinter.Frame): 4 | pass 5 | 6 | root = tkinter.Tk() 7 | EmptyFrame(master=root).mainloop() 8 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_07_list_comp_converter.py: -------------------------------------------------------------------------------- 1 | input_strings = ['1', '5', '28', '131', '3'] 2 | 3 | output_integers = [int(num) for num in input_strings] 4 | 5 | print(output_integers) 6 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_15_pytest_skipifmark.py: -------------------------------------------------------------------------------- 1 | import py.test 2 | 3 | @py.test.mark.skipif("sys.version_info <= (3,0)") 4 | def test_python3(): 5 | assert b"hello".decode() == "hello" 6 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_03_named_tuple.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | Stock = namedtuple("Stock", "symbol current high low") 3 | stock = Stock("GOOG", 613.30, high=625.86, low=610.50) 4 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_06_for_loop_converter.py: -------------------------------------------------------------------------------- 1 | input_strings = ['1', '5', '28', '131', '3'] 2 | 3 | output_integers = [] 4 | for num in input_strings: 5 | output_integers.append(int(num)) 6 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_18_bad_kw_default.py: -------------------------------------------------------------------------------- 1 | number = 5 2 | def funky_function(number=number): 3 | print(number) 4 | 5 | number=6 6 | funky_function(8) 7 | funky_function() 8 | print(number) 9 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_07_class_pytest.py: -------------------------------------------------------------------------------- 1 | 2 | class TestNumbers: 3 | def test_int_float(self): 4 | assert 1 == 1.0 5 | 6 | def test_int_str(self): 7 | assert 1 == "1" 8 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_05-invoking_method_statically.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def reset(self): 3 | self.x = 0 4 | self.y = 0 5 | 6 | p = Point() 7 | Point.reset(p) 8 | print(p.x, p.y) 9 | -------------------------------------------------------------------------------- /1261_07_Code/.1261_07_32_mailing_list_defaultdict_set.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono0926/Python-3-Object-Oriented-Programming/HEAD/1261_07_Code/.1261_07_32_mailing_list_defaultdict_set.py.swp -------------------------------------------------------------------------------- /1261_10_Code/1261_10_01_string_creation.py: -------------------------------------------------------------------------------- 1 | a = "hello" 2 | b = 'world' 3 | c = '''a multiple 4 | line string''' 5 | d = """More 6 | multiple""" 7 | e = ("Three " "Strings " 8 | "Together") 9 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_14_pytest_importorskip.py: -------------------------------------------------------------------------------- 1 | import py.test 2 | 3 | py.test.importorskip("postgresql") 4 | 5 | def test_connect(): 6 | pass 7 | 8 | def test_query(): 9 | pass 10 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_11_no_format.py: -------------------------------------------------------------------------------- 1 | subtotal = 12.32 2 | tax = subtotal * 0.07 3 | total = subtotal + tax 4 | 5 | print("Sub: ${0} Tax: ${1} Total: ${total}".format( 6 | subtotal, tax, total=total)) 7 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_33_mailing_list_get_emails.py: -------------------------------------------------------------------------------- 1 | def emails_in_groups(self, *groups): 2 | groups = set(groups) 3 | return {e for (e, g) in self.email_map.items() 4 | if g & groups} 5 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_16_decode_unicode.py: -------------------------------------------------------------------------------- 1 | characters = "cliché" 2 | print(characters.encode("UTF-8")) 3 | print(characters.encode("latin-1")) 4 | print(characters.encode("CP437")) 5 | print(characters.encode("ascii")) 6 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_20_collect_remaining_links.py: -------------------------------------------------------------------------------- 1 | for link in unvisited_links: 2 | if not link.startswith(self.url): 3 | continue 4 | self.collect_links(urlparse(link).path) 5 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_03_enumerate_max_min.py: -------------------------------------------------------------------------------- 1 | def min_max_indexes(seq): 2 | minimum = min(enumerate(seq), key=lambda s: s[1]) 3 | maximum = max(enumerate(seq), key=lambda s: s[1]) 4 | return minimum[0], maximum[0] 5 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_32_mailing_list_defaultdict_set.py: -------------------------------------------------------------------------------- 1 | def __init__(self): 2 | self.email_map = defaultdict(set) 3 | 4 | def add_to_group(self, email, group): 5 | self.email_map[email].add(group) 6 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_03_attributes.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | pass 3 | 4 | p1 = Point() 5 | p2 = Point() 6 | 7 | p1.x = 5 8 | p1.y = 4 9 | 10 | p2.x = 3 11 | p2.y = 6 12 | 13 | print(p1.x, p1.y) 14 | print(p2.x, p2.y) 15 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_21_print_collected_links.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | collector = LinkCollector(sys.argv[1]) 3 | collector.collect_links() 4 | for link in collector.collected_links: 5 | print(link) 6 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_02_enumerate_line_numbers.py: -------------------------------------------------------------------------------- 1 | import sys 2 | filename = sys.argv[1] 3 | 4 | with open(filename) as file: 5 | for index, line in enumerate(file): 6 | print("{0}: {1}".format(index+1, line), end='') 7 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_12_property_decorator_get_set.py: -------------------------------------------------------------------------------- 1 | class Foo: 2 | @property 3 | def foo(self): 4 | return self._foo 5 | 6 | @foo.setter 7 | def foo(self, value): 8 | self._foo = value 9 | 10 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_13_read_only_setattr.py: -------------------------------------------------------------------------------- 1 | class ReadOnlyX: 2 | def __setattr__(self, attr, value): 3 | if attr == "x": 4 | raise AttributeError("X is immutable") 5 | super().__setattr__(attr, value) 6 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_14_read_only_getattribute.py: -------------------------------------------------------------------------------- 1 | class ReadOnlyY: 2 | def __getattribute__(self, attr): 3 | if attr == "y": 4 | return "Just Try and Change Me!" 5 | return super().__getattribute__(attr) 6 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_03_simple_client.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4 | client.connect(('localhost', 2401)) 5 | print("Received: {0}".format(client.recv(1024))) 6 | client.close() 7 | 8 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_05_qt_emptyframe.py: -------------------------------------------------------------------------------- 1 | from PyQt4 import QtGui 2 | 3 | app = QtGui.QApplication([]) 4 | 5 | class EmptyWidget(QtGui.QWidget): 6 | pass 7 | 8 | window = EmptyWidget() 9 | window.show() 10 | app.exec_() 11 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_26_rudimentary_agent.py: -------------------------------------------------------------------------------- 1 | class Agent: 2 | def __init__(self): 3 | self.property_list = [] 4 | 5 | def display_properties(): 6 | for property in self.property_list: 7 | property.display() 8 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_08_send_mail.py: -------------------------------------------------------------------------------- 1 | class MailSender: 2 | def send_mail(self, message): 3 | print("Sending mail to " + self.email) 4 | # Add e-mail logic here 5 | 6 | class EmailableContact(Contact, MailSender): 7 | pass 8 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_10_friend_address_holder.py: -------------------------------------------------------------------------------- 1 | class AddressHolder: 2 | def __init__(self, street, city, state, code): 3 | self.street = street 4 | self.city = city 5 | self.state = state 6 | self.code = code 7 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_02_exception_quits.py: -------------------------------------------------------------------------------- 1 | def no_return(): 2 | print("I am about to raise an exception") 3 | raise Exception("This is always raised") 4 | print("This line will never execute") 5 | return "I won't be returned" 6 | 7 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_12_currency_format.py: -------------------------------------------------------------------------------- 1 | subtotal = 12.32 2 | tax = subtotal * 0.07 3 | total = subtotal + tax 4 | 5 | print("Sub: ${0:0.2f} Tax: ${1:0.2f} " 6 | "Total: ${total:0.2f}".format( 7 | subtotal, tax, total=total)) 8 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_09_send_mail_multi.py: -------------------------------------------------------------------------------- 1 | class MailSender: 2 | def send_mail(self, message): 3 | print("Sending mail to " + self.email) 4 | # Add e-mail logic here 5 | 6 | class EmailableContact(Friend, MailSender): 7 | pass 8 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_08_defaultdict_custom_function.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | num_items = 0 3 | def tuple_counter(): 4 | global num_items 5 | num_items += 1 6 | return (num_items, []) 7 | 8 | d = defaultdict(tuple_counter) 9 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_11-database_module-level-global-initializer.py: -------------------------------------------------------------------------------- 1 | class Database: 2 | # the database implementation 3 | pass 4 | 5 | database = None 6 | 7 | def initialize_database(): 8 | global database 9 | database = Database() 10 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_02_simple_contact_class_to_inherit_from.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | all_contacts = [] 3 | 4 | def __init__(self, name, email): 5 | self.name = name 6 | self.email = email 7 | Contact.all_contacts.append(self) 8 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_05_python_pretty_as_python.py: -------------------------------------------------------------------------------- 1 | class Color: 2 | def __init__(self, rgb_value, name): 3 | self.rgb_value = rgb_value 4 | self.name = name 5 | 6 | c = Color("#ff0000", "bright red") 7 | print(c.name) 8 | c.name = "red" 9 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_07_defaultdict_frequency.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | def letter_frequency(sentence): 3 | frequencies = defaultdict(int) 4 | for letter in sentence: 5 | frequencies[letter] += 1 6 | return frequencies 7 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_05_brace_escape.py: -------------------------------------------------------------------------------- 1 | template = """ 2 | public class {0} {{ 3 | public static void main(String[] args) {{ 4 | System.out.println("{1}"); 5 | }} 6 | }}""" 7 | 8 | print(template.format("MyClass", "print('hello world')")); 9 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_24_house_rental.py: -------------------------------------------------------------------------------- 1 | class HouseRental(Rental, House): 2 | def prompt_init(): 3 | init = House.prompt_init() 4 | init.update(Rental.prompt_init()) 5 | return init 6 | prompt_init = staticmethod(prompt_init) 7 | 8 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_27_add_function_to_object.py: -------------------------------------------------------------------------------- 1 | class A: 2 | def print(self): 3 | print("my class is A") 4 | 5 | def fake_print(): 6 | print("my class is not A") 7 | 8 | a = A() 9 | a.print() 10 | a.print = fake_print 11 | a.print() 12 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_19-findnote_str.py: -------------------------------------------------------------------------------- 1 | def _find_note(self, note_id): 2 | '''Locate the note with the given id.''' 3 | for note in self.notes: 4 | if str(note.id) == str(note_id): 5 | return note 6 | return None 7 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_06_setdefault_frequency.py: -------------------------------------------------------------------------------- 1 | def letter_frequency(sentence): 2 | frequencies = {} 3 | for letter in sentence: 4 | frequency = frequencies.setdefault(letter, 0) 5 | frequencies[letter] = frequency + 1 6 | return frequencies 7 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_34_send_mailing.py: -------------------------------------------------------------------------------- 1 | def send_mailing(self, subject, message, from_addr, 2 | *groups, **kwargs): 3 | emails = self.emails_in_groups(*groups) 4 | send_email(subject, message, from_addr, 5 | *emails, **kwargs) 6 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_05_dictionary_long_name.py: -------------------------------------------------------------------------------- 1 | class LongNameDict(dict): 2 | def longest_key(self): 3 | longest = None 4 | for key in self: 5 | if not longest or len(key) > len(longest): 6 | longest = key 7 | return longest 8 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_02_pass_tuple_to_function.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | def middle(stock, date): 3 | symbol, current, high, low = stock 4 | return (((high + low) /2), date) 5 | 6 | mid_value, date = middle(("GOOG", 613.30, 625.86, 610.50), 7 | datetime.date(2010, 1, 6)) 8 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_11_basic_cherrypy.py: -------------------------------------------------------------------------------- 1 | import cherrypy 2 | 3 | class SimplePage: 4 | @cherrypy.expose 5 | def index(self): 6 | with open("1267_12_07_html_document.html") as file: 7 | return file.read() 8 | 9 | cherrypy.quickstart(SimplePage()) 10 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/taichi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | I have studied Kung Fu, Tai Chi, Chi Kung, and fan under 4 | Master Helen Wu. I studied Wado 5 | Ryu Karate for many ears before that. 6 | 7 | 8 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_06_calling_decorated_sockets.py: -------------------------------------------------------------------------------- 1 | client, addr = server.accept() 2 | if log_send: 3 | client = LoggingSocket(client) 4 | if client.getpeername()[0] in compress_hosts: 5 | client = GzipSocket(client) 6 | respond(client) 7 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_13_pytest_simple_skip.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import py.test 3 | 4 | def test_simple_skip(): 5 | if sys.platform != "fakeos": 6 | py.test.skip("Test works only on fakeOS") 7 | 8 | fakeos.do_something_fake() 9 | assert fakeos.did_not_happen 10 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_16_coverage_unittest.py: -------------------------------------------------------------------------------- 1 | from stats import StatsList 2 | import unittest 3 | 4 | class TestMean(unittest.TestCase): 5 | def test_mean(self): 6 | self.assertEqual(StatsList([1,2,2,3,3,4]).mean(), 2.5) 7 | 8 | if __name__ == "__main__": 9 | unittest.main() 10 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_16_singleton_using_new.py: -------------------------------------------------------------------------------- 1 | class OneOnly: 2 | _singleton = None 3 | def __new__(cls, *args, **kwargs): 4 | if not cls._singleton: 5 | cls._singleton = super(OneOnly, cls).__new__( 6 | cls, *args, **kwargs) 7 | return cls._singleton 8 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_12_window_command_function.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Window: 4 | def exit(self): 5 | sys.exit(0) 6 | 7 | class MenuItem: 8 | def click(self): 9 | self.command() 10 | 11 | window = Window() 12 | menu_item = MenuItem() 13 | menu_item.command = window.exit 14 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_20_validation_function.py: -------------------------------------------------------------------------------- 1 | def get_valid_input(input_string, valid_options): 2 | input_string += " ({}) ".format(", ".join(valid_options)) 3 | response = input(input_string) 4 | while response.lower() not in valid_options: 5 | response = input(input_string) 6 | return response 7 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_04_pytho_ugly_as_java.py: -------------------------------------------------------------------------------- 1 | class Color: 2 | def __init__(self, rgb_value, name): 3 | self._rgb_value = rgb_value 4 | self._name = name 5 | 6 | def set_name(self, name): 7 | self._name = name 8 | 9 | def get_name(self): 10 | return self._name 11 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_15_log_delete_warnings_loop.py: -------------------------------------------------------------------------------- 1 | import sys 2 | inname, outname = sys.argv[1:3] 3 | 4 | with open(inname) as infile: 5 | with open(outname, "w") as outfile: 6 | for l in infile: 7 | if 'WARNING' in l: 8 | outfile.write(l.replace('\tWARNING', '')) 9 | 10 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_14_oop_pairs.py: -------------------------------------------------------------------------------- 1 | c = a + b 2 | c = a.add(b) 3 | 4 | l[0] = 5 5 | l.insert(0, 5) 6 | 7 | d[key] = value 8 | d.setitem(key, value) 9 | 10 | for x in alist: 11 | #do something with x 12 | it = alist.iterator() 13 | while it.has_next(): 14 | x = it.next() 15 | #do something with x 16 | 17 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_01_simplest_unittest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | class CheckNumbers(unittest.TestCase): 4 | def test_int_float(self): 5 | self.assertEquals(1, 1.0) 6 | 7 | def test_str_float(self): 8 | self.assertEquals(1, "1") 9 | 10 | if __name__ == "__main__": 11 | unittest.main() 12 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_11_friend_multi.py: -------------------------------------------------------------------------------- 1 | class Friend(Contact, AddressHolder): 2 | def __init__(self, name, email, phone, 3 | street, city, state, code): 4 | Contact.__init__(self, name, email) 5 | AddressHolder.__init__( 6 | self, street, city, state, code) 7 | self.phone = phone 8 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_05_catch_specific_exception.py: -------------------------------------------------------------------------------- 1 | def funny_division(anumber): 2 | try: 3 | return 100 / anumber 4 | except ZeroDivisionError: 5 | return "Silly wabbit, you can't divide by zero!" 6 | 7 | print(funny_division(0)) 8 | print(funny_division(50.0)) 9 | print(funny_division("hello")) 10 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_13_log_processor.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | inname = sys.argv[1] 4 | outname = sys.argv[2] 5 | 6 | with open(inname) as infile: 7 | with open(outname, "w") as outfile: 8 | warnings = (l for l in infile if 'WARNING' in l) 9 | for l in warnings: 10 | outfile.write(l) 11 | 12 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_01_even_integers.py: -------------------------------------------------------------------------------- 1 | class EvenOnly(list): 2 | def append(self, integer): 3 | if not isinstance(integer, int): 4 | raise TypeError("Only integers can be added") 5 | if integer % 2: 6 | raise ValueError("Only even numbers can be added") 7 | super().append(integer) 8 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_17_ducktype_flac.py: -------------------------------------------------------------------------------- 1 | class FlacFile: 2 | def __init__(self, filename): 3 | if not filename.endswith(".flac"): 4 | raise Exception("Invalid file format") 5 | 6 | self.filename = filename 7 | 8 | def play(self): 9 | print("playing {} as flac movie".format(self.filename)) 10 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_18_normalize_url.py: -------------------------------------------------------------------------------- 1 | def normalize_url(self, path, link): 2 | if link.startswith("http://"): 3 | return link 4 | elif link.startswith("/"): 5 | return self.url + link 6 | else: 7 | return self.url + path.rpartition('/' 8 | )[0] + '/' + link 9 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_19_link_downloader.py: -------------------------------------------------------------------------------- 1 | from collections import Iterable 2 | 3 | def get_pages(links): 4 | if not isinstance(links, Iterable) or isinstance( 5 | links, (bytes, str)): 6 | links = [links] 7 | for link in links: 8 | #download the link with urllib 9 | print(link) 10 | 11 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_12-main-example.py: -------------------------------------------------------------------------------- 1 | class UsefulClass: 2 | '''This class might be useful to other modules.''' 3 | pass 4 | 5 | def main(): 6 | '''creates a useful class and does something with it for our module.''' 7 | useful = UsefulClass() 8 | print(useful) 9 | 10 | if __name__ == "__main__": 11 | main() 12 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_20-notebook_modify_sanity_check.py: -------------------------------------------------------------------------------- 1 | def modify_memo(self, note_id, memo): 2 | '''Find the note with the given id and change its 3 | memo to the given value.''' 4 | note = self._find_note(note_id) 5 | if note: 6 | note.memo = memo 7 | return True 8 | return False 9 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_07-initialization_function.py: -------------------------------------------------------------------------------- 1 | class Point: 2 | def __init__(self, x, y): 3 | self.move(x, y) 4 | 5 | def move(self, x, y): 6 | self.x = x 7 | self.y = y 8 | 9 | def reset(self): 10 | self.move(0, 0) 11 | 12 | # Constructing a Point 13 | point = Point(3, 5) 14 | print(point.x, point.y) 15 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | I can be contacted in lots of ways. Here are some links: 4 | 5 | My Blog 6 | Home 7 | Contact 8 | Dad's books 9 | 10 | 11 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_23_stringio.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from io import StringIO, BytesIO 3 | source_file = StringIO("an oft-repeated cliché") 4 | dest_file = BytesIO() 5 | 6 | char = source_file.read(1) 7 | while char: 8 | dest_file.write(char.encode("ascii", "replace")) 9 | char = source_file.read(1) 10 | 11 | print(dest_file.getvalue()) 12 | 13 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_14_log_delete_warning_expression.py: -------------------------------------------------------------------------------- 1 | import sys 2 | inname, outname = sys.argv[1:3] 3 | 4 | with open(inname) as infile: 5 | with open(outname, "w") as outfile: 6 | warnings = (l.replace('\tWARNING', '') 7 | for l in infile if 'WARNING' in l) 8 | for l in warnings: 9 | outfile.write(l) 10 | 11 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_04_try_except.py: -------------------------------------------------------------------------------- 1 | def no_return(): 2 | print("I am about to raise an exception") 3 | raise Exception("This is always raised") 4 | print("This line will never execute") 5 | return "I won't be returned" 6 | 7 | try: 8 | no_return() 9 | except: 10 | print("I caught an exception") 11 | print("executed after the exception") 12 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_23_unpacking_arguments.py: -------------------------------------------------------------------------------- 1 | def show_args(arg1, arg2, arg3="THREE"): 2 | print(arg1, arg2, arg3) 3 | 4 | some_args = range(3) 5 | more_args = { 6 | "arg1": "ONE", 7 | "arg2": "TWO"} 8 | 9 | print("Unpacking a sequence:", end=" ") 10 | show_args(*some_args) 11 | print("Unpacking a dict:", end=" ") 12 | show_args(**more_args) 13 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_01_distances_no_objects.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def distance(p1, p2): 4 | return math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2) 5 | 6 | def perimeter(polygon): 7 | perimeter = 0 8 | points = polygon + [polygon[0]] 9 | for i in range(len(polygon)): 10 | perimeter += distance(points[i], points[i+1]) 11 | return perimeter 12 | -------------------------------------------------------------------------------- /1261_12_Code/blog_templates/comment_form.html: -------------------------------------------------------------------------------- 1 |
3 | Name:
4 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_09_list_tuple_frequency.py: -------------------------------------------------------------------------------- 1 | import string 2 | CHARACTERS = list(string.ascii_letters) + [" "] 3 | 4 | def letter_frequency(sentence): 5 | frequencies = [(c, 0) for c in CHARACTERS] 6 | for letter in sentence: 7 | index = CHARACTERS.index(letter) 8 | frequencies[index] = (letter,frequencies[index][1] + 1) 9 | return frequencies 10 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_13_tabular.py: -------------------------------------------------------------------------------- 1 | orders = [('burger', 2, 5), 2 | ('fries', 3.5, 1), 3 | ('cola', 1.75, 3)] 4 | 5 | print("PRODUCT QUANTITY PRICE SUBTOTAL") 6 | for product, price, quantity in orders: 7 | subtotal = price * quantity 8 | print("{0:10s}{1: ^9d} ${2: <8.2f}${3: >7.2f}".format( 9 | product, quantity, price, subtotal)) 10 | 11 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_06_setting_name_in_method.py: -------------------------------------------------------------------------------- 1 | class Color: 2 | def __init__(self, rgb_value, name): 3 | self._rgb_value = rgb_value 4 | self._name = name 5 | 6 | def set_name(self, name): 7 | if not name: 8 | raise Exception("Invalid Name") 9 | self._name = name 10 | 11 | def get_name(self): 12 | return self._name 13 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_06_format_kw_args.py: -------------------------------------------------------------------------------- 1 | template = """ 2 | From: <{from_email}> 3 | To: <{to_email}> 4 | Subject: {subject} 5 | {message}""" 6 | print(template.format( 7 | from_email = "a@example.com", 8 | to_email = "b@example.com", 9 | message = "Here's some mail for you. " 10 | " Hope you enjoy the message!", 11 | subject = "You have mail!" 12 | )) 13 | 14 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_08_tuple_dict_format.py: -------------------------------------------------------------------------------- 1 | emails = ("a@example.com", "b@example.com") 2 | message = { 3 | 'subject': "You Have Mail!", 4 | 'message': "Here's some mail for you!" 5 | } 6 | template = """ 7 | From: <{0[0]}> 8 | To: <{0[1]}> 9 | Subject: {message[subject]} 10 | {message[message]}""" 11 | print(template.format(emails, message=message)) 12 | 13 | 14 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/blog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | My real blog is here if you are 4 | interested. 5 | 6 | Here are some links: 7 | The first page 8 | Some contact info 9 | All about my dog! 10 | 11 | 12 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_05_flyweight_factory.py: -------------------------------------------------------------------------------- 1 | import weakref 2 | 3 | class CarModel: 4 | _models = weakref.WeakValueDictionary() 5 | 6 | def __new__(cls, model_name, *args, **kwargs): 7 | model = cls._models.get(model_name) 8 | if not model: 9 | model = super().__new__(cls) 10 | cls._models[model_name] = model 11 | 12 | return model 13 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Contact us 4 | Blog 5 | My Dog 6 | Some hobbies 7 | Contact AGAIN 8 | Favourite OS 9 | 10 | 11 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_09_tuple_in_dict_format.py: -------------------------------------------------------------------------------- 1 | emails = ("a@example.com", "b@example.com") 2 | message = { 3 | 'emails': emails, 4 | 'subject': "You Have Mail!", 5 | 'message': "Here's some mail for you!" 6 | } 7 | template = """ 8 | From: <{0[emails][0]}> 9 | To: <{0[emails][1]}> 10 | Subject: {0[subject]} 11 | {0[message]}""" 12 | print(template.format(message)) 13 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_22_context_manager.py: -------------------------------------------------------------------------------- 1 | class StringJoiner(list): 2 | def __enter__(self): 3 | return self 4 | 5 | def __exit__(self, type, value, tb): 6 | self.result = "".join(self) 7 | 8 | import random, string 9 | with StringJoiner() as joiner: 10 | for i in range(15): 11 | joiner.append(random.choice(string.ascii_letters)) 12 | 13 | print(joiner.result) 14 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_07_friend_overrides_init_super.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | all_contacts = [] 3 | 4 | def __init__(self, name, email): 5 | self.name = name 6 | self.email = email 7 | Contact.all_contacts.append(self) 8 | 9 | class Friend(Contact): 10 | def __init__(self, name, email, phone): 11 | super().__init__(name, email) 12 | self.phone = phone 13 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_11_exception_with_custom_args.py: -------------------------------------------------------------------------------- 1 | class InvalidWithdrawal(Exception): 2 | def __init__(self, balance, amount): 3 | super().__init__("account doesn't have ${}".format( 4 | amount)) 5 | self.amount = amount 6 | self.balance = balance 7 | 8 | def overage(self): 9 | return self.amount - self.balance 10 | 11 | raise InvalidWithdrawal(25, 50) 12 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_09_window_commands.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Window: 4 | def exit(self): 5 | sys.exit(0) 6 | 7 | class Document: 8 | def __init__(self, filename): 9 | self.filename = filename 10 | self.contents = "This file cannot be modified" 11 | 12 | def save(self): 13 | with open(self.filename, 'w') as file: 14 | file.write(self.contents) 15 | -------------------------------------------------------------------------------- /1261_12_Code/blog_templates/add.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}New Entry{% endblock %} 4 | {% block content %} 5 |
6 | Title:
7 |
9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_06_friend_overrides_init.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | all_contacts = [] 3 | 4 | def __init__(self, name, email): 5 | self.name = name 6 | self.email = email 7 | Contact.all_contacts.append(self) 8 | 9 | class Friend(Contact): 10 | def __init__(self, name, email, phone): 11 | self.name = name 12 | self.email = email 13 | self.phone = phone 14 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_15_cache_getter.py: -------------------------------------------------------------------------------- 1 | from urllib.request import urlopen 2 | 3 | class WebPage: 4 | def __init__(self, url): 5 | self.url = url 6 | self._content = None 7 | 8 | @property 9 | def content(self): 10 | if not self._content: 11 | print("Retrieving New Page...") 12 | self._content = urlopen(self.url).read() 13 | return self._content 14 | -------------------------------------------------------------------------------- /1261_12_Code/blog_templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% block title %}{% endblock %} 4 | 5 |

My Blog

6 | 10 |
11 | {% block content %} 12 | {% endblock %} 13 | 14 | 15 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_24_basic_pickling.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | 3 | some_data = ["a list", "containing", 5, 4 | "values including another list", 5 | ["inner", "list"]] 6 | 7 | with open("pickled_list", 'wb') as file: 8 | pickle.dump(some_data, file) 9 | 10 | with open("pickled_list", 'rb') as file: 11 | loaded_data = pickle.load(file) 12 | 13 | print(loaded_data) 14 | assert loaded_data == some_data 15 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_11_echo_server.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 4 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 5 | s.bind(('localhost',1028)) 6 | s.listen(1) 7 | 8 | try: 9 | while True: 10 | client, address = s.accept() 11 | data = client.recv(1024) 12 | client.send(data) 13 | client.close() 14 | finally: 15 | s.close() 16 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/hobbies.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | I do tai chi, woodworking, skating, writing, and programming. 4 | 5 | My Sifu 6 | Tai Chi stuff 7 | The home page 8 | Esme is my hobby too 9 | Recent stuff 10 | 11 | 12 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_03_method_calls_excepting.py: -------------------------------------------------------------------------------- 1 | def no_return(): 2 | print("I am about to raise an exception") 3 | raise Exception("This is always raised") 4 | print("This line will never execute") 5 | return "I won't be returned" 6 | 7 | def call_exceptor(): 8 | print("call_exceptor starts here...") 9 | no_return() 10 | print("an exception was raised...") 11 | print("...so these lines don't run") 12 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_07_setting_name_property.py: -------------------------------------------------------------------------------- 1 | class Color: 2 | def __init__(self, rgb_value, name): 3 | self.rgb_value = rgb_value 4 | self._name = name 5 | 6 | def _set_name(self, name): 7 | if not name: 8 | raise Exception("Invalid Name") 9 | self._name = name 10 | 11 | def _get_name(self): 12 | return self._name 13 | 14 | name = property(_get_name, _set_name) 15 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_03_contact_inherit_supplier.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | all_contacts = [] 3 | 4 | def __init__(self, name, email): 5 | self.name = name 6 | self.email = email 7 | Contact.all_contacts.append(self) 8 | 9 | class Supplier(Contact): 10 | def order(self, order): 11 | print("If this were a real system we would send " 12 | "{} order to {}".format(order, self.name)) 13 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_06_catch_multiple_exceptions.py: -------------------------------------------------------------------------------- 1 | def funny_division2(anumber): 2 | try: 3 | if anumber == 13: 4 | raise ValueError("13 is an unlucky number") 5 | return 100 / anumber 6 | except (ZeroDivisionError, TypeError): 7 | return "Enter a number other than zero" 8 | 9 | for val in (0, "hello", 50.0, 13): 10 | print("Testing {}:".format(val), end=" ") 11 | print(funny_division2(val)) 12 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_05_tdf_processor.py: -------------------------------------------------------------------------------- 1 | import sys 2 | filename = sys.argv[1] 3 | 4 | with open(filename) as file: 5 | header = file.readline().strip().split('\t') 6 | contacts = [ 7 | dict( 8 | zip(header, line.strip().split('\t')) 9 | ) for line in file 10 | ] 11 | 12 | for contact in contacts: 13 | print("email: {email} -- {last}, {first}".format( 14 | **contact)) 15 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_17_log_delete_warnings_generator.py: -------------------------------------------------------------------------------- 1 | import sys 2 | inname, outname = sys.argv[1:3] 3 | 4 | def warnings_filter(insequence): 5 | for l in insequence: 6 | if 'WARNING' in l: 7 | yield l.replace('\tWARNING', '') 8 | 9 | with open(inname) as infile: 10 | with open(outname, "w") as outfile: 11 | filter = warnings_filter(infile) 12 | for l in filter: 13 | outfile.write(l) 14 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_12_set_operations.py: -------------------------------------------------------------------------------- 1 | my_artists = {"Sarah Brightman", "Guns N' Roses", 2 | "Opeth", "Vixy and Tony"} 3 | 4 | auburns_artists = {"Nickelback", "Guns N' Roses", 5 | "Savage Garden"} 6 | 7 | print("All: {}".format(my_artists.union(auburns_artists))) 8 | print("Both: {}".format(auburns_artists.intersection(my_artists))) 9 | print("Either but not both: {}".format( 10 | my_artists.symmetric_difference(auburns_artists))) 11 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_02_simple_socket.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | def respond(client): 4 | response = input("Enter a value: ") 5 | client.send(bytes(response, 'utf8')) 6 | client.close() 7 | 8 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 | server.bind(('localhost',2401)) 10 | server.listen(1) 11 | try: 12 | while True: 13 | client, addr = server.accept() 14 | respond(client) 15 | finally: 16 | server.close() 17 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_09_tdf_list_comp.py: -------------------------------------------------------------------------------- 1 | import sys 2 | filename = sys.argv[1] 3 | 4 | contacts = [] 5 | with open(filename) as file: 6 | header = file.readline().strip().split('\t') 7 | for line in file: 8 | line = line.strip().split('\t') 9 | contact_map = zip(header, line) 10 | contacts.append(dict(contact_map)) 11 | 12 | for contact in contacts: 13 | print("email: {email} -- {last}, {first}".format( 14 | **contact)) 15 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_17-notebook_findnote_method.py: -------------------------------------------------------------------------------- 1 | def _find_note(self, note_id): 2 | '''Locate the note with the given id.''' 3 | for note in self.notes: 4 | if note.id == note_id: 5 | return note 6 | return None 7 | 8 | def modify_memo(self, note_id, memo): 9 | '''Find the note with the given id and change its 10 | memo to the given value.''' 11 | self._find_note(note_id).memo = memo 12 | -------------------------------------------------------------------------------- /1261_06_Code/case_study_serve/esme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | I have a Cavalier King Charles Spaniel named Esme. She's named after Esme (for 4 | Esmerelda) Weatherwax, from Terry Pratchett's Discworld series. 5 | 6 | Here's some links: 7 | 8 | My hobbies 9 | Wikipedia 10 | on Cavaliers 11 | 12 | 13 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_01_age_calculator.py: -------------------------------------------------------------------------------- 1 | class AgeCalculator: 2 | def __init__(self, birthday): 3 | self.year, self.month, self.day = ( 4 | int(x) for x in birthday.split('-')) 5 | 6 | def calculate_age(self, date): 7 | year, month, day = ( 8 | int(x) for x in date.split('-')) 9 | age = year - self.year 10 | if (month,day) < (self.month,self.day): 11 | age -= 1 12 | return age 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_10_object_comparison.py: -------------------------------------------------------------------------------- 1 | class WeirdSortee: 2 | def __init__(self, string, number, sort_num): 3 | self.string = string 4 | self.number = number 5 | self.sort_num = sort_num 6 | 7 | def __lt__(self, object): 8 | if self.sort_num: 9 | return self.number < object.number 10 | return self.string < object.string 11 | 12 | def __repr__(self): 13 | return"{}:{}".format(self.string, self.number) 14 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_21_kwarg_options.py: -------------------------------------------------------------------------------- 1 | class Options: 2 | default_options = { 3 | 'port': 21, 4 | 'host': 'localhost', 5 | 'username': None, 6 | 'password': None, 7 | 'debug': False, 8 | } 9 | def __init__(self, **kwargs): 10 | self.options = dict(Options.default_options) 11 | self.options.update(kwargs) 12 | 13 | def __getitem__(self, key): 14 | return self.options[key] 15 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_27_type_map.py: -------------------------------------------------------------------------------- 1 | class Agent: 2 | type_map = { 3 | ("house", "rental"): HouseRental, 4 | ("house", "purchase"): HousePurchase, 5 | ("apartment", "rental"): ApartmentRental, 6 | ("apartment", "purchase"): ApartmentPurchase 7 | } 8 | 9 | def __init__(self): 10 | self.property_list = [] 11 | 12 | def display_properties(): 13 | for property in self.property_list: 14 | property.display() 15 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_07_html_document.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This is a web page 5 | 6 | 7 | 8 |

Welcome To My Site

9 |
10 | This is my site. It is rather lame. 11 | But it's still mine. Mine, 12 | I say. 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_13_form_arguments.py: -------------------------------------------------------------------------------- 1 | import cherrypy 2 | 3 | class ContactPage: 4 | @cherrypy.expose 5 | def index(self, message=None): 6 | if message: 7 | print("The user submitted:\n{0}".format( 8 | message)) 9 | return "Thank you!" 10 | return """
11 | 12 | 13 |
""" 14 | 15 | cherrypy.quickstart(ContactPage()) 16 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_11_property_decorator_arguments.py: -------------------------------------------------------------------------------- 1 | class Silly: 2 | @property 3 | def silly(self): 4 | "This is a silly property" 5 | print("You are getting silly") 6 | return self._silly 7 | 8 | @silly.setter 9 | def silly(self, value): 10 | print("You are making silly {}".format(value)) 11 | self._silly = value 12 | 13 | @silly.deleter 14 | def silly(self): 15 | print("Whoah, you killed silly!") 16 | del self._silly 17 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_02_assertraises_python31.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | def average(seq): 4 | return sum(seq) / len(seq) 5 | 6 | class TestAverage(unittest.TestCase): 7 | def test_python30_zero(self): 8 | self.assertRaises(ZeroDivisionError, 9 | average, 10 | []) 11 | 12 | def test_python31_zero(self): 13 | with self.assertRaises(ZeroDivisionError): 14 | average([]) 15 | 16 | if __name__ == "__main__": 17 | unittest.main() 18 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_09_etree_write_html.py: -------------------------------------------------------------------------------- 1 | from xml.etree.ElementTree import (Element, SubElement, 2 | tostring) 3 | 4 | root = Element("html") 5 | head = Element("head") 6 | root.append(head) 7 | title = SubElement(head, "title") 8 | title.text = "my page" 9 | link = SubElement(head, "link") 10 | link.attrib['rel'] = "stylesheet" 11 | link.attrib['href'] = "styles.css" 12 | body = Element("body") 13 | body.text = "This is my website." 14 | root.append(body) 15 | 16 | print(tostring(root)) 17 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_11_song_artist_set.py: -------------------------------------------------------------------------------- 1 | song_library = [("Phantom Of The Opera", "Sarah Brightman"), 2 | ("Knocking On Heaven's Door", "Guns N' Roses"), 3 | ("Captain Nemo", "Sarah Brightman"), 4 | ("Patterns In The Ivy", "Opeth"), 5 | ("November Rain", "Guns N' Roses"), 6 | ("Beautiful", "Sarah Brightman"), 7 | ("Mal's Song", "Vixy and Tony")] 8 | 9 | artists = set() 10 | for song, artist in song_library: 11 | artists.add(artist) 12 | 13 | print(artists) 14 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_08_property_arguments.py: -------------------------------------------------------------------------------- 1 | class Silly: 2 | def _get_silly(self): 3 | print("You are getting silly") 4 | return self._silly 5 | def _set_silly(self, value): 6 | print("You are making silly {}".format(value)) 7 | self._silly = value 8 | def _del_silly(self): 9 | print("Whoah, you killed silly!") 10 | del self._silly 11 | 12 | silly = property(_get_silly, _set_silly, _del_silly, 13 | "This is a silly property") 14 | 15 | 16 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_19_template_abstract_noimple.py: -------------------------------------------------------------------------------- 1 | class QueryTemplate: 2 | def connect(self): 3 | pass 4 | def construct_query(self): 5 | pass 6 | def do_query(self): 7 | pass 8 | def format_results(self): 9 | pass 10 | def output_results(self): 11 | pass 12 | 13 | def process_format(self): 14 | self.connect() 15 | self.construct_query() 16 | self.do_query() 17 | self.format_results() 18 | self.output_results() 19 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_14_simple_xml_to_parse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Dusty Phillips 4 | Packt Publishing 5 | Python 3 Object Oriented Programming 6 | 7 | 8 | 1 9 | Object Oriented Design 10 | 11 | 12 | 2 13 | Objects In Python 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_14-name_mangling.py: -------------------------------------------------------------------------------- 1 | class SecretString: 2 | '''A not-at-all secure way to store a secret string.''' 3 | 4 | def __init__(self, plain_string, pass_phrase): 5 | self.__plain_string = plain_string 6 | self.__pass_phrase = pass_phrase 7 | 8 | def decrypt(self, pass_phrase): 9 | '''Only show the string if the pass_phrase is correct.''' 10 | if pass_phrase == self.__pass_phrase: 11 | return self.__plain_string 12 | else: 13 | return '' 14 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_01_reversible_objects.py: -------------------------------------------------------------------------------- 1 | normal_list=[1,2,3,4,5] 2 | 3 | class CustomSequence(): 4 | def __len__(self): 5 | return 5 6 | 7 | def __getitem__(self, index): 8 | return "x{0}".format(index) 9 | 10 | class FunkyBackwards(CustomSequence): 11 | def __reversed__(self): 12 | return "BACKWARDS!" 13 | 14 | for seq in normal_list, CustomSequence(), FunkyBackwards(): 15 | print("\n{0}: ".format(seq.__class__.__name__), end="") 16 | for item in reversed(seq): 17 | print(item, end=", ") 18 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_09_funcargs.py: -------------------------------------------------------------------------------- 1 | from stats import StatsList 2 | 3 | def pytest_funcarg__valid_stats(request): 4 | return StatsList([1,2,2,3,3,4]) 5 | 6 | 7 | def test_mean(valid_stats): 8 | assert valid_stats.mean() == 2.5 9 | 10 | def test_median(valid_stats): 11 | assert valid_stats.median() == 2.5 12 | valid_stats.append(4) 13 | assert valid_stats.median() == 3 14 | 15 | def test_mode(valid_stats): 16 | assert valid_stats.mode() == [2,3] 17 | valid_stats.remove(2) 18 | assert valid_stats.mode() == [3] 19 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_10_object_formatting.py: -------------------------------------------------------------------------------- 1 | class EMail: 2 | def __init__(self, from_addr, to_addr, subject, message): 3 | self.from_addr = from_addr 4 | self.to_addr = to_addr 5 | self.subject = subject 6 | self.message = message 7 | 8 | email = EMail("a@example.com", "b@example.com", 9 | "You Have Mail!", 10 | "Here's some mail for you!") 11 | 12 | template = """ 13 | From: <{0.from_addr}> 14 | To: <{0.to_addr}> 15 | Subject: {0.subject} 16 | 17 | {0.message}""" 18 | print(template.format(email)) 19 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_28_Character_class.py: -------------------------------------------------------------------------------- 1 | class Character: 2 | def __init__(self, character, 3 | bold=False, italic=False, underline=False): 4 | assert len(character) == 1 5 | self.character = character 6 | self.bold = bold 7 | self.italic = italic 8 | self.underline = underline 9 | 10 | def __str__(self): 11 | bold = "*" if self.bold else '' 12 | italic = "/" if self.italic else '' 13 | underline = "_" if self.underline else '' 14 | return bold + italic + underline + self.character 15 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_01_sqlite.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | connection = sqlite3.connect("mydb.db") 3 | connection.execute( 4 | "CREATE TABLE IF NOT EXISTS " 5 | "pet (type, breed, gender, name)") 6 | connection.execute("INSERT INTO pet VALUES(" 7 | "'dog', 'spaniel', 'female', 'Esme')") 8 | connection.execute("INSERT INTO pet VALUES(" 9 | "'cat', 'persian', 'male', 'Oscar')") 10 | results = connection.execute("SELECT breed, name" 11 | " from pet where type='dog'") 12 | for result in results: 13 | print(result[1]) 14 | connection.close() 15 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_07_catch_multiple_different.py: -------------------------------------------------------------------------------- 1 | def funny_division3(anumber): 2 | try: 3 | if anumber == 13: 4 | raise ValueError("13 is an unlucky number") 5 | return 100 / anumber 6 | except ZeroDivisionError: 7 | return "Enter a number other than zero" 8 | except TypeError: 9 | return "Enter a numerical value" 10 | except ValueError: 11 | print("No, No, not 13!") 12 | raise 13 | 14 | for val in (0, "hello", 50.0, 13): 15 | print("Testing %s:" % val, end=" ") 16 | print(funny_division3(val)) 17 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_28_callable_repeat.py: -------------------------------------------------------------------------------- 1 | from timer import Timer 2 | import datetime 3 | 4 | def format_time(message, *args): 5 | now = datetime.datetime.now().strftime("%I:%M:%S") 6 | print(message.format(*args, now=now)) 7 | 8 | class Repeater: 9 | def __init__(self): 10 | self.count = 0 11 | def __call__(self, timer): 12 | format_time("{now}: repeat {0}", self.count) 13 | self.count += 1 14 | timer.call_after(5, self) 15 | 16 | timer = Timer() 17 | timer.call_after(5, Repeater()) 18 | format_time("{now}: Starting") 19 | timer.run() 20 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_12_handle_custom_exception.py: -------------------------------------------------------------------------------- 1 | class InvalidWithdrawal(Exception): 2 | def __init__(self, balance, amount): 3 | super().__init__("account doesn't have ${}".format( 4 | amount)) 5 | self.amount = amount 6 | self.balance = balance 7 | 8 | def overage(self): 9 | return self.amount - self.balance 10 | 11 | try: 12 | raise InvalidWithdrawal(25, 50) 13 | except InvalidWithdrawal as e: 14 | print("I'm sorry, but your withdrawal is " 15 | "more than your balance by " 16 | "${}".format(e.overage())) 17 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_10_funcarg_finalizer.py: -------------------------------------------------------------------------------- 1 | import tempfile 2 | import shutil 3 | import os.path 4 | 5 | def pytest_funcarg__temp_dir(request): 6 | dir = tempfile.mkdtemp() 7 | print(dir) 8 | 9 | def cleanup(): 10 | shutil.rmtree(dir) 11 | request.addfinalizer(cleanup) 12 | return dir 13 | 14 | def test_osfiles(temp_dir): 15 | os.mkdir(os.path.join(temp_dir, 'a')) 16 | os.mkdir(os.path.join(temp_dir, 'b')) 17 | dir_contents = os.listdir(temp_dir) 18 | assert len(dir_contents) == 2 19 | assert 'a' in dir_contents 20 | assert 'b' in dir_contents 21 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_04_contact_list_inheritance.py: -------------------------------------------------------------------------------- 1 | class ContactList(list): 2 | def search(self, name): 3 | '''Return all contacts that contain the search value 4 | in their name.''' 5 | matching_contacts = [] 6 | for contact in self: 7 | if name in contact.name: 8 | matching_contacts.append(contact) 9 | return matching_contacts 10 | 11 | class Contact: 12 | all_contacts = ContactList() 13 | 14 | def __init__(self, name, email): 15 | self.name = name 16 | self.email = email 17 | self.all_contacts.append(self) 18 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_29_send_email.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | from email.mime.text import MIMEText 3 | 4 | def send_email(subject, message, from_addr, *to_addrs, 5 | host="localhost", port=1025, **headers): 6 | 7 | email = MIMEText(message) 8 | email['Subject'] = subject 9 | email['From'] = from_addr 10 | for header, value in headers.items(): 11 | email[header] = value 12 | 13 | sender = smtplib.SMTP(host, port) 14 | for addr in to_addrs: 15 | del email['To'] 16 | email['To'] = addr 17 | sender.sendmail(from_addr, addr, email.as_string()) 18 | sender.quit() 19 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_03_age_calculator_adapt_date.py: -------------------------------------------------------------------------------- 1 | class AgeCalculator: 2 | def __init__(self, birthday): 3 | self.year, self.month, self.day = ( 4 | int(x) for x in birthday.split('-')) 5 | 6 | def calculate_age(self, date): 7 | year, month, day = ( 8 | int(x) for x in date.split('-')) 9 | age = year - self.year 10 | if (month,day) < (self.month,self.day): 11 | age -= 1 12 | return age 13 | 14 | import datetime 15 | class AgeableDate(datetime.date): 16 | def split(self, char): 17 | return self.year, self.month, self.day 18 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_09_finally_and_else.py: -------------------------------------------------------------------------------- 1 | import random 2 | some_exceptions = [ValueError, TypeError, IndexError, None] 3 | 4 | try: 5 | choice = random.choice(some_exceptions) 6 | print("raising {}".format(choice)) 7 | if choice: 8 | raise choice("An error") 9 | except ValueError: 10 | print("Caught a ValueError") 11 | except TypeError: 12 | print("Caught a TypeError") 13 | except Exception as e: 14 | print("Caught some other error: %s" % e.__class__.__name__) 15 | else: 16 | print("This code called if there is no exception") 17 | finally: 18 | print("This cleanup code is always called") 19 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_13_branching_vs_exceptions.py: -------------------------------------------------------------------------------- 1 | def divide_with_exception(number, divisor): 2 | try: 3 | print("{} / {} = {}".format( 4 | number, divisor, number / divisor * 1.0)) 5 | except ZeroDivisionError: 6 | print("You can't divide by zero") 7 | 8 | def divide_with_if(number, divisor): 9 | if divisor == 0: 10 | print("You can't divide by zero") 11 | else: 12 | print("{} / {} = {}".format( 13 | number, divisor, number / divisor * 1.0)) 14 | 15 | divide_with_exception(10, 5) 16 | divide_with_if(10, 5) 17 | divide_with_if(10, 0) 18 | divide_with_exception(10, 0) 19 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_17_link_parser.py: -------------------------------------------------------------------------------- 1 | from urllib.request import urlopen 2 | from urllib.parse import urlparse 3 | import re 4 | import sys 5 | LINK_REGEX = re.compile( 6 | "]*href=['\"]([^'\"]+)['\"][^>]*>") 7 | 8 | class LinkCollector: 9 | def __init__(self, url): 10 | self.url = "http://" + urlparse(url).netloc 11 | 12 | def collect_links(self, path="/"): 13 | full_url = self.url + path 14 | page = str(urlopen(full_url).read()) 15 | links = LINK_REGEX.findall(page) 16 | print(links) 17 | 18 | if __name__ == "__main__": 19 | LinkCollector(sys.argv[1]).collect_links() 20 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_20_scaleimage_inheritance.py: -------------------------------------------------------------------------------- 1 | from zip_processor import ZipProcessor 2 | import os 3 | import sys 4 | from pygame import image 5 | from pygame.transform import scale 6 | 7 | class ScaleZip(ZipProcessor): 8 | 9 | def process_files(self): 10 | '''Scale each image in the directory to 640x480''' 11 | for filename in os.listdir(self.temp_directory): 12 | im = image.load(self._full_filename(filename)) 13 | scaled = scale(im, (640,480)) 14 | image.save(scaled, self._full_filename(filename)) 15 | 16 | if __name__ == "__main__": 17 | ScaleZip(*sys.argv[1:4]).process_zip() 18 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_24_most_basic_document.py: -------------------------------------------------------------------------------- 1 | class Document: 2 | def __init__(self): 3 | self.characters = [] 4 | self.cursor = 0 5 | self.filename = '' 6 | 7 | def insert(self, character): 8 | self.characters.insert(self.cursor, character) 9 | self.cursor += 1 10 | 11 | def delete(self): 12 | del self.characters[self.cursor] 13 | 14 | def save(self): 15 | f = open(self.filename, 'w') 16 | f.write(''.join(self.characters)) 17 | f.close() 18 | 19 | def forward(self): 20 | self.cursor += 1 21 | 22 | def back(self): 23 | self.cursor -= 1 24 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_13_set_operations2.py: -------------------------------------------------------------------------------- 1 | my_artists = {"Sarah Brightman", "Guns N' Roses", 2 | "Opeth", "Vixy and Tony"} 3 | 4 | bands = {"Guns N' Roses", "Opeth"} 5 | 6 | print("my_artists is to bands:") 7 | print("issuperset: {}".format(my_artists.issuperset(bands))) 8 | print("issubset: {}".format(my_artists.issubset(bands))) 9 | print("difference: {}".format(my_artists.difference(bands))) 10 | print("*"*20) 11 | print("bands is to my_artists:") 12 | print("issuperset: {}".format(bands.issuperset(my_artists))) 13 | print("issubset: {}".format(bands.issubset(my_artists))) 14 | print("difference: {}".format(bands.difference(my_artists))) 15 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_12_log_file.log: -------------------------------------------------------------------------------- 1 | Jan 26, 2010 11:25:25 DEBUG This is a debugging message. 2 | Jan 26, 2010 11:25:36 INFO This is an information method. 3 | Jan 26, 2010 11:25:46 WARNING This is a warning. It could be serious. 4 | Jan 26, 2010 11:25:52 WARNING Another warning sent. 5 | Jan 26, 2010 11:25:59 INFO Here's some information. 6 | Jan 26, 2010 11:26:13 DEBUG Debug messages are only useful if you want to figure something out. 7 | Jan 26, 2010 11:26:32 INFO Information is usually harmless, but helpful. 8 | Jan 26, 2010 11:26:40 WARNING Warnings should be heeded. 9 | Jan 26, 2010 11:26:54 WARNING Watch for warnings. 10 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_13-class_in_function.py: -------------------------------------------------------------------------------- 1 | def format_string(string, formatter=None): 2 | '''Format a string using the formatter object, which 3 | is expected to have a format() method that accepts 4 | a string.''' 5 | class DefaultFormatter: 6 | '''Format a string in title case.''' 7 | def format(self, string): 8 | return str(string).title() 9 | 10 | if not formatter: 11 | formatter = DefaultFormatter() 12 | 13 | return formatter.format(string) 14 | 15 | hello_string = "hello world, how are you today?" 16 | print(" input: " + hello_string) 17 | print("output: " + format_string(hello_string)) 18 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_05_random_key_dict.py: -------------------------------------------------------------------------------- 1 | random_keys = {} 2 | random_keys['astring'] = 'somestring' 3 | random_keys[5] = 'aninteger' 4 | random_keys[25.2] = 'floats work too' 5 | random_keys[("abc", 123)] = 'so do tuples' 6 | 7 | class AnObject: 8 | def __init__(self, avalue): 9 | self.avalue = avalue 10 | 11 | my_object = AnObject(14) 12 | random_keys[my_object] = "We can even store objects" 13 | my_object.avalue = 12 14 | try: 15 | random_keys[[1,2,3]] = "we can't store lists though" 16 | except: 17 | print("unable to store list\n") 18 | 19 | for key, value in random_keys.items(): 20 | print("{} has value {}".format(key, value)) 21 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_10_set_comprehension.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | Book = namedtuple("Book", "author title genre") 4 | books = [ 5 | Book("Pratchett", "Nightwatch", "fantasy"), 6 | Book("Pratchett", "Thief Of Time", "fantasy"), 7 | Book("Le Guin", "The Dispossessed", "scifi"), 8 | Book("Le Guin", "A Wizard Of Earthsea", "fantasy"), 9 | Book("Turner", "The Thief", "fantasy"), 10 | Book("Phillips", "Preston Diamond", "western"), 11 | Book("Phillips", "Twice Upon A Time", "scifi"), 12 | ] 13 | 14 | fantasy_authors = { 15 | b.author for b in books if b.genre == 'fantasy'} 16 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_11_dict_comprehension.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | Book = namedtuple("Book", "author title genre") 4 | books = [ 5 | Book("Pratchett", "Nightwatch", "fantasy"), 6 | Book("Pratchett", "Thief Of Time", "fantasy"), 7 | Book("Le Guin", "The Dispossessed", "scifi"), 8 | Book("Le Guin", "A Wizard Of Earthsea", "fantasy"), 9 | Book("Turner", "The Thief", "fantasy"), 10 | Book("Phillips", "Preston Diamond", "western"), 11 | Book("Phillips", "Twice Upon A Time", "scifi"), 12 | ] 13 | 14 | fantasy_titles = { 15 | b.title: b for b in books if b.genre == 'fantasy'} 16 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_16_polymorphic_audio.py: -------------------------------------------------------------------------------- 1 | class AudioFile: 2 | def __init__(self, filename): 3 | if not filename.endswith(self.ext): 4 | raise Exception("Invalid file format") 5 | 6 | self.filename = filename 7 | 8 | class MP3File(AudioFile): 9 | ext = "mp3" 10 | def play(self): 11 | print("playing {} as mp3".format(self.filename)) 12 | 13 | class WavFile(AudioFile): 14 | ext = "wav" 15 | def play(self): 16 | print("playing {} as wav".format(self.filename)) 17 | 18 | class OggFile(AudioFile): 19 | ext = "ogg" 20 | def play(self): 21 | print("playing {} as ogg".format(self.filename)) 22 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_04_tkinter_dice.py: -------------------------------------------------------------------------------- 1 | import tkinter 2 | import random 3 | 4 | class DiceFrame(tkinter.Frame): 5 | def __init__(self, master): 6 | super().__init__(master) 7 | 8 | die = tkinter.Button(self, 9 | text = "Roll!", 10 | command=self.roll) 11 | die.pack() 12 | self.roll_result = tkinter.StringVar() 13 | label = tkinter.Label(self, 14 | textvariable=self.roll_result) 15 | label.pack() 16 | self.pack() 17 | 18 | def roll(self): 19 | self.roll_result.set(random.randint(1, 6)) 20 | 21 | root = tkinter.Tk() 22 | DiceFrame(master=root).mainloop() 23 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_15_inventory_handling.py: -------------------------------------------------------------------------------- 1 | class Inventory: 2 | def lock(self, item_type): 3 | pass 4 | 5 | def unlock(self, item_type): 6 | pass 7 | 8 | def purchase(self, item_type): 9 | pass 10 | 11 | item_type = 'widget' 12 | inv = Inventory() 13 | inv.lock(item_type) 14 | try: 15 | num_left = inv.purchase(item_type) 16 | except InvalidItemType: 17 | print("Sorry, we don't sell {}".format(item_type)) 18 | except OutOfStock: 19 | print("Sorry, that item is out of stock.") 20 | else: 21 | print("Purchase complete. There are " 22 | "{} {}s left".format(num_left, item_type)) 23 | finally: 24 | inv.unlock() 25 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_16_composite_folder_methods.py: -------------------------------------------------------------------------------- 1 | class Folder: 2 | def __init__(self, name): 3 | self.name = name 4 | self.children = {} 5 | 6 | def add_child(self, child): 7 | pass 8 | 9 | def move(self, new_path): 10 | pass 11 | 12 | def copy(self, new_path): 13 | pass 14 | 15 | def delete(self): 16 | pass 17 | 18 | class File: 19 | def __init__(self, name, contents): 20 | self.name = name 21 | self.contents = contents 22 | 23 | def move(self, new_path): 24 | pass 25 | 26 | def copy(self, new_path): 27 | pass 28 | 29 | def delete(self): 30 | pass 31 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_02_distances_by_object.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Point: 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distance(self, p2): 9 | return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2) 10 | 11 | class Polygon: 12 | def __init__(self): 13 | self.vertices = [] 14 | 15 | def add_point(self, point): 16 | self.vertices.append((point)) 17 | 18 | def perimeter(self): 19 | perimeter = 0 20 | points = self.vertices + [self.vertices[0]] 21 | for i in range(len(self.vertices)): 22 | perimeter += points[i].distance(points[i+1]) 23 | return perimeter 24 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_24_function_object.py: -------------------------------------------------------------------------------- 1 | def my_function(): 2 | print("The Function Was Called") 3 | my_function.description = "A silly function" 4 | 5 | def second_function(): 6 | print("The second was called") 7 | second_function.description = "A sillier function." 8 | 9 | def another_function(function): 10 | print("The description:", end=" ") 11 | print(function.description) 12 | print("The name:", end=" ") 13 | print(function.__name__) 14 | print("The class:", end=" ") 15 | print(function.__class__) 16 | print("Now I'll call the function passed in") 17 | function() 18 | 19 | another_function(my_function) 20 | another_function(second_function) 21 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_30_send_email_dict_headers.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | from email.mime.text import MIMEText 3 | 4 | def send_email(subject, message, from_addr, *to_addrs, 5 | host="localhost", port=1025, headers=None): 6 | 7 | headers = {} if headers is None else headers 8 | 9 | email = MIMEText(message) 10 | email['Subject'] = subject 11 | email['From'] = from_addr 12 | for header, value in headers.items(): 13 | email[header] = value 14 | 15 | sender = smtplib.SMTP(host, port) 16 | for addr in to_addrs: 17 | del email['To'] 18 | email['To'] = addr 19 | sender.sendmail(from_addr, addr, email.as_string()) 20 | sender.quit() 21 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_04_test_stats.py: -------------------------------------------------------------------------------- 1 | from stats import StatsList 2 | import unittest 3 | 4 | class TestValidInputs(unittest.TestCase): 5 | def setUp(self): 6 | self.stats = StatsList([1,2,2,3,3,4]) 7 | 8 | def test_mean(self): 9 | self.assertEqual(self.stats.mean(), 2.5) 10 | 11 | def test_median(self): 12 | self.assertEqual(self.stats.median(), 2.5) 13 | self.stats.append(4) 14 | self.assertEqual(self.stats.median(), 3) 15 | 16 | def test_mode(self): 17 | self.assertEqual(self.stats.mode(), [2,3]) 18 | self.stats.remove(2) 19 | self.assertEqual(self.stats.mode(), [3]) 20 | 21 | if __name__ == "__main__": 22 | unittest.main() 23 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_16_log_delete_warnings_object.py: -------------------------------------------------------------------------------- 1 | import sys 2 | inname, outname = sys.argv[1:3] 3 | 4 | class WarningFilter: 5 | def __init__(self, insequence): 6 | self.insequence = insequence 7 | def __iter__(self): 8 | return self 9 | def __next__(self): 10 | l = self.insequence.readline() 11 | while l and 'WARNING' not in l: 12 | l = self.insequence.readline() 13 | if not l: 14 | raise StopIteration 15 | return l.replace('\tWARNING', '') 16 | 17 | with open(inname) as infile: 18 | with open(outname, "w") as outfile: 19 | filter = WarningFilter(infile) 20 | for l in filter: 21 | outfile.write(l) 22 | 23 | -------------------------------------------------------------------------------- /1261_11_Code/stats.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class StatsList(list): 4 | def mean(self): 5 | return sum(self) / len(self) 6 | 7 | def median(self): 8 | if len(self) % 2: 9 | return self[int(len(self) / 2)] 10 | else: 11 | idx = int(len(self) / 2) 12 | return (self[idx] + self[idx-1]) / 2 13 | 14 | def mode(self): 15 | freqs = defaultdict(int) 16 | for item in self: 17 | freqs[item] += 1 18 | mode_freq = max(freqs.values()) 19 | modes = [] 20 | for item, value in freqs.items(): 21 | if value == mode_freq: 22 | modes.append(item) 23 | return modes 24 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_03_stats.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | class StatsList(list): 4 | def mean(self): 5 | return sum(self) / len(self) 6 | 7 | def median(self): 8 | if len(self) % 2: 9 | return self[int(len(self) / 2)] 10 | else: 11 | idx = int(len(self) / 2) 12 | return (self[idx] + self[idx-1]) / 2 13 | 14 | def mode(self): 15 | freqs = defaultdict(int) 16 | for item in self: 17 | freqs[item] += 1 18 | mode_freq = max(freqs.values()) 19 | modes = [] 20 | for item, value in freqs.items(): 21 | if value == mode_freq: 22 | modes.append(item) 23 | return modes 24 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_13_document_command_callable.py: -------------------------------------------------------------------------------- 1 | class Document: 2 | def __init__(self, filename): 3 | self.filename = filename 4 | self.contents = "This file cannot be modified" 5 | 6 | def save(self): 7 | with open(self.filename, 'w') as file: 8 | file.write(self.contents) 9 | 10 | class KeyboardShortcut: 11 | def keypress(self): 12 | self.command() 13 | 14 | class SaveCommand: 15 | def __init__(self, document): 16 | self.document = document 17 | 18 | def __call__(self): 19 | self.document.save() 20 | 21 | document = Document("a_file.txt") 22 | shortcut = KeyboardShortcut() 23 | save_command = SaveCommand(document) 24 | shortcut.command = save_command 25 | -------------------------------------------------------------------------------- /1261_12_Code/blog_templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}My Blog{% endblock %} 4 | {% block content %} 5 | {% for article in articles %} 6 |

{{article.title}}

7 | {{article.pub_date.strftime('%b %d %Y')}} 8 |

{{article.message}}

9 |
10 |

Comments

11 | {% for comment in article.comments %} 12 | {{comment.name}} wrote: 13 |

14 | {{comment.message}} 15 |

16 | {% endfor %} 17 | {% include "comment_form.html" %} 18 |
19 |
20 | {% endfor %} 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_05_skipping_tests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | 4 | class SkipTests(unittest.TestCase): 5 | @unittest.expectedFailure 6 | def test_fails(self): 7 | self.assertEqual(False, True) 8 | 9 | @unittest.skip("Test is useless") 10 | def test_skip(self): 11 | self.assertEqual(False, True) 12 | 13 | @unittest.skipIf(sys.version_info.minor == 1, 14 | "broken on 3.1") 15 | def test_skipif(self): 16 | self.assertEqual(False, True) 17 | 18 | @unittest.skipUnless(sys.platform.startswith('linux'), 19 | "broken on linux") 20 | def test_skipunless(self): 21 | self.assertEqual(False, True) 22 | 23 | if __name__ == "__main__": 24 | unittest.main() 25 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_15_friend_multi_super.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | all_contacts = [] 3 | 4 | def __init__(self, name='', email='', **kwargs): 5 | super().__init__(**kwargs) 6 | self.name = name 7 | self.email = email 8 | self.all_contacts.append(self) 9 | 10 | class AddressHolder: 11 | def __init__(self, street='', city='', state='', code='', **kwargs): 12 | super().__init__(**kwargs) 13 | self.street = street 14 | self.city = city 15 | self.state = state 16 | self.code = code 17 | 18 | class Friend(Contact, AddressHolder): 19 | def __init__(self, phone='', **kwargs): 20 | print(kwargs) 21 | super().__init__(**kwargs) 22 | self.phone = phone 23 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_25_remaining_subclasses.py: -------------------------------------------------------------------------------- 1 | class ApartmentRental(Rental, Apartment): 2 | def prompt_init(): 3 | init = Apartment.prompt_init() 4 | init.update(Rental.prompt_init()) 5 | return init 6 | prompt_init = staticmethod(prompt_init) 7 | 8 | class ApartmentPurchase(Purchase, Apartment): 9 | def prompt_init(): 10 | init = Apartment.prompt_init() 11 | init.update(Purchase.prompt_init()) 12 | return init 13 | prompt_init = staticmethod(prompt_init) 14 | 15 | class HousePurchase(Purchase, House): 16 | def prompt_init(): 17 | init = House.prompt_init() 18 | init.update(Purchase.prompt_init()) 19 | return init 20 | prompt_init = staticmethod(prompt_init) 21 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_06-methods_with_arguments.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Point: 4 | def move(self, x, y): 5 | self.x = x 6 | self.y = y 7 | def reset(self): 8 | self.move(0, 0) 9 | def calculate_distance(self, other_point): 10 | return math.sqrt( 11 | (self.x - other_point.x)**2 + 12 | (self.y - other_point.y)**2) 13 | 14 | 15 | # how to use it: 16 | point1 = Point() 17 | point2 = Point() 18 | 19 | point1.reset() 20 | point2.move(5,0) 21 | print(point2.calculate_distance(point1)) 22 | assert (point2.calculate_distance(point1) == 23 | point1.calculate_distance(point2)) 24 | point1.move(3,4) 25 | print(point1.calculate_distance(point2)) 26 | print(point1.calculate_distance(point1)) 27 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_25_document_cursor.py: -------------------------------------------------------------------------------- 1 | class Cursor: 2 | def __init__(self, document): 3 | self.document = document 4 | self.position = 0 5 | 6 | def forward(self): 7 | self.position += 1 8 | 9 | def back(self): 10 | self.position -= 1 11 | 12 | def home(self): 13 | while self.document.characters[ 14 | self.position-1] != '\n': 15 | self.position -= 1 16 | if self.position == 0: 17 | # Got to beginning of file before newline 18 | break 19 | 20 | def end(self): 21 | while self.position < len(self.document.characters 22 | ) and self.document.characters[self.position] != '\n': 23 | self.position += 1 24 | 25 | 26 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_04_logging_decorator.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class LogSocket: 4 | def __init__(self, socket): 5 | self.socket = socket 6 | 7 | def send(self, data): 8 | print("Sending {0} to {1}".format( 9 | data, self.socket.getpeername()[0])) 10 | self.socket.send(data) 11 | 12 | def close(self): 13 | self.socket.close() 14 | 15 | def respond(client): 16 | response = input("Enter a value: ") 17 | client.send(bytes(response, 'utf8')) 18 | client.close() 19 | 20 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 21 | server.bind(('',2401)) 22 | server.listen(1) 23 | try: 24 | while True: 25 | client, addr = server.accept() 26 | respond(LogSocket(client)) 27 | finally: 28 | server.close() 29 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_09_logging_decorator.py: -------------------------------------------------------------------------------- 1 | import time 2 | def log_calls(func): 3 | def wrapper(*args, **kwargs): 4 | now = time.time() 5 | print("Calling {0} with {1} and {2}".format( 6 | func.__name__, args, kwargs)) 7 | return_value = func(*args, **kwargs) 8 | print("Executed {0} in {1}ms".format( 9 | func.__name__, time.time() - now)) 10 | return return_value 11 | return wrapper 12 | 13 | def test1(a,b,c): 14 | print("\ttest1 called") 15 | 16 | def test2(a,b): 17 | print("\ttest2 called") 18 | 19 | def test3(a,b): 20 | print("\ttest3 called") 21 | time.sleep(1) 22 | 23 | test1 = log_calls(test1) 24 | test2 = log_calls(test2) 25 | test3 = log_calls(test3) 26 | 27 | test1(1,2,3) 28 | test2(4,b=5) 29 | test3(6,7) 30 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_26_json_objects.py: -------------------------------------------------------------------------------- 1 | class Contact: 2 | def __init__(self, first, last): 3 | self.first = first 4 | self.last = last 5 | 6 | @property 7 | def full_name(self): 8 | return("{} {}".format(self.first, self.last)) 9 | 10 | 11 | import json 12 | class ContactEncoder(json.JSONEncoder): 13 | def default(self, obj): 14 | if isinstance(obj, Contact): 15 | return {'is_contact': True, 16 | 'first': obj.first, 17 | 'last': obj.last, 18 | 'full': obj.full_name} 19 | return super().default(obj) 20 | 21 | def decode_contact(dic): 22 | if dic.get('is_contact'): 23 | return Contact(dic['first'], dic['last']) 24 | else: 25 | return dic 26 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_11_observer_core.py: -------------------------------------------------------------------------------- 1 | class Inventory: 2 | def __init__(self): 3 | self.observers = [] 4 | self._product = None 5 | self._quantity = 0 6 | 7 | def attach(self, observer): 8 | self.observers.append(observer) 9 | 10 | @property 11 | def product(self): 12 | return self._product 13 | @product.setter 14 | def product(self, value): 15 | self._product = value 16 | self._update_observers() 17 | 18 | @property 19 | def quantity(self): 20 | return self._quantity 21 | @quantity.setter 22 | def quantity(self, value): 23 | self._quantity = value 24 | self._update_observers() 25 | 26 | def _update_observers(self): 27 | for observer in self.observers: 28 | observer() 29 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_14_contrived_diamond_super.py: -------------------------------------------------------------------------------- 1 | class BaseClass: 2 | num_base_calls = 0 3 | def call_me(self): 4 | print("Calling method on Base Class") 5 | self.num_base_calls += 1 6 | 7 | class LeftSubclass(BaseClass): 8 | num_left_calls = 0 9 | def call_me(self): 10 | super().call_me() 11 | print("Calling method on Left Subclass") 12 | self.num_left_calls += 1 13 | 14 | class RightSubclass(BaseClass): 15 | num_right_calls = 0 16 | def call_me(self): 17 | super().call_me() 18 | print("Calling method on Right Subclass") 19 | self.num_right_calls += 1 20 | 21 | class Subclass(LeftSubclass, RightSubclass): 22 | num_sub_calls = 0 23 | def call_me(self): 24 | super().call_me() 25 | print("Calling method on Subclass") 26 | self.num_sub_calls += 1 27 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_03_object_polygon_init.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Point: 4 | def __init__(self, x, y): 5 | self.x = x 6 | self.y = y 7 | 8 | def distance(self, p2): 9 | return math.sqrt((self.x-p2.x)**2 + (self.y-p2.y)**2) 10 | 11 | class Polygon: 12 | def __init__(self, points = []): 13 | self.vertices = [] 14 | for point in points: 15 | if isinstance(point, tuple): 16 | point = Point(*point) 17 | self.vertices.append(point) 18 | 19 | def add_point(self, point): 20 | self.vertices.append((point)) 21 | 22 | def perimeter(self): 23 | perimeter = 0 24 | points = self.vertices + [self.vertices[0]] 25 | for i in range(len(self.vertices)): 26 | perimeter += points[i].distance(points[i+1]) 27 | return perimeter 28 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_02_age_calculator_adapted.py: -------------------------------------------------------------------------------- 1 | class AgeCalculator: 2 | def __init__(self, birthday): 3 | self.year, self.month, self.day = ( 4 | int(x) for x in birthday.split('-')) 5 | 6 | def calculate_age(self, date): 7 | year, month, day = ( 8 | int(x) for x in date.split('-')) 9 | age = year - self.year 10 | if (month,day) < (self.month,self.day): 11 | age -= 1 12 | return age 13 | 14 | class DateAgeAdapter: 15 | def _str_date(self, date): 16 | return date.strftime("%Y-%m-%d") 17 | 18 | def __init__(self, birthday): 19 | birthday = self._str_date(birthday) 20 | self.calculator = AgeCalculator(birthday) 21 | 22 | def get_age(self, date): 23 | date = self._str_date(date) 24 | return self.calculator.calculate_age(date) 25 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_18_property.py: -------------------------------------------------------------------------------- 1 | class Property: 2 | def __init__(self, square_feet='', beds='', 3 | baths='', **kwargs): 4 | super().__init__(**kwargs) 5 | self.square_feet = square_feet 6 | self.num_bedrooms = beds 7 | self.num_baths = baths 8 | 9 | def display(self): 10 | print("PROPERTY DETAILS") 11 | print("================") 12 | print("square footage: {}".format(self.square_feet)) 13 | print("bedrooms: {}".format(self.num_bedrooms)) 14 | print("bathrooms: {}".format(self.num_baths)) 15 | print() 16 | 17 | def prompt_init(): 18 | return dict(square_feet=input("Enter the square feet: "), 19 | beds=input("Enter number of bedrooms: "), 20 | baths=input("Enter number of baths: ")) 21 | prompt_init = staticmethod(prompt_init) 22 | 23 | -------------------------------------------------------------------------------- /1261_07_Code/timer.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | 4 | class TimedEvent: 5 | def __init__(self, endtime, callback): 6 | self.endtime = endtime 7 | self.callback = callback 8 | 9 | def ready(self): 10 | return self.endtime <= datetime.datetime.now() 11 | 12 | class Timer: 13 | def __init__(self): 14 | self.events = [] 15 | 16 | def call_after(self, delay, callback): 17 | end_time = datetime.datetime.now() + \ 18 | datetime.timedelta(seconds=delay) 19 | 20 | self.events.append(TimedEvent(end_time, callback)) 21 | 22 | def run(self): 23 | while True: 24 | ready_events = (e for e in self.events if e.ready()) 25 | for event in ready_events: 26 | event.callback(self) 27 | self.events.remove(event) 28 | time.sleep(0.5) 29 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_05_gzip_decorator.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import gzip 3 | from io import BytesIO 4 | 5 | class GzipSocket: 6 | def __init__(self, socket): 7 | self.socket = socket 8 | 9 | def send(self, data): 10 | buf = BytesIO() 11 | zipfile = gzip.GzipFile(fileobj=buf, mode="w") 12 | zipfile.write(data) 13 | zipfile.close() 14 | self.socket.send(buf.getvalue()) 15 | 16 | def close(self): 17 | self.socket.close() 18 | 19 | def respond(client): 20 | response = input("Enter a value: ") 21 | client.send(bytes(response, 'utf8')) 22 | client.close() 23 | 24 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 25 | server.bind(('',2401)) 26 | server.listen(1) 27 | try: 28 | while True: 29 | client, addr = server.accept() 30 | respond(GzipSocket(client)) 31 | finally: 32 | server.close() 33 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_25_timer.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | 4 | class TimedEvent: 5 | def __init__(self, endtime, callback): 6 | self.endtime = endtime 7 | self.callback = callback 8 | 9 | def ready(self): 10 | return self.endtime <= datetime.datetime.now() 11 | 12 | class Timer: 13 | def __init__(self): 14 | self.events = [] 15 | 16 | def call_after(self, delay, callback): 17 | end_time = datetime.datetime.now() + \ 18 | datetime.timedelta(seconds=delay) 19 | 20 | self.events.append(TimedEvent(end_time, callback)) 21 | 22 | def run(self): 23 | while True: 24 | ready_events = (e for e in self.events if e.ready()) 25 | for event in ready_events: 26 | event.callback(self) 27 | self.events.remove(event) 28 | time.sleep(0.5) 29 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_18_create_database_for_template.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | conn = sqlite3.connect("sales.db") 4 | 5 | conn.execute("CREATE TABLE Sales (salesperson text, " 6 | "amt currency, year integer, model text, new boolean)") 7 | conn.execute("INSERT INTO Sales values" 8 | " ('Tim', 16000, 2010, 'Honda Fit', 'true')") 9 | conn.execute("INSERT INTO Sales values" 10 | " ('Tim', 9000, 2006, 'Ford Focus', 'false')") 11 | conn.execute("INSERT INTO Sales values" 12 | " ('Gayle', 8000, 2004, 'Dodge Neon', 'false')") 13 | conn.execute("INSERT INTO Sales values" 14 | " ('Gayle', 28000, 2009, 'Ford Mustang', 'true')") 15 | conn.execute("INSERT INTO Sales values" 16 | " ('Gayle', 50000, 2010, 'Lincoln Navigator', 'true')") 17 | conn.execute("INSERT INTO Sales values" 18 | " ('Don', 20000, 2008, 'Toyota Prius', 'false')") 19 | conn.commit() 20 | conn.close() 21 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_12_contrived_diamond.py: -------------------------------------------------------------------------------- 1 | class BaseClass: 2 | num_base_calls = 0 3 | def call_me(self): 4 | print("Calling method on Base Class") 5 | self.num_base_calls += 1 6 | 7 | class LeftSubclass(BaseClass): 8 | num_left_calls = 0 9 | def call_me(self): 10 | BaseClass.call_me(self) 11 | print("Calling method on Left Subclass") 12 | self.num_left_calls += 1 13 | 14 | class RightSubclass(BaseClass): 15 | num_right_calls = 0 16 | def call_me(self): 17 | BaseClass.call_me(self) 18 | print("Calling method on Right Subclass") 19 | self.num_right_calls += 1 20 | 21 | class Subclass(LeftSubclass, RightSubclass): 22 | num_sub_calls = 0 23 | def call_me(self): 24 | LeftSubclass.call_me(self) 25 | RightSubclass.call_me(self) 26 | print("Calling method on Subclass") 27 | self.num_sub_calls += 1 28 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_20_template_abstract_implemented.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | class QueryTemplate: 4 | def connect(self): 5 | self.conn = sqlite3.connect("sales.db") 6 | 7 | def construct_query(self): 8 | raise NotImplementedError() 9 | 10 | def do_query(self): 11 | results = self.conn.execute(self.query) 12 | self.results = results.fetchall() 13 | 14 | def format_results(self): 15 | output = [] 16 | for row in self.results: 17 | row =[str(i) for i in row] 18 | output.append(", ".join(row)) 19 | self.formatted_results = "\n".join(output) 20 | 21 | def output_results(self): 22 | raise NotImplementedError() 23 | 24 | def process_format(self): 25 | self.connect() 26 | self.construct_query() 27 | self.do_query() 28 | self.format_results() 29 | self.output_results() 30 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_02_alchemy_intro.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy as sqa 2 | from sqlalchemy.ext.declarative import declarative_base 3 | 4 | Base = declarative_base() 5 | 6 | class Pet(Base): 7 | __tablename__ = "pet" 8 | id = sqa.Column(sqa.Integer, primary_key=True) 9 | type = sqa.Column(sqa.String(16)) 10 | breed = sqa.Column(sqa.String(32)) 11 | gender = sqa.Column(sqa.Enum("male", "female")) 12 | name = sqa.Column(sqa.String(64)) 13 | 14 | engine = sqa.create_engine('sqlite:///mydata.db') 15 | Base.metadata.create_all(engine) 16 | 17 | pet = Pet() 18 | pet.id = 1 19 | pet.type = "dog" 20 | pet.breed = "spaniel" 21 | pet.gender = "female" 22 | pet.name = "Esme" 23 | 24 | Session = sqa.orm.sessionmaker(bind=engine) 25 | session = Session() 26 | 27 | session.add(pet) 28 | session.commit() 29 | 30 | session.query(Pet).filter_by(name="Esme").one() 31 | session.query(Pet).filter(Pet.name=="Esme") 32 | -------------------------------------------------------------------------------- /1261_10_Code/1261_10_25_state_pickling.py: -------------------------------------------------------------------------------- 1 | from threading import Timer 2 | import datetime 3 | from urllib.request import urlopen 4 | 5 | class UpdatedURL: 6 | def __init__(self, url): 7 | self.url = url 8 | self.contents = '' 9 | self.last_updated = None 10 | self.update() 11 | 12 | def update(self): 13 | self.contents = urlopen(self.url).read() 14 | self.last_updated = datetime.datetime.now() 15 | self.schedule() 16 | 17 | def schedule(self): 18 | self.timer = Timer(3600, self.update) 19 | self.timer.setDaemon(True) 20 | self.timer.start() 21 | 22 | def __getstate__(self): 23 | new_state = self.__dict__.copy() 24 | if 'timer' in new_state: 25 | del new_state['timer'] 26 | return new_state 27 | 28 | def __setstate__(self, data): 29 | self.__dict__ = data 30 | self.schedule() 31 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_15-note_object.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | last_id = 0 4 | 5 | class Note: 6 | '''Represent a note in the notebook. Match against a 7 | string in searches and store tags for each note.''' 8 | 9 | 10 | def __init__(self, memo, tags=''): 11 | '''initialize a note with memo and optional 12 | space-separated tags. Automatically set the note's 13 | creation date and a unique id''' 14 | self.memo = memo 15 | self.tags = tags 16 | self.creation_date = datetime.date.today() 17 | global last_id 18 | last_id += 1 19 | self.id = last_id 20 | 21 | def match(self, filter): 22 | '''Determine if this note matches the filter 23 | text. Return True if it matches, False otherwise. 24 | 25 | Search is case sensitive and matches both text and 26 | tags.''' 27 | return filter in self.memo or filter in self.tags 28 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_14_inventory_mock_object.py: -------------------------------------------------------------------------------- 1 | class Inventory: 2 | def lock(self, item_type): 3 | '''Select the type of item that is going to 4 | be manipulated. This method will lock the 5 | item so nobody else can manipulate the 6 | inventory until it's returned. This prevents 7 | selling the same item to two different 8 | customers.''' 9 | pass 10 | 11 | def unlock(self, item_type): 12 | '''Release the given type so that other 13 | customers can access it.''' 14 | pass 15 | 16 | def purchase(self, item_type): 17 | '''If the item is not locked, raise an 18 | exception. If the itemtype does not exist, 19 | raise an exception. If the item is currently 20 | out of stock, raise an exception. If the item 21 | is available, subtract one item and return 22 | the number of items left.''' 23 | pass 24 | 25 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_06_flyweight_init.py: -------------------------------------------------------------------------------- 1 | import weakref 2 | 3 | class CarModel: 4 | _models = weakref.WeakValueDictionary() 5 | 6 | def __new__(cls, model_name, *args, **kwargs): 7 | model = cls._models.get(model_name) 8 | if not model: 9 | model = super().__new__(cls) 10 | cls._models[model_name] = model 11 | 12 | return model 13 | 14 | def __init__(self, model_name, air=False, tilt=False, 15 | cruise_control=False, power_locks=False, 16 | alloy_wheels=False, usb_charger=False): 17 | if not hasattr(self, "initialized"): 18 | self.model_name = model_name 19 | self.air = air 20 | self.tilt = tilt 21 | self.cruise_control = cruise_control 22 | self.power_locks = power_locks 23 | self.alloy_wheels = alloy_wheels 24 | self.usb_charger = usb_charger 25 | self.initialized=True 26 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_12_pytest_echo.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import socket 3 | import time 4 | 5 | def pytest_funcarg__echoserver(request): 6 | def setup(): 7 | p = subprocess.Popen( 8 | ['python3', '1261_11_11_echo_server.py']) 9 | time.sleep(1) 10 | return p 11 | 12 | def cleanup(p): 13 | p.terminate() 14 | 15 | return request.cached_setup( 16 | setup=setup, 17 | teardown=cleanup, 18 | scope="session") 19 | 20 | def pytest_funcarg__clientsocket(request): 21 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 22 | s.connect(('localhost', 1028)) 23 | request.addfinalizer(lambda: s.close()) 24 | return s 25 | 26 | def test_echo(echoserver, clientsocket): 27 | clientsocket.send(b"abc") 28 | assert clientsocket.recv(3) == b'abc' 29 | 30 | def test_echo2(echoserver, clientsocket): 31 | clientsocket.send(b"def") 32 | assert clientsocket.recv(3) == b'def' 33 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_28_add_property.py: -------------------------------------------------------------------------------- 1 | class Agent: 2 | type_map = { 3 | ("house", "rental"): HouseRental, 4 | ("house", "purchase"): HousePurchase, 5 | ("apartment", "rental"): ApartmentRental, 6 | ("apartment", "purchase"): ApartmentPurchase 7 | } 8 | 9 | def __init__(self): 10 | self.property_list = [] 11 | 12 | def display_properties(): 13 | for property in self.property_list: 14 | property.display() 15 | 16 | def add_property(self): 17 | property_type = get_valid_input( 18 | "What type of property? ", 19 | ("house", "apartment")).lower() 20 | payment_type = get_valid_input( 21 | "What payment type? ", 22 | ("purchase", "rental")).lower() 23 | 24 | PropertyClass = self.type_map[(property_type, payment_type)] 25 | init_args = PropertyClass.prompt_init() 26 | self.property_list.append(PropertyClass(**init_args)) 27 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_22_all_arguments.py: -------------------------------------------------------------------------------- 1 | import shutil 2 | import os.path 3 | def augmented_move(target_folder, *filenames, 4 | verbose=False, **specific): 5 | '''Move all filenames into the target_folder, allowing 6 | specific treatment of certain files.''' 7 | 8 | def print_verbose(message, filename): 9 | '''print the message only if verbose is enabled''' 10 | if verbose: 11 | print(message.format(filename)) 12 | 13 | for filename in filenames: 14 | target_path = os.path.join(target_folder, filename) 15 | if filename in specific: 16 | if specific[filename] == 'ignore': 17 | print_verbose("Ignoring {0}", filename) 18 | elif specific[filename] == 'copy': 19 | print_verbose("Copying {0}", filename) 20 | shutil.copyfile(filename, target_path) 21 | else: 22 | print_verbose("Moving {0}", filename) 23 | shutil.move(filename, target_path) 24 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_19_zipreplace_inheritance.py: -------------------------------------------------------------------------------- 1 | from zip_processor import ZipProcessor 2 | import sys 3 | import os 4 | 5 | class ZipReplace(ZipProcessor): 6 | def __init__(self, filename, search_string, 7 | replace_string): 8 | super().__init__(filename) 9 | self.search_string = search_string 10 | self.replace_string = replace_string 11 | 12 | def process_files(self): 13 | '''perform a search and replace on all files in the 14 | temporary directory''' 15 | for filename in os.listdir(self.temp_directory): 16 | with open( 17 | self._full_filename(filename)) as file: 18 | contents = file.read() 19 | contents = contents.replace( 20 | self.search_string, self.replace_string) 21 | with open(self._full_filename(filename), "w") as file: 22 | file.write(contents) 23 | 24 | if __name__ == "__main__": 25 | ZipReplace(*sys.argv[1:4]).process_zip() 26 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_16_dictsorted.py: -------------------------------------------------------------------------------- 1 | from collections import KeysView, ItemsView, ValuesView 2 | class DictSorted(dict): 3 | def __new__(*args, **kwargs): 4 | new_dict = dict.__new__(*args, **kwargs) 5 | new_dict.ordered_keys = [] 6 | return new_dict 7 | 8 | def __setitem__(self, key, value): 9 | '''self[key] = value syntax''' 10 | if key not in self.ordered_keys: 11 | self.ordered_keys.append(key) 12 | super().__setitem__(key, value) 13 | 14 | def setdefault(self, key, value): 15 | if key not in self.ordered_keys: 16 | self.ordered_keys.append(key) 17 | return super().setdefault(key, value) 18 | 19 | def keys(self): 20 | return KeysView(self) 21 | 22 | def values(self): 23 | return ValuesView(self) 24 | 25 | def items(self): 26 | return ItemsView(self) 27 | 28 | def __iter__(self): 29 | '''for x in self syntax''' 30 | return self.ordered_keys.__iter__() 31 | -------------------------------------------------------------------------------- /1261_07_Code/1261_07_26_timer_test.py: -------------------------------------------------------------------------------- 1 | from timer import Timer 2 | import datetime 3 | 4 | def format_time(message, *args): 5 | now = datetime.datetime.now().strftime("%I:%M:%S") 6 | print(message.format(*args, now=now)) 7 | 8 | def one(timer): 9 | format_time("{now}: Called One") 10 | 11 | def two(timer): 12 | format_time("{now}: Called Two") 13 | 14 | def three(timer): 15 | format_time("{now}: Called Three") 16 | 17 | class Repeater: 18 | def __init__(self): 19 | self.count = 0 20 | def repeater(self, timer): 21 | format_time("{now}: repeat {0}", self.count) 22 | self.count += 1 23 | timer.call_after(5, self.repeater) 24 | 25 | timer = Timer() 26 | timer.call_after(1, one) 27 | timer.call_after(2, one) 28 | timer.call_after(2, two) 29 | timer.call_after(4, two) 30 | timer.call_after(3, three) 31 | timer.call_after(6, three) 32 | repeater = Repeater() 33 | timer.call_after(5, repeater.repeater) 34 | format_time("{now}: Starting") 35 | timer.run() 36 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_18_zipprocessor.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import zipfile 4 | 5 | class ZipProcessor: 6 | def __init__(self, zipname): 7 | self.zipname = zipname 8 | self.temp_directory = "unzipped-{}".format( 9 | zipname[:-4]) 10 | 11 | def _full_filename(self, filename): 12 | return os.path.join(self.temp_directory, filename) 13 | 14 | def process_zip(self): 15 | self.unzip_files() 16 | self.process_files() 17 | self.zip_files() 18 | 19 | def unzip_files(self): 20 | os.mkdir(self.temp_directory) 21 | zip = zipfile.ZipFile(self.zipname) 22 | try: 23 | zip.extractall(self.temp_directory) 24 | finally: 25 | zip.close() 26 | 27 | def zip_files(self): 28 | file = zipfile.ZipFile(self.zipname, 'w') 29 | for filename in os.listdir(self.temp_directory): 30 | file.write(self._full_filename(filename), filename) 31 | shutil.rmtree(self.temp_directory) 32 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_12_observer_observing.py: -------------------------------------------------------------------------------- 1 | class Inventory: 2 | def __init__(self): 3 | self.observers = [] 4 | self._product = None 5 | self._quantity = 0 6 | 7 | def attach(self, observer): 8 | self.observers.append(observer) 9 | 10 | @property 11 | def product(self): 12 | return self._product 13 | @product.setter 14 | def product(self, value): 15 | self._product = value 16 | self._update_observers() 17 | 18 | @property 19 | def quantity(self): 20 | return self._quantity 21 | @quantity.setter 22 | def quantity(self, value): 23 | self._quantity = value 24 | self._update_observers() 25 | 26 | def _update_observers(self): 27 | for observer in self.observers: 28 | observer() 29 | 30 | class ConsoleObserver: 31 | def __init__(self, inventory): 32 | self.inventory = inventory 33 | 34 | def __call__(self): 35 | print(self.inventory.product) 36 | print(self.inventory.quantity) 37 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_23_zipreplace_composition.py: -------------------------------------------------------------------------------- 1 | from zip_processor import ZipProcessor 2 | import sys 3 | import os 4 | 5 | class ZipReplace: 6 | def __init__(self, search_string, replace_string): 7 | self.search_string = search_string 8 | self.replace_string = replace_string 9 | 10 | def process(self, zipprocessor): 11 | '''perform a search and replace on all files in the 12 | temporary directory''' 13 | for filename in os.listdir( 14 | zipprocessor.temp_directory): 15 | with open(zipprocessor._full_filename( 16 | filename)) as file: 17 | contents = file.read() 18 | contents = contents.replace( 19 | self.search_string, self.replace_string) 20 | with open(zipprocessor._full_filename(filename), "w") as file: 21 | file.write(contents) 22 | 23 | if __name__ == "__main__": 24 | zipreplace = ZipReplace(*sys.argv[2:4]) 25 | ZipProcessor(sys.argv[1], zipreplace).process_zip() 26 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_10_window_command_invokers.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Window: 4 | def exit(self): 5 | sys.exit(0) 6 | 7 | class Document: 8 | def __init__(self, filename): 9 | self.filename = filename 10 | self.contents = "This file cannot be modified" 11 | 12 | def save(self): 13 | with open(self.filename, 'w') as file: 14 | file.write(self.contents) 15 | 16 | class ToolbarButton: 17 | def __init__(self, name, iconname): 18 | self.name = name 19 | self.iconname = iconname 20 | 21 | def click(self): 22 | self.command.execute() 23 | 24 | class MenuItem: 25 | def __init__(self, menu_name, menuitem_name): 26 | self.menu = menu_name 27 | self.item = menuitem_name 28 | 29 | def click(self): 30 | self.command.execute() 31 | 32 | class KeyboardShortcut: 33 | def __init__(self, key, modifier): 34 | self.key = key 35 | self.modifier = modifier 36 | 37 | def keypress(self): 38 | self.command.execute() 39 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_08_etree_read_html.py: -------------------------------------------------------------------------------- 1 | from xml.etree.ElementTree import fromstring 2 | 3 | with open("1267_12_07_html_document.html") as file: 4 | root = fromstring(file.read()) 5 | 6 | print("ROOT NODE") 7 | print("\ttag:", root.tag) 8 | print("\tnumber of children:", len(root)) 9 | print("\tchildren:", [c.tag for c in root.getchildren()]) 10 | head = root[0] 11 | print("HEAD NODE") 12 | print("\tfirst child:", head[0].tag) 13 | print("\tsecond_child:", head[1].tag) 14 | print("\tlink attributes:", head[1].attrib) 15 | article = root[1][1] 16 | print("ARTICLE NODE") 17 | print("\ttag:", article.tag) 18 | print("\ttext:", article.text) 19 | print("\tfirst child:", article[0].tag, article[0].text) 20 | print("\t\tem's tail:", article[0].tail) 21 | print("\tsecond child:", article[1].tag, article[1].text) 22 | print("\tstrong's tail:", article[1].tail) 23 | 24 | # XPath Selection 25 | print('search for child tag:', root.find('head')) 26 | print('search children recursively:', root.findall('.//em')) 27 | print('build path:', root.findtext('./body/article/em')) 28 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_12_multipage_cherrypy.py: -------------------------------------------------------------------------------- 1 | import cherrypy 2 | 3 | template = """ 4 | 5 | 6 | {message} 7 | 8 | """ 9 | 10 | class AboutPage: 11 | @cherrypy.expose 12 | def index(self): 13 | return template.format(message=""" 14 | I'm not a very interesting person...""") 15 | 16 | @cherrypy.expose 17 | def contactPage(self): 18 | print(self) 19 | return template.format( 20 | message="I can't be contacted anywhere.") 21 | 22 | class MainPage: 23 | about = AboutPage() 24 | contact = contactPage 25 | @cherrypy.expose 26 | def index(self): 27 | return template.format(message=""" 28 | This is the main page. 29 |
About Me 30 | Contact Me 31 | Some Links 32 | """) 33 | 34 | @cherrypy.expose 35 | def links(self): 36 | return template.format( 37 | message="No Links Yet") 38 | 39 | cherrypy.quickstart(MainPage()) 40 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_17_component_hierarchy.py: -------------------------------------------------------------------------------- 1 | class Component: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def move(self, new_path): 6 | new_folder =get_path(new_path) 7 | del self.parent.children[self.name] 8 | new_folder.children[self.name] = self 9 | self.parent = new_folder 10 | 11 | def delete(self): 12 | del self.parent.children[self.name] 13 | 14 | class Folder(Component): 15 | def __init__(self, name): 16 | super().__init__(name) 17 | self.children = {} 18 | 19 | def add_child(self, child): 20 | pass 21 | 22 | def copy(self, new_path): 23 | pass 24 | 25 | class File(Component): 26 | def __init__(self, name, contents): 27 | super().__init__(name) 28 | self.contents = contents 29 | 30 | def copy(self, new_path): 31 | pass 32 | 33 | root = Folder('') 34 | def get_path(path): 35 | names = path.split('/')[1:] 36 | node = root 37 | for name in names: 38 | node = node.children[name] 39 | return node 40 | 41 | -------------------------------------------------------------------------------- /1261_05_Code/zip_processor.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import zipfile 4 | 5 | class ZipProcessor: 6 | def __init__(self, zipname, processor): 7 | self.zipname = zipname 8 | self.temp_directory = "unzipped-{}".format( 9 | zipname[:-4]) 10 | self.processor = processor 11 | 12 | def _full_filename(self, filename): 13 | return os.path.join(self.temp_directory, filename) 14 | 15 | def process_zip(self): 16 | self.unzip_files() 17 | self.processor.process(self.temp_directory) 18 | self.zip_files() 19 | 20 | def unzip_files(self): 21 | os.mkdir(self.temp_directory) 22 | zip = zipfile.ZipFile(self.zipname) 23 | try: 24 | zip.extractall(self.temp_directory) 25 | finally: 26 | zip.close() 27 | 28 | def zip_files(self): 29 | file = zipfile.ZipFile(self.zipname, 'w') 30 | for filename in os.listdir(self.temp_directory): 31 | file.write(self._full_filename(filename), filename) 32 | shutil.rmtree(self.temp_directory) 33 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_09-docstrings.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Point: 4 | 'Represents a point in two-dimensional geometric coordinates' 5 | 6 | def __init__(self, x=0, y=0): 7 | '''Initialize the position of a new point. The x and y coordinates can 8 | be specified. If they are not, the point defaults to the origin.''' 9 | self.move(x, y) 10 | 11 | def move(self, x, y): 12 | "Move the point to a new location in two-dimensional space." 13 | self.x = x 14 | self.y = y 15 | 16 | def reset(self): 17 | 'Reset the point back to the geometric origin: 0, 0' 18 | self.move(0, 0) 19 | 20 | def calculate_distance(self, other_point): 21 | """Calculate the distance from this point to a second point passed 22 | as a parameter. 23 | 24 | This function uses the Pythagorean Theorem to calculate the distance 25 | between the two points. The distance is returned as a float.""" 26 | 27 | return math.sqrt( 28 | (self.x - other_point.x)**2 + 29 | (self.y - other_point.y)**2) 30 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_21_zipprocessor_composition.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import zipfile 4 | 5 | class ZipProcessor: 6 | def __init__(self, zipname, processor): 7 | self.zipname = zipname 8 | self.temp_directory = "unzipped-{}".format( 9 | zipname[:-4]) 10 | self.processor = processor 11 | 12 | def _full_filename(self, filename): 13 | return os.path.join(self.temp_directory, filename) 14 | 15 | def process_zip(self): 16 | self.unzip_files() 17 | self.processor.process(self.temp_directory) 18 | self.zip_files() 19 | 20 | def unzip_files(self): 21 | os.mkdir(self.temp_directory) 22 | zip = zipfile.ZipFile(self.zipname) 23 | try: 24 | zip.extractall(self.temp_directory) 25 | finally: 26 | zip.close() 27 | 28 | def zip_files(self): 29 | file = zipfile.ZipFile(self.zipname, 'w') 30 | for filename in os.listdir(self.temp_directory): 31 | file.write(self._full_filename(filename), filename) 32 | shutil.rmtree(self.temp_directory) 33 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_18_add_child.py: -------------------------------------------------------------------------------- 1 | class Component: 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def move(self, new_path): 6 | new_folder =get_path(new_path) 7 | del self.parent.children[self.name] 8 | new_folder.children[self.name] = self 9 | self.parent = new_folder 10 | 11 | def delete(self): 12 | del self.parent.children[self.name] 13 | 14 | class Folder(Component): 15 | def __init__(self, name): 16 | super().__init__(name) 17 | self.children = {} 18 | 19 | def add_child(self, child): 20 | child.parent = self 21 | self.children[child.name] = child 22 | 23 | def copy(self, new_path): 24 | pass 25 | 26 | class File(Component): 27 | def __init__(self, name, contents): 28 | super().__init__(name) 29 | self.contents = contents 30 | 31 | def copy(self, new_path): 32 | pass 33 | 34 | root = Folder('') 35 | def get_path(path): 36 | names = path.split('/')[1:] 37 | node = root 38 | for name in names: 39 | node = node.children[name] 40 | return node 41 | 42 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_04.5_tkinter_pack.py: -------------------------------------------------------------------------------- 1 | import tkinter 2 | 3 | class PackFrame(tkinter.Frame): 4 | def __init__(self, master): 5 | super().__init__(master) 6 | 7 | button1 = tkinter.Button(self, 8 | text = "expand fill") 9 | button1.pack(expand=True, fill="both", side="left") 10 | button2 = tkinter.Button(self, 11 | text = "anchor ne pady") 12 | button2.pack(anchor="ne", pady=5, side="left") 13 | button3 = tkinter.Button(self, 14 | text = "anchor se padx") 15 | button3.pack(anchor="se", padx=5, side="left") 16 | 17 | class TwoPackFrames(tkinter.Frame): 18 | def __init__(self, master): 19 | super().__init__(master) 20 | button1 = tkinter.Button(self, 21 | text="ipadx") 22 | button1.pack(ipadx=215) 23 | packFrame1 = PackFrame(self) 24 | packFrame1.pack(side="bottom", anchor="e") 25 | packFrame2 = PackFrame(self) 26 | packFrame2.pack(side="bottom", anchor="w") 27 | self.pack() 28 | 29 | root = tkinter.Tk() 30 | TwoPackFrames(master=root).mainloop() 31 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_19_visited_links_sets.py: -------------------------------------------------------------------------------- 1 | class LinkCollector: 2 | def __init__(self, url): 3 | self.url = "http://" + urlparse(url).netloc 4 | self.collected_links = set() 5 | self.visited_links = set() 6 | 7 | def collect_links(self, path="/"): 8 | full_url = self.url + path 9 | self.visited_links.add(full_url) 10 | page = str(urlopen(full_url).read()) 11 | links = LINK_REGEX.findall(page) 12 | links = {self.normalize_url(path, link 13 | ) for link in links} 14 | self.collected_links = links.union( 15 | self.collected_links) 16 | unvisited_links = links.difference( 17 | self.visited_links) 18 | print(links, self.visited_links, 19 | self.collected_links, unvisited_links) 20 | 21 | def normalize_url(self, path, link): 22 | if link.startswith("http://"): 23 | return link 24 | elif link.startswith("/"): 25 | return self.url + link 26 | else: 27 | return self.url + path.rpartition('/' 28 | )[0] + '/' + link 29 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_21_apartment_nice_prompt.py: -------------------------------------------------------------------------------- 1 | class Apartment(Property): 2 | valid_laundries = ("coin", "ensuite", "none") 3 | valid_balconies = ("yes", "no", "solarium") 4 | 5 | def __init__(self, balcony='', laundry='', **kwargs): 6 | super().__init__(**kwargs) 7 | self.balcony = balcony 8 | self.laundry = laundry 9 | 10 | def display(self): 11 | super().display() 12 | print("APARTMENT DETAILS") 13 | print("laundry: {}".format(self.laundry)) 14 | print("has balcony: {}".format(self.balcony)) 15 | 16 | def prompt_init(): 17 | parent_init = Property.prompt_init() 18 | laundry = get_valid_input( 19 | "What laundry facilities does " 20 | "the property have? ", 21 | Apartment.valid_laundries) 22 | balcony = get_valid_input( 23 | "Does the property have a balcony? ", 24 | Apartment.valid_balconies) 25 | parent_init.update({ 26 | "laundry": laundry, 27 | "balcony": balcony 28 | }) 29 | return parent_init 30 | prompt_init = staticmethod(prompt_init) 31 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_16-notebook_first.py: -------------------------------------------------------------------------------- 1 | class Notebook: 2 | '''Represent a collection of notes that can be tagged, 3 | modified, and searched.''' 4 | 5 | def __init__(self): 6 | '''Initialize a notebook with an empty list.''' 7 | self.notes = [] 8 | 9 | def new_note(self, memo, tags=''): 10 | '''Create a new note and add it to the list.''' 11 | self.notes.append(Note(memo, tags)) 12 | 13 | def modify_memo(self, note_id, memo): 14 | '''Find the note with the given id and change its 15 | memo to the given value.''' 16 | for note in self.notes: 17 | if note.id == note_id: 18 | note.memo = memo 19 | break 20 | 21 | def modify_tags(self, note_id, tags): 22 | '''Find the note with the given id and change its 23 | tags to the given value.''' 24 | for note in self.notes: 25 | if note.id == note_id: 26 | note.tags = tags 27 | break 28 | 29 | def search(self, filter): 30 | '''Find all notes that match the given filter 31 | string.''' 32 | return [note for note in self.notes if 33 | note.match(filter)] 34 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_07_flyweight_check_serial.py: -------------------------------------------------------------------------------- 1 | import weakref 2 | 3 | class CarModel: 4 | _models = weakref.WeakValueDictionary() 5 | 6 | def __new__(cls, model_name, *args, **kwargs): 7 | model = cls._models.get(model_name) 8 | if not model: 9 | model = super().__new__(cls) 10 | cls._models[model_name] = model 11 | 12 | return model 13 | 14 | def __init__(self, model_name, air=False, tilt=False, 15 | cruise_control=False, power_locks=False, 16 | alloy_wheels=False, usb_charger=False): 17 | if not hasattr(self, "initted"): 18 | self.model_name = model_name 19 | self.air = air 20 | self.tilt = tilt 21 | self.cruise_control = cruise_control 22 | self.power_locks = power_locks 23 | self.alloy_wheels = alloy_wheels 24 | self.usb_charger = usb_charger 25 | self.initted=True 26 | 27 | def check_serial(self, serial_number): 28 | print("Sorry, we are unable to check " 29 | "the serial number {0} on the {1} " 30 | "at this time".format( 31 | serial_number, self.model_name)) 32 | 33 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_16_auth_user.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | class User: 4 | def __init__(self, username, password): 5 | '''Create a new user object. The password 6 | will be encrypted before storing.''' 7 | self.username = username 8 | self.password = self._encrypt_pw(password) 9 | self.is_logged_in = False 10 | 11 | def _encrypt_pw(self, password): 12 | '''Encrypt the password with the username and return 13 | the sha digest.''' 14 | hash_string = (self.username + password) 15 | hash_string = hash_string.encode("utf8") 16 | return hashlib.sha256(hash_string).hexdigest() 17 | 18 | def check_password(self, password): 19 | '''Return True if the password is valid for this 20 | user, false otherwise.''' 21 | encrypted = self._encrypt_pw(password) 22 | return encrypted == self.password 23 | 24 | 25 | class AuthException(Exception): 26 | def __init__(self, username, user=None): 27 | super().__init__(username) 28 | self.username = username 29 | self.user = user 30 | 31 | class UsernameAlreadyExists(AuthException): 32 | pass 33 | 34 | class PasswordTooShort(AuthException): 35 | pass 36 | -------------------------------------------------------------------------------- /1261_11_Code/1261_11_08_setup_teardown.py: -------------------------------------------------------------------------------- 1 | def setup_module(module): 2 | print("\nsetting up MODULE {0}".format( 3 | module.__name__)) 4 | 5 | def teardown_module(module): 6 | print("tearing down MODULE {0}".format( 7 | module.__name__)) 8 | 9 | def test_a_function(): 10 | print("RUNNING TEST FUNCTION") 11 | 12 | class BaseTest: 13 | def setup_class(cls): 14 | print("setting up CLASS {0}".format( 15 | cls.__name__)) 16 | 17 | def teardown_class(cls): 18 | print("tearing down CLASS {0}\n".format( 19 | cls.__name__)) 20 | 21 | def setup_method(self, method): 22 | print("setting up METHOD {0}".format( 23 | method.__name__)) 24 | 25 | def teardown_method(self, method): 26 | print("tearing down METHOD {0}".format( 27 | method.__name__)) 28 | 29 | class TestClass1(BaseTest): 30 | def test_method_1(self): 31 | print("RUNNING METHOD 1-1") 32 | 33 | def test_method_2(self): 34 | print("RUNNING METHOD 1-2") 35 | 36 | class TestClass2(BaseTest): 37 | def test_method_1(self): 38 | print("RUNNING METHOD 2-1") 39 | 40 | def test_method_2(self): 41 | print("RUNNING METHOD 2-2") 42 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_22_house.py: -------------------------------------------------------------------------------- 1 | class House(Property): 2 | valid_garage = ("attached", "detached", "none") 3 | valid_fenced = ("yes", "no") 4 | 5 | def __init__(self, num_stories='', 6 | garage='', fenced='', **kwargs): 7 | super().__init__(**kwargs) 8 | self.garage = garage 9 | self.fenced = fenced 10 | self.num_stories = num_stories 11 | 12 | def display(self): 13 | super().display() 14 | print("HOUSE DETAILS") 15 | print("# of stories: {}".format(self.num_stories)) 16 | print("garage: {}".format(self.garage)) 17 | print("fenced yard: {}".format(self.fenced)) 18 | 19 | def prompt_init(): 20 | parent_init = Property.prompt_init() 21 | fenced = get_valid_input("Is the yard fenced? ", 22 | House.valid_fenced) 23 | garage = get_valid_input("Is there a garage? ", 24 | House.valid_garage) 25 | num_stories = input("How many stories? ") 26 | 27 | parent_init.update({ 28 | "fenced": fenced, 29 | "garage": garage, 30 | "num_stories": num_stories 31 | }) 32 | return parent_init 33 | prompt_init = staticmethod(prompt_init) 34 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_13_strategy_tile.py: -------------------------------------------------------------------------------- 1 | from pygame import image 2 | from pygame.transform import scale 3 | from pygame import Surface 4 | 5 | class TiledStrategy: 6 | def make_background(self, img_file, desktop_size): 7 | in_img = image.load(img_file) 8 | out_img = Surface(desktop_size) 9 | for x in range((out_img.get_width( 10 | ) // in_img.get_width()) + 1): 11 | for y in range((out_img.get_height( 12 | ) // in_img.get_height()) + 1): 13 | out_img.blit(in_img, (in_img.get_width() * x, 14 | in_img.get_height() * y)) 15 | return out_img 16 | 17 | class CenteredStrategy: 18 | def make_background(self, img_file, desktop_size): 19 | in_img = image.load(img_file) 20 | out_img = Surface(desktop_size) 21 | out_img.fill((0,0,0)) 22 | left = (out_img.get_width() - in_img.get_width()) / 2 23 | top = (out_img.get_height() - in_img.get_height()) / 2 24 | out_img.blit(in_img, (left, top)) 25 | return out_img 26 | 27 | class ScaledStrategy: 28 | def make_background(self, img_file, desktop_size): 29 | in_img = image.load(img_file) 30 | return scale(in_img, desktop_size) 31 | -------------------------------------------------------------------------------- /1261_11_Code/casestudy/vigenere_cipher.py: -------------------------------------------------------------------------------- 1 | def combine_character(plain, keyword): 2 | plain = plain.upper() 3 | keyword = keyword.upper() 4 | plain_num = ord(plain) - ord('A') 5 | keyword_num = ord(keyword) - ord('A') 6 | return chr(ord('A') + (plain_num + keyword_num) % 26) 7 | 8 | def separate_character(cypher, keyword): 9 | cypher = cypher.upper() 10 | keyword = keyword.upper() 11 | cypher_num = ord(cypher) - ord('A') 12 | keyword_num = ord(keyword) - ord('A') 13 | return chr(ord('A') + (cypher_num - keyword_num) % 26) 14 | 15 | class VigenereCipher: 16 | def __init__(self, keyword): 17 | self.keyword = keyword 18 | 19 | def extend_keyword(self, number): 20 | repeats = number // len(self.keyword) + 1 21 | return (self.keyword * repeats)[:number] 22 | 23 | def _code(self, text, combine_func): 24 | text = text.replace(" ", "").upper() 25 | combined = [] 26 | keyword = self.extend_keyword(len(text)) 27 | for p,k in zip(text, keyword): 28 | combined.append(combine_func(p,k)) 29 | return "".join(combined) 30 | 31 | def encode(self, plaintext): 32 | return self._code(plaintext, combine_character) 33 | 34 | def decode(self, ciphertext): 35 | return self._code(ciphertext, separate_character) 36 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_26_document_using_cursor.py: -------------------------------------------------------------------------------- 1 | class Cursor: 2 | def __init__(self, document): 3 | self.document = document 4 | self.position = 0 5 | 6 | def forward(self): 7 | self.position += 1 8 | 9 | def back(self): 10 | self.position -= 1 11 | 12 | def home(self): 13 | while self.document.characters[ 14 | self.position-1] != '\n': 15 | self.position -= 1 16 | if self.position == 0: 17 | # Got to beginning of file before newline 18 | break 19 | 20 | def end(self): 21 | while self.position < len(self.document.characters 22 | ) and self.document.characters[self.position] != '\n': 23 | self.position += 1 24 | 25 | 26 | class Document: 27 | def __init__(self): 28 | self.characters = [] 29 | self.cursor = Cursor(self) 30 | self.filename = '' 31 | 32 | def insert(self, character): 33 | self.characters.insert(self.cursor.position, 34 | character) 35 | self.cursor.forward() 36 | 37 | def delete(self): 38 | del self.characters[self.cursor.position] 39 | 40 | def save(self): 41 | f = open(self.filename, 'w') 42 | f.write(''.join(self.characters)) 43 | f.close() 44 | -------------------------------------------------------------------------------- /1261_07_Code/mailing_list.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | from email.mime.text import MIMEText 3 | from collections import defaultdict 4 | 5 | def send_email(subject, message, from_addr, *to_addrs, 6 | host="localhost", port=1025, headers): 7 | 8 | email = MIMEText(message) 9 | email['Subject'] = subject 10 | email['From'] = from_addr 11 | for header, value in headers.items(): 12 | email[header] = value 13 | 14 | sender = smtplib.SMTP(host, port) 15 | for addr in to_addrs: 16 | del email['To'] 17 | email['To'] = addr 18 | sender.sendmail(from_addr, addr, email.as_string()) 19 | sender.quit() 20 | 21 | class MailingList: 22 | '''Manage groups of e-mail addresses for sending e-mails.''' 23 | def __init__(self): 24 | self.email_map = defaultdict(set) 25 | 26 | def add_to_group(self, email, group): 27 | self.email_map[email].add(group) 28 | 29 | def emails_in_groups(self, *groups): 30 | groups = set(groups) 31 | return {e for (e, g) in self.email_map.items() 32 | if g & groups} 33 | 34 | def send_mailing(self, subject, message, from_addr, 35 | *groups, **kwargs): 36 | emails = self.emails_in_groups(*groups) 37 | send_email(subject, message, from_addr, 38 | *emails, **kwargs) 39 | -------------------------------------------------------------------------------- /1261_11_Code/casestudy/vigenere_cipher1.py: -------------------------------------------------------------------------------- 1 | def combine_character(plain, keyword): 2 | plain = plain.upper() 3 | keyword = keyword.upper() 4 | plain_num = ord(plain) - ord('A') 5 | keyword_num = ord(keyword) - ord('A') 6 | return chr(ord('A') + (plain_num + keyword_num) % 26) 7 | 8 | def separate_character(cypher, keyword): 9 | cypher = cypher.upper() 10 | keyword = keyword.upper() 11 | cypher_num = ord(cypher) - ord('A') 12 | keyword_num = ord(keyword) - ord('A') 13 | return chr(ord('A') + (cypher_num - keyword_num) % 26) 14 | 15 | class VigenereCipher: 16 | def __init__(self, keyword): 17 | self.keyword = keyword 18 | 19 | def extend_keyword(self, number): 20 | repeats = number // len(self.keyword) + 1 21 | return (self.keyword * repeats)[:number] 22 | 23 | def encode(self, plaintext): 24 | plaintext = plaintext.replace(" ", "").upper() 25 | cipher = [] 26 | keyword = self.extend_keyword(len(plaintext)) 27 | for p,k in zip(plaintext, keyword): 28 | cipher.append(combine_character(p,k)) 29 | return "".join(cipher) 30 | 31 | def decode(self, ciphertext): 32 | plain = [] 33 | keyword = self.extend_keyword(len(ciphertext)) 34 | for p,k in zip(ciphertext, keyword): 35 | plain.append(separate_character(p,k)) 36 | return "".join(plain) 37 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_04_email_facade.py: -------------------------------------------------------------------------------- 1 | import smtplib 2 | import imaplib 3 | 4 | class EmailFacade: 5 | def __init__(self, host, username, password): 6 | self.host = host 7 | self.username = username 8 | self.password = password 9 | 10 | def send_email(self, to_email, subject, message): 11 | if not "@" in self.username: 12 | from_email = "{0}@{1}".format( 13 | self.username, self.host) 14 | else: 15 | from_email = self.username 16 | message = ("From: {0}\r\n" 17 | "To: {1}\r\n" 18 | "Subject: {2}\r\n\r\n{3}").format( 19 | from_email, 20 | to_email, 21 | subject, 22 | message) 23 | 24 | smtp = smtplib.SMTP(self.host) 25 | smtp.login(self.username, self.password) 26 | smtp.sendmail(from_email, [to_email], message) 27 | 28 | def get_inbox(self): 29 | mailbox = imaplib.IMAP4(self.host) 30 | mailbox.login(bytes(self.username, 'utf8'), 31 | bytes(self.password, 'utf8')) 32 | mailbox.select() 33 | x, data = mailbox.search(None, 'ALL') 34 | messages = [] 35 | for num in data[0].split(): 36 | x, message = mailbox.fetch(num, '(RFC822)') 37 | messages.append(message[0][1]) 38 | return messages 39 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_19_apartment_ugly_prompt.py: -------------------------------------------------------------------------------- 1 | class Apartment(Property): 2 | valid_laundries = ("coin", "ensuite", "none") 3 | valid_balconies = ("yes", "no", "solarium") 4 | 5 | def __init__(self, balcony='', laundry='', **kwargs): 6 | super().__init__(**kwargs) 7 | self.balcony = balcony 8 | self.laundry = laundry 9 | 10 | def display(self): 11 | super().display() 12 | print("APARTMENT DETAILS") 13 | print("laundry: {}".format(self.laundry)) 14 | print("has balcony: {}".format(self.balcony)) 15 | 16 | def prompt_init(): 17 | parent_init = Property.prompt_init() 18 | laundry = '' 19 | while laundry.lower() not in \ 20 | Apartment.valid_laundries: 21 | laundry = input("What laundry facilities does " 22 | "the property have? ({})".format( 23 | ", ".join(Apartment.valid_laundries)) 24 | balcony = '' 25 | while balcony.lower() not in \ 26 | Apartment.valid_balconies: 27 | balcony = input( 28 | "Does the property have a balcony? " 29 | "({})".format( 30 | ", ".join(Apartment.valid_balconies)) 31 | parent_init.update({ 32 | "laundry": laundry, 33 | "balcony": balcony 34 | }) 35 | return parent_init 36 | prompt_init = staticmethod(prompt_init) 37 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_06_rockpaper.py: -------------------------------------------------------------------------------- 1 | from PyQt4 import QtGui 2 | import random 3 | 4 | app = QtGui.QApplication([]) 5 | 6 | choices = ["Rock", "Paper", "Scissors"] 7 | 8 | class RockPaperScissorsWidget(QtGui.QWidget): 9 | def __init__(self): 10 | super().__init__() 11 | rock = RPSButton("Rock", self) 12 | paper = RPSButton("Paper", self) 13 | scissors = RPSButton("Scissors", self) 14 | for button in (rock, paper, scissors): 15 | button.resize(100, 100) 16 | rock.move(0,0) 17 | paper.move(0,100) 18 | scissors.move(0,200) 19 | self.response = QtGui.QLabel("", self) 20 | self.response.setGeometry(110, 0, 200, 300) 21 | 22 | class RPSButton(QtGui.QPushButton): 23 | def mousePressEvent(self, event): 24 | computer_choice = random.choice(choices) 25 | user_choice = self.text() 26 | 27 | comp_idx = choices.index(computer_choice) 28 | user_idx = choices.index(user_choice) 29 | 30 | message = { 31 | 0: 'Tied', 32 | 1: 'Computer Wins', 33 | 2: 'You Win'}[(comp_idx - user_idx + 3) % 3] 34 | 35 | 36 | self.parent().response.setText("You chose {0}
" 37 | "Computer chose {1}
" 38 | "{2}".format(user_choice, computer_choice, message)) 39 | 40 | 41 | window = RockPaperScissorsWidget() 42 | window.show() 43 | app.exec_() 44 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_08_car_class.py: -------------------------------------------------------------------------------- 1 | import weakref 2 | 3 | class CarModel: 4 | _models = weakref.WeakValueDictionary() 5 | 6 | def __new__(cls, model_name, *args, **kwargs): 7 | model = cls._models.get(model_name) 8 | if not model: 9 | model = super().__new__(cls) 10 | cls._models[model_name] = model 11 | 12 | return model 13 | 14 | def __init__(self, model_name, air=False, tilt=False, 15 | cruise_control=False, power_locks=False, 16 | alloy_wheels=False, usb_charger=False): 17 | if not hasattr(self, "initted"): 18 | self.model_name = model_name 19 | self.air = air 20 | self.tilt = tilt 21 | self.cruise_control = cruise_control 22 | self.power_locks = power_locks 23 | self.alloy_wheels = alloy_wheels 24 | self.usb_charger = usb_charger 25 | self.initted=True 26 | 27 | def check_serial(self, serial_number): 28 | print("Sorry, we are unable to check " 29 | "the serial number {0} on the {1} " 30 | "at this time".format( 31 | serial_number, self.model_name)) 32 | 33 | class Car: 34 | def __init__(self, model, color, serial): 35 | self.model = model 36 | self.color = color 37 | self.serial = serial 38 | 39 | def check_serial(self): 40 | return self.model.check_serial(self.serial) 41 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_10_lxml_xpath.py: -------------------------------------------------------------------------------- 1 | from lxml.etree import fromstring 2 | 3 | with open("1267_12_07_html_document.html") as file: 4 | root = fromstring(file.read()) 5 | 6 | print("ROOT NODE") 7 | print("\ttag:", root.tag) 8 | print("\tnumber of children:", len(root)) 9 | print("\tchildren:", [c.tag for c in root.getchildren()]) 10 | head = root[0] 11 | print("HEAD NODE") 12 | print("\tfirst child:", head[0].tag) 13 | print("\tsecond_child:", head[1].tag) 14 | print("\tlink attributes:", head[1].attrib) 15 | article = root[1][1] 16 | print("ARTICLE NODE") 17 | print("\ttag:", article.tag) 18 | print("\ttext:", article.text) 19 | print("\tfirst child:", article[0].tag, article[0].text) 20 | print("\t\tem's tail:", article[0].tail) 21 | print("\tsecond child:", article[1].tag, article[1].text) 22 | print("\tstrong's tail:", article[1].tail) 23 | 24 | # XPath Selection 25 | print('search for child tag:', root.find('head')) 26 | print('search children recursively:', root.findall('.//em')) 27 | print('build path:', root.findtext('./body/article/em')) 28 | 29 | # lxml XPath selection 30 | print('xpath attribute:', root.xpath('//link[@href]')) 31 | print('xpath text filter:', root.xpath('//*[contains(em, "my")]')) 32 | print('xpath first child:', root.xpath('/html/body/article/em[1]')) 33 | 34 | # css select selection 35 | from lxml.cssselect import CSSSelector 36 | print('css class selector:', CSSSelector('.simple')(root)) 37 | print('css tag selector:', CSSSelector('em')(root)) 38 | -------------------------------------------------------------------------------- /1261_03_Code/1261_3_23_purchase_and_rental.py: -------------------------------------------------------------------------------- 1 | class Purchase: 2 | def __init__(self, price='', taxes='', **kwargs): 3 | super().__init__(**kwargs) 4 | self.price = price 5 | self.taxes = taxes 6 | 7 | def display(self): 8 | super().display() 9 | print("PURCHASE DETAILS") 10 | print("selling price: {}".format(self.price)) 11 | print("estimated taxes: {}".format(self.taxes)) 12 | 13 | def prompt_init(): 14 | return dict( 15 | price=input("What is the selling price? "), 16 | taxes=input("What are the estimated taxes? ")) 17 | prompt_init = staticmethod(prompt_init) 18 | 19 | class Rental: 20 | def __init__(self, furnished='', utilities='', 21 | rent='', **kwargs): 22 | super().__init__(**kwargs) 23 | self.furnished = furnished 24 | self.rent = rent 25 | self.utilities = utilities 26 | 27 | def display(self): 28 | super().display() 29 | print("RENTAL DETAILS") 30 | print("rent: {}".format(self.rent)) 31 | print("estimated utilities: {}".format( 32 | self.utilities)) 33 | print("furnished: {}".format(self.furnished)) 34 | 35 | def prompt_init(): 36 | return dict( 37 | rent=input("What is the monthly rent? "), 38 | utilities=input( 39 | "What are the estimated utilities? "), 40 | furnished = get_valid_input( 41 | "Is the property furnished? ", 42 | ("yes", "no"))) 43 | prompt_init = staticmethod(prompt_init) 44 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_21_template_concretes.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | class QueryTemplate: 4 | def connect(self): 5 | self.conn = sqlite3.connect("sales.db") 6 | 7 | def construct_query(self): 8 | raise NotImplementedError() 9 | 10 | def do_query(self): 11 | results = self.conn.execute(self.query) 12 | self.results = results.fetchall() 13 | 14 | def format_results(self): 15 | output = [] 16 | for row in self.results: 17 | row =[str(i) for i in row] 18 | output.append(", ".join(row)) 19 | self.formatted_results = "\n".join(output) 20 | 21 | def output_results(self): 22 | raise NotImplementedError() 23 | 24 | def process_format(self): 25 | self.connect() 26 | self.construct_query() 27 | self.do_query() 28 | self.format_results() 29 | self.output_results() 30 | 31 | import datetime 32 | class NewVehiclesQuery(QueryTemplate): 33 | def construct_query(self): 34 | self.query = "select * from Sales where new='true'" 35 | 36 | def output_results(self): 37 | print(self.formatted_results) 38 | 39 | class UserGrossQuery(QueryTemplate): 40 | def construct_query(self): 41 | self.query = ("select salesperson, sum(amt) " + 42 | " from Sales group by salesperson") 43 | 44 | def output_results(self): 45 | filename = "gross_sales_{0}".format( 46 | datetime.date.today().strftime("%Y%m%d") 47 | ) 48 | with open(filename, 'w') as outfile: 49 | outfile.write(self.formatted_results) 50 | -------------------------------------------------------------------------------- /1261_11_Code/casestudy/test_vigenere_cipher.py: -------------------------------------------------------------------------------- 1 | from vigenere_cipher import VigenereCipher 2 | from vigenere_cipher import combine_character 3 | from vigenere_cipher import separate_character 4 | 5 | def test_encode(): 6 | cipher = VigenereCipher("TRAIN") 7 | encoded = cipher.encode("ENCODEDINPYTHON") 8 | assert encoded == "XECWQXUIVCRKHWA" 9 | 10 | def test_encode_character(): 11 | cipher = VigenereCipher("TRAIN") 12 | encoded = cipher.encode("E") 13 | assert encoded == "X" 14 | 15 | def test_encode_spaces(): 16 | cipher = VigenereCipher("TRAIN") 17 | encoded = cipher.encode("ENCODED IN PYTHON") 18 | assert encoded == "XECWQXUIVCRKHWA" 19 | 20 | def test_encode_lowercase(): 21 | cipher = VigenereCipher("TRain") 22 | encoded = cipher.encode("encoded in Python") 23 | assert encoded == "XECWQXUIVCRKHWA" 24 | 25 | def test_combine_character(): 26 | assert combine_character("E", "T") == "X" 27 | assert combine_character("N", "R") == "E" 28 | 29 | def test_extend_keyword(): 30 | cipher = VigenereCipher("TRAIN") 31 | extended = cipher.extend_keyword(16) 32 | assert extended == "TRAINTRAINTRAINT" 33 | 34 | def test_extend_keyword_even(): 35 | cipher = VigenereCipher("TRAIN") 36 | extended = cipher.extend_keyword(15) 37 | assert extended == "TRAINTRAINTRAIN" 38 | 39 | def test_separate_character(): 40 | assert separate_character("X", "T") == "E" 41 | assert separate_character("E", "R") == "N" 42 | 43 | def test_decode(): 44 | cipher = VigenereCipher("TRAIN") 45 | decoded = cipher.decode("XECWQXUIVCRKHWA") 46 | assert decoded == "ENCODEDINPYTHON" 47 | -------------------------------------------------------------------------------- /1261_06_Code/link_collector.py: -------------------------------------------------------------------------------- 1 | from urllib.request import urlopen 2 | from urllib.parse import urlparse 3 | import re 4 | import sys 5 | LINK_REGEX = re.compile( 6 | "]*href=['\"]([^'\"]+)['\"][^>]*>") 7 | 8 | class LinkCollector: 9 | def __init__(self, url): 10 | self.url = "http://%s" % urlparse(url).netloc 11 | self.collected_links = {} 12 | self.visited_links = set() 13 | 14 | def collect_links(self, path="/"): 15 | full_url = self.url + path 16 | self.visited_links.add(full_url) 17 | page = str(urlopen(full_url).read()) 18 | links = LINK_REGEX.findall(page) 19 | links = {self.normalize_url(path, link 20 | ) for link in links} 21 | self.collected_links[full_url] = links 22 | for link in links: 23 | self.collected_links.setdefault(link, set()) 24 | unvisited_links = links.difference( 25 | self.visited_links) 26 | for link in unvisited_links: 27 | if link.startswith(self.url): 28 | self.collect_links(urlparse(link).path) 29 | 30 | def normalize_url(self, path, link): 31 | if link.startswith("http://"): 32 | return link 33 | elif link.startswith("/"): 34 | return self.url + link 35 | else: 36 | return self.url + path.rpartition('/' 37 | )[0] + '/' + link 38 | 39 | if __name__ == "__main__": 40 | collector = LinkCollector(sys.argv[1]) 41 | collector.collect_links() 42 | for link, item in collector.collected_links.items(): 43 | print("%s: %s" % (link, item)) 44 | -------------------------------------------------------------------------------- /1261_06_Code/1261_06_22_dict_link_collector.py: -------------------------------------------------------------------------------- 1 | from urllib.request import urlopen 2 | from urllib.parse import urlparse 3 | import re 4 | import sys 5 | LINK_REGEX = re.compile( 6 | "]*href=['\"]([^'\"]+)['\"][^>]*>") 7 | 8 | class LinkCollector: 9 | def __init__(self, url): 10 | self.url = "http://%s" % urlparse(url).netloc 11 | self.collected_links = {} 12 | self.visited_links = set() 13 | 14 | def collect_links(self, path="/"): 15 | full_url = self.url + path 16 | self.visited_links.add(full_url) 17 | page = str(urlopen(full_url).read()) 18 | links = LINK_REGEX.findall(page) 19 | links = {self.normalize_url(path, link 20 | ) for link in links} 21 | self.collected_links[full_url] = links 22 | for link in links: 23 | self.collected_links.setdefault(link, set()) 24 | unvisited_links = links.difference( 25 | self.visited_links) 26 | for link in unvisited_links: 27 | if link.startswith(self.url): 28 | self.collect_links(urlparse(link).path) 29 | 30 | def normalize_url(self, path, link): 31 | if link.startswith("http://"): 32 | return link 33 | elif link.startswith("/"): 34 | return self.url + link 35 | else: 36 | return self.url + path.rpartition('/' 37 | )[0] + '/' + link 38 | 39 | if __name__ == "__main__": 40 | collector = LinkCollector(sys.argv[1]) 41 | collector.collect_links() 42 | for link, item in collector.collected_links.items(): 43 | print("{}: {}".format(link, item)) 44 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_17_zipsearch.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import shutil 4 | import zipfile 5 | 6 | class ZipReplace: 7 | def __init__(self, filename, search_string, replace_string): 8 | self.filename = filename 9 | self.search_string = search_string 10 | self.replace_string = replace_string 11 | self.temp_directory = "unzipped-{}".format( 12 | filename) 13 | 14 | def _full_filename(self, filename): 15 | return os.path.join(self.temp_directory, filename) 16 | 17 | def zip_find_replace(self): 18 | self.unzip_files() 19 | self.find_replace() 20 | self.zip_files() 21 | 22 | def unzip_files(self): 23 | os.mkdir(self.temp_directory) 24 | zip = zipfile.ZipFile(self.filename) 25 | try: 26 | zip.extractall(self.temp_directory) 27 | finally: 28 | zip.close() 29 | 30 | def find_replace(self): 31 | for filename in os.listdir(self.temp_directory): 32 | with open(self._full_filename(filename)) as file: 33 | contents = file.read() 34 | contents = contents.replace( 35 | self.search_string, self.replace_string) 36 | with open(self._full_filename(filename), "w") as file: 37 | file.write(contents) 38 | 39 | def zip_files(self): 40 | file = zipfile.ZipFile(self.filename, 'w') 41 | for filename in os.listdir(self.temp_directory): 42 | file.write(self._full_filename(filename), filename) 43 | shutil.rmtree(self.temp_directory) 44 | 45 | if __name__ == "__main__": 46 | ZipReplace(*sys.argv[1:4]).zip_find_replace() 47 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_17_authenticator.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | class User: 4 | def __init__(self, username, password): 5 | '''Create a new user object. The password 6 | will be encrypted before storing.''' 7 | self.username = username 8 | self.password = self._encrypt_pw(password) 9 | self.is_logged_in = False 10 | 11 | def _encrypt_pw(self, password): 12 | '''Encrypt the password with the username and return 13 | the sha digest.''' 14 | hash_string = (self.username + password) 15 | hash_string = hash_string.encode("utf8") 16 | return hashlib.sha256(hash_string).hexdigest() 17 | 18 | def check_password(self, password): 19 | '''Return True if the password is valid for this 20 | user, false otherwise.''' 21 | encrypted = self._encrypt_pw(password) 22 | return encrypted == self.password 23 | 24 | 25 | class AuthException(Exception): 26 | def __init__(self, username, user=None): 27 | super().__init__(username) 28 | self.username = username 29 | self.user = user 30 | 31 | class UsernameAlreadyExists(AuthException): 32 | pass 33 | 34 | class PasswordTooShort(AuthException): 35 | pass 36 | 37 | class Authenticator: 38 | def __init__(self): 39 | '''Construct an authenticator to manage 40 | users logging in and out.''' 41 | self.users = {} 42 | 43 | def add_user(self, username, password): 44 | if username in self.users: 45 | raise UsernameAlreadyExists(username) 46 | if len(password) < 6: 47 | raise PasswordTooShort(username) 48 | self.users[username] = User(username, password) 49 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_11_window_command_commands.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Window: 4 | def exit(self): 5 | sys.exit(0) 6 | 7 | class Document: 8 | def __init__(self, filename): 9 | self.filename = filename 10 | self.contents = "This file cannot be modified" 11 | 12 | def save(self): 13 | with open(self.filename, 'w') as file: 14 | file.write(self.contents) 15 | 16 | class ToolbarButton: 17 | def __init__(self, name, iconname): 18 | self.name = name 19 | self.iconname = iconname 20 | 21 | def click(self): 22 | self.command.execute() 23 | 24 | class MenuItem: 25 | def __init__(self, menu_name, menuitem_name): 26 | self.menu = menu_name 27 | self.item = menuitem_name 28 | 29 | def click(self): 30 | self.command.execute() 31 | 32 | class KeyboardShortcut: 33 | def __init__(self, key, modifier): 34 | self.key = key 35 | self.modifier = modifier 36 | 37 | def keypress(self): 38 | self.command.execute() 39 | 40 | class SaveCommand: 41 | def __init__(self, document): 42 | self.document = document 43 | 44 | def execute(self): 45 | self.document.save() 46 | 47 | class ExitCommand: 48 | def __init__(self, window): 49 | self.window = window 50 | 51 | def execute(self): 52 | self.window.exit() 53 | 54 | window = Window() 55 | document = Document("a_document.txt") 56 | save = SaveCommand(document) 57 | exit = ExitCommand(window) 58 | 59 | save_button = ToolbarButton('save', 'save.png') 60 | save_button.command = save 61 | save_keystroke = KeyboardShortcut("s", "ctrl") 62 | save_keystroke.command = save 63 | exit_menu = MenuItem("File", "Exit") 64 | exit_menu.command = exit 65 | 66 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_14_formatters.py: -------------------------------------------------------------------------------- 1 | class FranceDateFormatter: 2 | def format_date(self, y, m, d): 3 | y, m, d = (str(x) for x in (y,m,d)) 4 | y = '20' + y if len(y) == 2 else y 5 | m = '0' + m if len(m) == 1 else m 6 | d = '0' + d if len(d) == 1 else d 7 | return("{0}/{1}/{2}".format(d,m,y)) 8 | 9 | class USADateFormatter: 10 | def format_date(self, y, m, d): 11 | y, m, d = (str(x) for x in (y,m,d)) 12 | y = '20' + y if len(y) == 2 else y 13 | m = '0' + m if len(m) == 1 else m 14 | d = '0' + d if len(d) == 1 else d 15 | return("{0}-{1}-{2}".format(m,d,y)) 16 | 17 | class FranceCurrencyFormatter: 18 | def format_currency(self, base, cents): 19 | base, cents = (str(x) for x in (base, cents)) 20 | if len(cents) == 0: 21 | cents = '00' 22 | elif len(cents) == 1: 23 | cents = '0' + cents 24 | 25 | digits = [] 26 | for i,c in enumerate(reversed(base)): 27 | if i and not i % 3: 28 | digits.append(' ') 29 | digits.append(c) 30 | base = ''.join(reversed(digits)) 31 | return "{0}€{1}".format(base, cents) 32 | 33 | class USACurrencyFormatter: 34 | def format_currency(self, base, cents): 35 | base, cents = (str(x) for x in (base, cents)) 36 | if len(cents) == 0: 37 | cents = '00' 38 | elif len(cents) == 1: 39 | cents = '0' + cents 40 | 41 | digits = [] 42 | for i,c in enumerate(reversed(base)): 43 | if i and not i % 3: 44 | digits.append(',') 45 | digits.append(c) 46 | base = ''.join(reversed(digits)) 47 | return "${0}.{1}".format(base, cents) 48 | 49 | -------------------------------------------------------------------------------- /1261_02_Code/menu.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from notebook import Notebook, Note 3 | 4 | class Menu: 5 | '''Display a menu and respond to choices when run.''' 6 | def __init__(self): 7 | self.notebook = Notebook() 8 | self.choices = { 9 | "1": self.show_notes, 10 | "2": self.search_notes, 11 | "3": self.add_note, 12 | "4": self.modify_note, 13 | "5": self.quit 14 | } 15 | 16 | def display_menu(self): 17 | print(""" 18 | Notebook Menu 19 | 20 | 1. Show all Notes 21 | 2. Search Notes 22 | 3. Add Note 23 | 4. Modify Note 24 | 5. Quit 25 | """) 26 | 27 | def run(self): 28 | '''Display the menu and respond to choices.''' 29 | while True: 30 | self.display_menu() 31 | choice = input("Enter an option: ") 32 | action = self.choices.get(choice) 33 | if action: 34 | action() 35 | else: 36 | print("{0} is not a valid choice".format(choice)) 37 | 38 | def show_notes(self, notes=None): 39 | if not notes: 40 | notes = self.notebook.notes 41 | for note in notes: 42 | print("{0}: {1}\n{2}".format( 43 | note.id, note.tags, note.memo)) 44 | 45 | def search_notes(self): 46 | filter = input("Search for: ") 47 | notes = self.notebook.search(filter) 48 | self.show_notes(notes) 49 | 50 | def add_note(self): 51 | memo = input("Enter a memo: ") 52 | self.notebook.new_note(memo) 53 | print("Your note has been added.") 54 | 55 | def modify_note(self): 56 | id = input("Enter a note id: ") 57 | memo = input("Enter a memo: ") 58 | tags = input("Enter tags: ") 59 | if memo: 60 | self.notebook.modify_memo(id, memo) 61 | if tags: 62 | self.notebook.modify_tags(id, tags) 63 | 64 | def quit(self): 65 | print("Thank you for using your notebook today.") 66 | sys.exit(0) 67 | 68 | if __name__ == "__main__": 69 | Menu().run() 70 | -------------------------------------------------------------------------------- /1261_05_Code/Document.py: -------------------------------------------------------------------------------- 1 | class Document: 2 | def __init__(self): 3 | self.characters = [] 4 | self.cursor = Cursor(self) 5 | self.filename = '' 6 | 7 | def insert(self, character): 8 | if not hasattr(character, 'character'): 9 | character = Character(character) 10 | self.characters.insert(self.cursor.position, 11 | character) 12 | self.cursor.forward() 13 | 14 | def delete(self): 15 | del self.characters[self.cursor.position] 16 | 17 | def save(self): 18 | f = open(self.filename, 'w') 19 | f.write(''.join(self.characters)) 20 | f.close() 21 | 22 | @property 23 | def string(self): 24 | return "".join((str(c) for c in self.characters)) 25 | 26 | 27 | class Cursor: 28 | def __init__(self, document): 29 | self.document = document 30 | self.position = 0 31 | 32 | def forward(self): 33 | self.position += 1 34 | 35 | def back(self): 36 | self.position -= 1 37 | 38 | def home(self): 39 | while self.document.characters[ 40 | self.position-1].character != '\n': 41 | self.position -= 1 42 | if self.position == 0: 43 | # Got to beginning of file before newline 44 | break 45 | 46 | def end(self): 47 | while self.position < len(self.document.characters) and \ 48 | self.document.characters[ 49 | self.position].character != '\n': 50 | self.position += 1 51 | 52 | class Character: 53 | def __init__(self, character, 54 | bold=False, italic=False, underline=False): 55 | assert len(character) == 1 56 | self.character = character 57 | self.bold = bold 58 | self.italic = italic 59 | self.underline = underline 60 | 61 | def __str__(self): 62 | bold = "*" if self.bold else '' 63 | italic = "/" if self.italic else '' 64 | underline = "_" if self.underline else '' 65 | return bold + italic + underline + self.character 66 | -------------------------------------------------------------------------------- /1261_02_Code/1261_2_18-notebook_menu.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from notebook import Notebook, Note 3 | 4 | class Menu: 5 | '''Display a menu and respond to choices when run.''' 6 | def __init__(self): 7 | self.notebook = Notebook() 8 | self.choices = { 9 | "1": self.show_notes, 10 | "2": self.search_notes, 11 | "3": self.add_note, 12 | "4": self.modify_note, 13 | "5": self.quit 14 | } 15 | 16 | def display_menu(self): 17 | print(""" 18 | Notebook Menu 19 | 20 | 1. Show all Notes 21 | 2. Search Notes 22 | 3. Add Note 23 | 4. Modify Note 24 | 5. Quit 25 | """) 26 | 27 | def run(self): 28 | '''Display the menu and respond to choices.''' 29 | while True: 30 | self.display_menu() 31 | choice = input("Enter an option: ") 32 | action = self.choices.get(choice) 33 | if action: 34 | action() 35 | else: 36 | print("{0} is not a valid choice".format(choice)) 37 | 38 | def show_notes(self, notes=None): 39 | if not notes: 40 | notes = self.notebook.notes 41 | for note in notes: 42 | print("{0}: {1}\n{2}".format( 43 | note.id, note.tags, note.memo)) 44 | 45 | def search_notes(self): 46 | filter = input("Search for: ") 47 | notes = self.notebook.search(filter) 48 | self.show_notes(notes) 49 | 50 | def add_note(self): 51 | memo = input("Enter a memo: ") 52 | self.notebook.new_note(memo) 53 | print("Your note has been added.") 54 | 55 | def modify_note(self): 56 | id = input("Enter a note id: ") 57 | memo = input("Enter a memo: ") 58 | tags = input("Enter tags: ") 59 | if memo: 60 | self.notebook.modify_memo(id, memo) 61 | if tags: 62 | self.notebook.modify_tags(id, tags) 63 | 64 | def quit(self): 65 | print("Thank you for using your notebook today.") 66 | sys.exit(0) 67 | 68 | if __name__ == "__main__": 69 | Menu().run() 70 | -------------------------------------------------------------------------------- /1261_05_Code/1261_05_29_document_with_character.py: -------------------------------------------------------------------------------- 1 | class Document: 2 | def __init__(self): 3 | self.characters = [] 4 | self.cursor = Cursor(self) 5 | self.filename = '' 6 | 7 | def insert(self, character): 8 | if not hasattr(character, 'character'): 9 | character = Character(character) 10 | self.characters.insert(self.cursor.position, 11 | character) 12 | self.cursor.forward() 13 | 14 | def delete(self): 15 | del self.characters[self.cursor.position] 16 | 17 | def save(self): 18 | f = open(self.filename, 'w') 19 | f.write(''.join(self.characters)) 20 | f.close() 21 | 22 | @property 23 | def string(self): 24 | return "".join((str(c) for c in self.characters)) 25 | 26 | 27 | class Cursor: 28 | def __init__(self, document): 29 | self.document = document 30 | self.position = 0 31 | 32 | def forward(self): 33 | self.position += 1 34 | 35 | def back(self): 36 | self.position -= 1 37 | 38 | def home(self): 39 | while self.document.characters[ 40 | self.position-1].character != '\n': 41 | self.position -= 1 42 | if self.position == 0: 43 | # Got to beginning of file before newline 44 | break 45 | 46 | def end(self): 47 | while self.position < len(self.document.characters) and \ 48 | self.document.characters[ 49 | self.position].character != '\n': 50 | self.position += 1 51 | 52 | class Character: 53 | def __init__(self, character, 54 | bold=False, italic=False, underline=False): 55 | assert len(character) == 1 56 | self.character = character 57 | self.bold = bold 58 | self.italic = italic 59 | self.underline = underline 60 | 61 | def __str__(self): 62 | bold = "*" if self.bold else '' 63 | italic = "/" if self.italic else '' 64 | underline = "_" if self.underline else '' 65 | return bold + italic + underline + self.character 66 | -------------------------------------------------------------------------------- /1261_09_Code/1261_09_15_formatter_factories.py: -------------------------------------------------------------------------------- 1 | class FranceDateFormatter: 2 | def format_date(self, y, m, d): 3 | y, m, d = (str(x) for x in (y,m,d)) 4 | y = '20' + y if len(y) == 2 else y 5 | m = '0' + m if len(m) == 1 else m 6 | d = '0' + d if len(d) == 1 else d 7 | return("{0}/{1}/{2}".format(d,m,y)) 8 | 9 | class USADateFormatter: 10 | def format_date(self, y, m, d): 11 | y, m, d = (str(x) for x in (y,m,d)) 12 | y = '20' + y if len(y) == 2 else y 13 | m = '0' + m if len(m) == 1 else m 14 | d = '0' + d if len(d) == 1 else d 15 | return("{0}-{1}-{2}".format(m,d,y)) 16 | 17 | class FranceCurrencyFormatter: 18 | def format_currency(self, base, cents): 19 | base, cents = (str(x) for x in (base, cents)) 20 | if len(cents) == 0: 21 | cents = '00' 22 | elif len(cents) == 1: 23 | cents = '0' + cents 24 | 25 | digits = [] 26 | for i,c in enumerate(reversed(base)): 27 | if i and not i % 3: 28 | digits.append(' ') 29 | digits.append(c) 30 | base = ''.join(reversed(digits)) 31 | return "{0}€{1}".format(base, cents) 32 | 33 | class USACurrencyFormatter: 34 | def format_currency(self, base, cents): 35 | base, cents = (str(x) for x in (base, cents)) 36 | if len(cents) == 0: 37 | cents = '00' 38 | elif len(cents) == 1: 39 | cents = '0' + cents 40 | 41 | digits = [] 42 | for i,c in enumerate(reversed(base)): 43 | if i and not i % 3: 44 | digits.append(',') 45 | digits.append(c) 46 | base = ''.join(reversed(digits)) 47 | return "${0}.{1}".format(base, cents) 48 | 49 | class USAFormatterFactory: 50 | def create_date_formatter(self): 51 | return USADateFormatter() 52 | def create_currency_formatter(self): 53 | return USACurrencyFormatter() 54 | 55 | class FranceFormatterFactory: 56 | def create_date_formatter(self): 57 | return FranceDateFormatter() 58 | def create_currency_formatter(self): 59 | return FranceCurrencyFormatter() 60 | 61 | country_code = "US" 62 | factory_map = { 63 | "US": USAFormatterFactory, 64 | "FR": FranceFormatterFactory} 65 | formatter_factory = factory_map.get(country_code)() 66 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_18_login.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | class User: 4 | def __init__(self, username, password): 5 | '''Create a new user object. The password 6 | will be encrypted before storing.''' 7 | self.username = username 8 | self.password = self._encrypt_pw(password) 9 | self.is_logged_in = False 10 | 11 | def _encrypt_pw(self, password): 12 | '''Encrypt the password with the username and return 13 | the sha digest.''' 14 | hash_string = (self.username + password) 15 | hash_string = hash_string.encode("utf8") 16 | return hashlib.sha256(hash_string).hexdigest() 17 | 18 | def check_password(self, password): 19 | '''Return True if the password is valid for this 20 | user, false otherwise.''' 21 | encrypted = self._encrypt_pw(password) 22 | return encrypted == self.password 23 | 24 | 25 | class AuthException(Exception): 26 | def __init__(self, username, user=None): 27 | super().__init__(username) 28 | self.username = username 29 | self.user = user 30 | 31 | class UsernameAlreadyExists(AuthException): 32 | pass 33 | 34 | class PasswordTooShort(AuthException): 35 | pass 36 | 37 | class InvalidUsername(AuthException): 38 | pass 39 | 40 | class InvalidPassword(AuthException): 41 | pass 42 | 43 | class Authenticator: 44 | def __init__(self): 45 | '''Construct an authenticator to manage 46 | users logging in and out.''' 47 | self.users = {} 48 | 49 | def add_user(self, username, password): 50 | if username in self.users: 51 | raise UsernameAlreadyExists(username) 52 | if len(password) < 6: 53 | raise PasswordTooShort(username) 54 | self.users[username] = User(username, password) 55 | 56 | def login(self, username, password): 57 | try: 58 | user = self.users[username] 59 | except KeyError: 60 | raise InvalidUsername(username) 61 | 62 | if not user.check_password(password): 63 | raise InvalidPassword(username, user) 64 | 65 | user.is_logged_in = True 66 | return True 67 | 68 | def is_logged_in(self, username): 69 | if username in self.users: 70 | return self.users[username].is_logged_in 71 | return False 72 | 73 | authenticator = Authenticator() 74 | -------------------------------------------------------------------------------- /1261_02_Code/notebook.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | # Store the next available id for all new notes 4 | last_id = 0 5 | 6 | class Note: 7 | '''Represent a note in the notebook. Match against a 8 | string in searches and store tags for each note.''' 9 | 10 | 11 | def __init__(self, memo, tags=''): 12 | '''initialize a note with memo and optional 13 | space-separated tags. Automatically set the note's 14 | creation date and a unique id''' 15 | self.memo = memo 16 | self.tags = tags 17 | self.creation_date = datetime.date.today() 18 | global last_id 19 | last_id += 1 20 | self.id = last_id 21 | 22 | def match(self, filter): 23 | '''Determine if this note matches the filter 24 | text. Return True if it matches, False otherwise. 25 | 26 | Search is case sensitive and matches both text and 27 | tags.''' 28 | return filter in self.memo or filter in self.tags 29 | 30 | class Notebook: 31 | '''Represent a collection of notes that can be tagged, 32 | modified, and searched.''' 33 | 34 | def __init__(self): 35 | '''Initialize a notebook with an empty list.''' 36 | self.notes = [] 37 | 38 | def new_note(self, memo, tags=''): 39 | '''Create a new note and add it to the list.''' 40 | self.notes.append(Note(memo, tags)) 41 | 42 | def _find_note(self, note_id): 43 | '''Locate the note with the given id.''' 44 | for note in self.notes: 45 | if str(note.id) == str(note_id): 46 | return note 47 | return None 48 | 49 | def modify_memo(self, note_id, memo): 50 | '''Find the note with the given id and change its 51 | memo to the given value.''' 52 | note = self._find_note(note_id) 53 | if note: 54 | note.memo = memo 55 | return True 56 | return False 57 | 58 | def modify_tags(self, note_id, tags): 59 | '''Find the note with the given id and change its 60 | tags to the given value.''' 61 | note = self._find_note(note_id) 62 | if note: 63 | note.tags = tags 64 | return True 65 | return False 66 | 67 | def search(self, filter): 68 | '''Find all notes that match the given filter 69 | string.''' 70 | return [note for note in self.notes if 71 | note.match(filter)] 72 | -------------------------------------------------------------------------------- /1261_12_Code/1267_12_14_blog.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import sqlalchemy as sqa 3 | from sqlalchemy.ext.declarative import declarative_base 4 | 5 | Base = declarative_base() 6 | 7 | class Article(Base): 8 | __tablename__ = "article" 9 | rowid = sqa.Column(sqa.Integer, primary_key=True) 10 | title = sqa.Column(sqa.String) 11 | message = sqa.Column(sqa.String) 12 | pub_date = sqa.Column(sqa.DateTime) 13 | 14 | def __init__(self, title, message): 15 | self.title = title 16 | self.message = message 17 | self.pub_date=datetime.datetime.now() 18 | 19 | class Comment(Base): 20 | __tablename__ = "comment" 21 | rowid = sqa.Column(sqa.Integer, primary_key=True) 22 | article_id = sqa.Column(sqa.Integer, 23 | sqa.ForeignKey('article.rowid')) 24 | article = sqa.orm.relationship(Article, backref="comments") 25 | name = sqa.Column(sqa.String) 26 | message = sqa.Column(sqa.String) 27 | 28 | def __init__(self, article_id, name, message): 29 | self.article_id = article_id 30 | self.name = name 31 | self.message = message 32 | 33 | 34 | engine = sqa.create_engine('sqlite:///blog.db') 35 | Base.metadata.create_all(engine) 36 | Session = sqa.orm.sessionmaker(bind=engine) 37 | 38 | import jinja2 39 | templates = jinja2.Environment(loader=jinja2.FileSystemLoader( 40 | 'blog_templates')) 41 | 42 | import cherrypy 43 | class Blog: 44 | @cherrypy.expose 45 | def index(self): 46 | session = Session() 47 | articles = session.query(Article).all() 48 | template = templates.get_template("index.html") 49 | content = template.render(articles=articles) 50 | session.close() 51 | return content 52 | 53 | @cherrypy.expose 54 | def add(self): 55 | template = templates.get_template("add.html") 56 | return template.render() 57 | 58 | @cherrypy.expose 59 | def process_add(self, title=None, message=None): 60 | session = Session() 61 | article = Article(title, message) 62 | session.add(article) 63 | session.commit() 64 | session.close() 65 | raise cherrypy.HTTPRedirect("/") 66 | 67 | @cherrypy.expose 68 | def process_comment(self, article_id, name=None, 69 | message=None): 70 | session = Session() 71 | comment = Comment(article_id, name, message) 72 | session.add(comment) 73 | session.commit() 74 | session.close() 75 | raise cherrypy.HTTPRedirect("/") 76 | 77 | cherrypy.quickstart(Blog()) 78 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_20_test_auth.py: -------------------------------------------------------------------------------- 1 | import auth 2 | 3 | # Set up a test user and permission 4 | auth.authenticator.add_user("joe", "joepassword") 5 | auth.authorizor.add_permission("test program") 6 | auth.authorizor.add_permission("change program") 7 | auth.authorizor.permit_user("test program", "joe") 8 | 9 | class Editor: 10 | def __init__(self): 11 | self.username = None 12 | self.menu_map = { 13 | "login": self.login, 14 | "test": self.test, 15 | "change": self.change, 16 | "quit": self.quit 17 | } 18 | 19 | def login(self): 20 | logged_in = False 21 | while not logged_in: 22 | username = input("username: ") 23 | password = input("password: ") 24 | try: 25 | logged_in = auth.authenticator.login( 26 | username, password) 27 | except auth.InvalidUsername: 28 | print("Sorry, that username does not exist") 29 | except auth.InvalidPassword: 30 | print("Sorry, incorrect password") 31 | else: 32 | self.username = username 33 | 34 | def is_permitted(self, permission): 35 | try: 36 | auth.authorizor.check_permission( 37 | permission, self.username) 38 | except auth.NotLoggedInError as e: 39 | print("{} is not logged in".format(e.username)) 40 | return False 41 | except auth.NotPermittedError as e: 42 | print("{} cannot {}".format( 43 | e.username, permission)) 44 | return False 45 | else: 46 | return True 47 | 48 | def test(self): 49 | if self.is_permitted("test program"): 50 | print("Testing program now...") 51 | 52 | def change(self): 53 | if self.is_permitted("change program"): 54 | print("Changing program now...") 55 | 56 | def quit(self): 57 | raise SystemExit() 58 | 59 | def menu(self): 60 | try: 61 | answer = "" 62 | while True: 63 | print(""" 64 | Please enter a command: 65 | \tlogin\tLogin 66 | \ttest\tTest the program 67 | \tchange\tChange the program 68 | \tquit\tQuit 69 | """) 70 | answer = input("enter a command: ").lower() 71 | try: 72 | func = self.menu_map[answer] 73 | except KeyError: 74 | print("{} is not a valid option".format( 75 | answer)) 76 | else: 77 | func() 78 | finally: 79 | print("Thank you for testing the auth module") 80 | 81 | 82 | Editor().menu() 83 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_15_xml_states.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, tag_name, parent=None): 3 | self.parent = parent 4 | self.tag_name = tag_name 5 | self.children = [] 6 | self.text="" 7 | 8 | def __str__(self): 9 | if self.text: 10 | return self.tag_name + ": " + self.text 11 | else: 12 | return self.tag_name 13 | 14 | class FirstTag: 15 | def process(self, remaining_string, parser): 16 | i_start_tag = remaining_string.find('<') 17 | i_end_tag = remaining_string.find('>') 18 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 19 | root = Node(tag_name) 20 | parser.root = parser.current_node = root 21 | parser.state = ChildNode() 22 | return remaining_string[i_end_tag+1:] 23 | 24 | class ChildNode: 25 | def process(self, remaining_string, parser): 26 | stripped = remaining_string.strip() 27 | if stripped.startswith("') 39 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 40 | node = Node(tag_name, parser.current_node) 41 | parser.current_node.children.append(node) 42 | parser.current_node = node 43 | parser.state = ChildNode() 44 | return remaining_string[i_end_tag+1:] 45 | 46 | class TextNode: 47 | def process(self, remaining_string, parser): 48 | i_start_tag = remaining_string.find('<') 49 | text = remaining_string[:i_start_tag] 50 | parser.current_node.text = text 51 | parser.state = ChildNode() 52 | return remaining_string[i_start_tag:] 53 | 54 | class CloseTag: 55 | def process(self, remaining_string, parser): 56 | i_start_tag = remaining_string.find('<') 57 | i_end_tag = remaining_string.find('>') 58 | assert remaining_string[i_start_tag+1] == "/" 59 | tag_name = remaining_string[i_start_tag+2:i_end_tag] 60 | assert tag_name == parser.current_node.tag_name 61 | parser.current_node = parser.current_node.parent 62 | parser.state = ChildNode() 63 | return remaining_string[i_end_tag+1:].strip() 64 | 65 | class Parser: 66 | def __init__(self, parse_string): 67 | self.parse_string = parse_string 68 | self.root = None 69 | self.current_node = None 70 | 71 | self.state = FirstTag() 72 | 73 | def process(self, remaining_string): 74 | remaining = self.state.process(remaining_string, self) 75 | if remaining: 76 | self.process(remaining) 77 | 78 | def start(self): 79 | self.process(self.parse_string) 80 | 81 | if __name__ == "__main__": 82 | import sys 83 | with open(sys.argv[1]) as file: 84 | contents = file.read() 85 | p = Parser(contents) 86 | p.start() 87 | 88 | nodes = [p.root] 89 | while nodes: 90 | node = nodes.pop(0) 91 | print(node) 92 | nodes = node.children + nodes 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /1261_08_Code/1261_08_17_xml_singletonstates.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, tag_name, parent=None): 3 | self.parent = parent 4 | self.tag_name = tag_name 5 | self.children = [] 6 | self.text="" 7 | 8 | def __str__(self): 9 | if self.text: 10 | return self.tag_name + ": " + self.text 11 | else: 12 | return self.tag_name 13 | 14 | class FirstTag: 15 | def process(self, remaining_string, parser): 16 | i_start_tag = remaining_string.find('<') 17 | i_end_tag = remaining_string.find('>') 18 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 19 | root = Node(tag_name) 20 | parser.root = parser.current_node = root 21 | parser.state = child_node 22 | return remaining_string[i_end_tag+1:] 23 | 24 | class ChildNode: 25 | def process(self, remaining_string, parser): 26 | stripped = remaining_string.strip() 27 | if stripped.startswith("') 39 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 40 | node = Node(tag_name, parser.current_node) 41 | parser.current_node.children.append(node) 42 | parser.current_node = node 43 | parser.state = child_node 44 | return remaining_string[i_end_tag+1:] 45 | 46 | class TextNode: 47 | def process(self, remaining_string, parser): 48 | i_start_tag = remaining_string.find('<') 49 | text = remaining_string[:i_start_tag] 50 | parser.current_node.text = text 51 | parser.state = child_node 52 | return remaining_string[i_start_tag:] 53 | 54 | class CloseTag: 55 | def process(self, remaining_string, parser): 56 | i_start_tag = remaining_string.find('<') 57 | i_end_tag = remaining_string.find('>') 58 | assert remaining_string[i_start_tag+1] == "/" 59 | tag_name = remaining_string[i_start_tag+2:i_end_tag] 60 | assert tag_name == parser.current_node.tag_name 61 | parser.current_node = parser.current_node.parent 62 | parser.state = child_node 63 | return remaining_string[i_end_tag+1:].strip() 64 | 65 | first_tag = FirstTag() 66 | child_node = ChildNode() 67 | text_node = TextNode() 68 | open_tag = OpenTag() 69 | close_tag = CloseTag() 70 | 71 | class Parser: 72 | def __init__(self, parse_string): 73 | self.parse_string = parse_string 74 | self.root = None 75 | self.current_node = None 76 | 77 | self.state = first_tag 78 | 79 | def process(self, remaining_string): 80 | remaining = self.state.process(remaining_string, self) 81 | if remaining: 82 | self.process(remaining) 83 | 84 | def start(self): 85 | self.process(self.parse_string) 86 | 87 | if __name__ == "__main__": 88 | import sys 89 | with open(sys.argv[1]) as file: 90 | contents = file.read() 91 | p = Parser(contents) 92 | p.start() 93 | 94 | nodes = [p.root] 95 | while nodes: 96 | node = nodes.pop(0) 97 | print(node) 98 | nodes = node.children + nodes 99 | -------------------------------------------------------------------------------- /1261_08_Code/oldsing: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, tag_name, parent=None): 3 | self.parent = parent 4 | self.tag_name = tag_name 5 | self.children = [] 6 | self.text="" 7 | 8 | def __str__(self): 9 | if self.text: 10 | return self.tag_name + ": " + self.text 11 | else: 12 | return self.tag_name 13 | 14 | class FirstTag: 15 | def process(self, remaining_string, parser): 16 | i_start_tag = remaining_string.find('<') 17 | i_end_tag = remaining_string.find('>') 18 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 19 | root = Node(tag_name) 20 | parser.root = parser.current_node = root 21 | parser.state = child_node 22 | parser.process(remaining_string[i_end_tag+1:]) 23 | 24 | class ChildNode: 25 | def process(self, remaining_string, parser): 26 | stripped = remaining_string.strip() 27 | if stripped.startswith("') 39 | tag_name = remaining_string[i_start_tag+1:i_end_tag] 40 | node = Node(tag_name, parser.current_node) 41 | parser.current_node.children.append(node) 42 | parser.current_node = node 43 | parser.state = child_node 44 | parser.process(remaining_string[i_end_tag+1:]) 45 | 46 | class TextNode: 47 | def process(self, remaining_string, parser): 48 | i_start_tag = remaining_string.find('<') 49 | text = remaining_string[:i_start_tag] 50 | parser.current_node.text = text 51 | parser.state = child_node 52 | parser.process(remaining_string[i_start_tag:]) 53 | 54 | class CloseTag: 55 | def process(self, remaining_string, parser): 56 | i_start_tag = remaining_string.find('<') 57 | i_end_tag = remaining_string.find('>') 58 | assert remaining_string[i_start_tag+1] == "/" 59 | tag_name = remaining_string[i_start_tag+2:i_end_tag] 60 | assert tag_name == parser.current_node.tag_name 61 | parser.current_node = parser.current_node.parent 62 | parser.state = child_node 63 | if parser.current_node: 64 | parser.process(remaining_string[i_end_tag+1:]) 65 | 66 | first_tag = FirstTag() 67 | child_node = ChildNode() 68 | text_node = TextNode() 69 | open_tag = OpenTag() 70 | close_tag = CloseTag() 71 | 72 | class Parser: 73 | def __init__(self, parse_string): 74 | self.parse_string = parse_string 75 | self.root = None 76 | self.current_node = None 77 | 78 | self.state = first_tag 79 | 80 | def process(self, remaining_string): 81 | self.state.process(remaining_string, self) 82 | 83 | def start(self): 84 | self.process(self.parse_string) 85 | 86 | if __name__ == "__main__": 87 | import sys 88 | with open(sys.argv[1]) as file: 89 | contents = file.read() 90 | p = Parser(contents) 91 | p.start() 92 | 93 | nodes = [p.root] 94 | while nodes: 95 | node = nodes.pop(0) 96 | print(node) 97 | nodes = node.children + nodes 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /1261_04_Code/auth.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | class User: 4 | def __init__(self, username, password): 5 | '''Create a new user object. The password 6 | will be encrypted before storing.''' 7 | self.username = username 8 | self.password = self._encrypt_pw(password) 9 | self.is_logged_in = False 10 | 11 | def _encrypt_pw(self, password): 12 | '''Encrypt the password with the username and return 13 | the sha digest.''' 14 | hash_string = (self.username + password) 15 | hash_string = hash_string.encode("utf8") 16 | return hashlib.sha256(hash_string).hexdigest() 17 | 18 | def check_password(self, password): 19 | '''Return True if the password is valid for this 20 | user, false otherwise.''' 21 | encrypted = self._encrypt_pw(password) 22 | return encrypted == self.password 23 | 24 | class AuthException(Exception): 25 | def __init__(self, username, user=None): 26 | super().__init__(username) 27 | self.username = username 28 | self.user = user 29 | 30 | class UsernameAlreadyExists(AuthException): 31 | pass 32 | 33 | class PasswordTooShort(AuthException): 34 | pass 35 | 36 | class InvalidUsername(AuthException): 37 | pass 38 | 39 | class InvalidPassword(AuthException): 40 | pass 41 | 42 | class PermissionError(Exception): 43 | pass 44 | 45 | class NotLoggedInError(AuthException): 46 | pass 47 | 48 | class NotPermittedError(AuthException): 49 | pass 50 | 51 | class Authenticator: 52 | def __init__(self): 53 | '''Construct an authenticator to manage 54 | users logging in and out.''' 55 | self.users = {} 56 | 57 | def add_user(self, username, password): 58 | if username in self.users: 59 | raise UsernameAlreadyExists(username) 60 | if len(password) < 6: 61 | raise PasswordTooShort(username) 62 | self.users[username] = User(username, password) 63 | 64 | def login(self, username, password): 65 | try: 66 | user = self.users[username] 67 | except KeyError: 68 | raise InvalidUsername(username) 69 | 70 | if not user.check_password(password): 71 | raise InvalidPassword(username, user) 72 | 73 | user.is_logged_in = True 74 | return True 75 | 76 | def is_logged_in(self, username): 77 | if username in self.users: 78 | return self.users[username].is_logged_in 79 | return False 80 | 81 | class Authorizor: 82 | def __init__(self, authenticator): 83 | self.authenticator = authenticator 84 | self.permissions = {} 85 | 86 | def add_permission(self, perm_name): 87 | '''Create a new permission that users 88 | can be added to''' 89 | try: 90 | perm_set = self.permissions[perm_name] 91 | except KeyError: 92 | self.permissions[perm_name] = set() 93 | else: 94 | raise PermissionError("Permission Exists") 95 | 96 | def permit_user(self, perm_name, username): 97 | '''Grant the given permission to the user''' 98 | try: 99 | perm_set = self.permissions[perm_name] 100 | except KeyError: 101 | raise PermissionError("Permission does not exist") 102 | else: 103 | if username not in self.authenticator.users: 104 | raise InvalidUsername(username) 105 | perm_set.add(username) 106 | 107 | def check_permission(self, perm_name, username): 108 | if not self.authenticator.is_logged_in(username): 109 | raise NotLoggedInError(username) 110 | try: 111 | perm_set = self.permissions[perm_name] 112 | except KeyError: 113 | raise PermissionError("Permission does not exist") 114 | else: 115 | if username not in perm_set: 116 | raise NotPermittedError(username) 117 | else: 118 | return True 119 | 120 | 121 | 122 | authenticator = Authenticator() 123 | authorizor = Authorizor(authenticator) 124 | -------------------------------------------------------------------------------- /1261_04_Code/1261_04_19_authorizor.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | class User: 4 | def __init__(self, username, password): 5 | '''Create a new user object. The password 6 | will be encrypted before storing.''' 7 | self.username = username 8 | self.password = self._encrypt_pw(password) 9 | self.is_logged_in = False 10 | 11 | def _encrypt_pw(self, password): 12 | '''Encrypt the password with the username and return 13 | the sha digest.''' 14 | hash_string = (self.username + password) 15 | hash_string = hash_string.encode("utf8") 16 | return hashlib.sha256(hash_string).hexdigest() 17 | 18 | def check_password(self, password): 19 | '''Return True if the password is valid for this 20 | user, false otherwise.''' 21 | encrypted = self._encrypt_pw(password) 22 | return encrypted == self.password 23 | 24 | class AuthException(Exception): 25 | def __init__(self, username, user=None): 26 | super().__init__(username) 27 | self.username = username 28 | self.user = user 29 | 30 | class UsernameAlreadyExists(AuthException): 31 | pass 32 | 33 | class PasswordTooShort(AuthException): 34 | pass 35 | 36 | class InvalidUsername(AuthException): 37 | pass 38 | 39 | class InvalidPassword(AuthException): 40 | pass 41 | 42 | class PermissionError(Exception): 43 | pass 44 | 45 | class NotLoggedInError(AuthException): 46 | pass 47 | 48 | class NotPermittedError(AuthException): 49 | pass 50 | 51 | class Authenticator: 52 | def __init__(self): 53 | '''Construct an authenticator to manage 54 | users logging in and out.''' 55 | self.users = {} 56 | 57 | def add_user(self, username, password): 58 | if username in self.users: 59 | raise UsernameAlreadyExists(username) 60 | if len(password) < 6: 61 | raise PasswordTooShort(username) 62 | self.users[username] = User(username, password) 63 | 64 | def login(self, username, password): 65 | try: 66 | user = self.users[username] 67 | except KeyError: 68 | raise InvalidUsername(username) 69 | 70 | if not user.check_password(password): 71 | raise InvalidPassword(username, user) 72 | 73 | user.is_logged_in = True 74 | return True 75 | 76 | def is_logged_in(self, username): 77 | if username in self.users: 78 | return self.users[username].is_logged_in 79 | return False 80 | 81 | class Authorizor: 82 | def __init__(self, authenticator): 83 | self.authenticator = authenticator 84 | self.permissions = {} 85 | 86 | def add_permission(self, perm_name): 87 | '''Create a new permission that users 88 | can be added to''' 89 | try: 90 | perm_set = self.permissions[perm_name] 91 | except KeyError: 92 | self.permissions[perm_name] = set() 93 | else: 94 | raise PermissionError("Permission Exists") 95 | 96 | def permit_user(self, perm_name, username): 97 | '''Grant the given permission to the user''' 98 | try: 99 | perm_set = self.permissions[perm_name] 100 | except KeyError: 101 | raise PermissionError("Permission does not exist") 102 | else: 103 | if username not in self.authenticator.users: 104 | raise InvalidUsername(username) 105 | perm_set.add(username) 106 | 107 | def check_permission(self, perm_name, username): 108 | if not self.authenticator.is_logged_in(username): 109 | raise NotLoggedInError(username) 110 | try: 111 | perm_set = self.permissions[perm_name] 112 | except KeyError: 113 | raise PermissionError("Permission does not exist") 114 | else: 115 | if username not in perm_set: 116 | raise NotPermittedError(username) 117 | else: 118 | return True 119 | 120 | 121 | 122 | authenticator = Authenticator() 123 | authorizor = Authorizor(authenticator) 124 | -------------------------------------------------------------------------------- /1261_03_Code/final_case_study.py: -------------------------------------------------------------------------------- 1 | class Property: 2 | def __init__(self, square_feet='', beds='', 3 | baths='', **kwargs): 4 | super().__init__(**kwargs) 5 | self.square_feet = square_feet 6 | self.num_bedrooms = beds 7 | self.num_baths = baths 8 | 9 | def display(self): 10 | print("PROPERTY DETAILS") 11 | print("================") 12 | print("square footage: {}".format(self.square_feet)) 13 | print("bedrooms: {}".format(self.num_bedrooms)) 14 | print("bathrooms: {}".format(self.num_baths)) 15 | print() 16 | 17 | def prompt_init(): 18 | return dict(square_feet=input("Enter the square feet: "), 19 | beds=input("Enter number of bedrooms: "), 20 | baths=input("Enter number of baths: ")) 21 | prompt_init = staticmethod(prompt_init) 22 | 23 | def get_valid_input(input_string, valid_options): 24 | input_string += " ({}) ".format((", ".join(valid_options))) 25 | response = input(input_string) 26 | while response.lower() not in valid_options: 27 | response = input(input_string) 28 | return response 29 | 30 | class Apartment(Property): 31 | valid_laundries = ("coin", "ensuite", "none") 32 | valid_balconies = ("yes", "no", "solarium") 33 | 34 | def __init__(self, balcony='', laundry='', **kwargs): 35 | super().__init__(**kwargs) 36 | self.balcony = balcony 37 | self.laundry = laundry 38 | 39 | def display(self): 40 | super().display() 41 | print("APARTMENT DETAILS") 42 | print("laundry: {}".format(self.laundry)) 43 | print("has balcony: {}".format(self.balcony)) 44 | 45 | def prompt_init(): 46 | parent_init = Property.prompt_init() 47 | laundry = get_valid_input( 48 | "What laundry facilities does " 49 | "the property have? ", 50 | Apartment.valid_laundries) 51 | balcony = get_valid_input( 52 | "Does the property have a balcony?", 53 | Apartment.valid_balconies) 54 | parent_init.update({ 55 | "laundry": laundry, 56 | "balcony": balcony 57 | }) 58 | return parent_init 59 | prompt_init = staticmethod(prompt_init) 60 | 61 | class House(Property): 62 | valid_garage = ("attached", "detached", "none") 63 | valid_fenced = ("yes", "no") 64 | 65 | def __init__(self, num_stories='', 66 | garage='', fenced='', **kwargs): 67 | super().__init__(**kwargs) 68 | self.garage = garage 69 | self.fenced = fenced 70 | self.num_stories = num_stories 71 | 72 | def display(self): 73 | super().display() 74 | print("HOUSE DETAILS") 75 | print("# of stories: {}".format(self.num_stories)) 76 | print("garage: {}".format(self.garage)) 77 | print("fenced yard: {}".format(self.fenced)) 78 | 79 | def prompt_init(): 80 | parent_init = Property.prompt_init() 81 | fenced = get_valid_input("Is the yard fenced? ", 82 | House.valid_fenced) 83 | garage = get_valid_input("Is there a garage? ", 84 | House.valid_garage) 85 | num_stories = input("How many stories? ") 86 | 87 | parent_init.update({ 88 | "fenced": fenced, 89 | "garage": garage, 90 | "num_stories": num_stories 91 | }) 92 | return parent_init 93 | prompt_init = staticmethod(prompt_init) 94 | 95 | class Purchase: 96 | def __init__(self, price='', taxes='', **kwargs): 97 | super().__init__(**kwargs) 98 | self.price = price 99 | self.taxes = taxes 100 | 101 | def display(self): 102 | super().display() 103 | print("PURCHASE DETAILS") 104 | print("selling price: {}".format(self.price)) 105 | print("estimated taxes: {}".format(self.taxes)) 106 | 107 | def prompt_init(): 108 | return dict( 109 | price=input("What is the selling price? "), 110 | taxes=input("What are the estimated taxes? ")) 111 | prompt_init = staticmethod(prompt_init) 112 | 113 | class Rental: 114 | def __init__(self, furnished='', utilities='', 115 | rent='', **kwargs): 116 | super().__init__(**kwargs) 117 | self.furnished = furnished 118 | self.rent = rent 119 | self.utilities = utilities 120 | 121 | def display(self): 122 | super().display() 123 | print("RENTAL DETAILS") 124 | print("rent: {}".format(self.rent)) 125 | print("estimated utilities: {}".format(self.utilities)) 126 | print("furnished: {}".format(self.furnished)) 127 | 128 | def prompt_init(): 129 | return dict( 130 | rent=input("What is the monthly rent? "), 131 | utilities=input("What are the estimated utilities? "), 132 | furnished = get_valid_input("Is the property furnished? ", 133 | ("yes", "no"))) 134 | prompt_init = staticmethod(prompt_init) 135 | 136 | class HouseRental(Rental, House): 137 | def prompt_init(): 138 | init = House.prompt_init() 139 | init.update(Rental.prompt_init()) 140 | return init 141 | prompt_init = staticmethod(prompt_init) 142 | 143 | class ApartmentRental(Rental, Apartment): 144 | def prompt_init(): 145 | init = Apartment.prompt_init() 146 | init.update(Rental.prompt_init()) 147 | return init 148 | prompt_init = staticmethod(prompt_init) 149 | 150 | class ApartmentPurchase(Purchase, Apartment): 151 | def prompt_init(): 152 | init = Apartment.prompt_init() 153 | init.update(Purchase.prompt_init()) 154 | return init 155 | prompt_init = staticmethod(prompt_init) 156 | 157 | class HousePurchase(Purchase, House): 158 | def prompt_init(): 159 | init = House.prompt_init() 160 | init.update(Purchase.prompt_init()) 161 | return init 162 | prompt_init = staticmethod(prompt_init) 163 | 164 | class Agent: 165 | type_map = { 166 | ("house", "rental"): HouseRental, 167 | ("house", "purchase"): HousePurchase, 168 | ("apartment", "rental"): ApartmentRental, 169 | ("apartment", "purchase"): ApartmentPurchase 170 | } 171 | def __init__(self): 172 | self.property_list = [] 173 | 174 | def display_properties(self): 175 | for property in self.property_list: 176 | property.display() 177 | 178 | def add_property(self): 179 | property_type = get_valid_input( 180 | "What type of property? ", 181 | ("house", "apartment")).lower() 182 | payment_type = get_valid_input( 183 | "What payment type? ", 184 | ("purchase", "rental")).lower() 185 | 186 | PropertyClass = self.type_map[(property_type, payment_type)] 187 | init_args = PropertyClass.prompt_init() 188 | self.property_list.append(PropertyClass(**init_args)) 189 | --------------------------------------------------------------------------------