├── .gitignore ├── LICENSE ├── README.md ├── days ├── 01-03-datetimes │ ├── README.md │ └── code │ │ ├── datetime_date.py │ │ └── datetime_timedelta.py ├── 04-06-collections │ ├── README.md │ └── collections.ipynb ├── 07-09-data-structures │ ├── README.md │ └── code │ │ ├── commands.py │ │ └── data.py ├── 10-12-pytest │ ├── README.md │ ├── fizzbuzz │ │ ├── fizzbuzz.py │ │ └── test_fizzbuzz.py │ ├── guess │ │ ├── guess.py │ │ └── test_guess.py │ └── requirements.txt ├── 100-freestyle │ └── README.md ├── 13-15-text-games │ ├── README.md │ ├── data │ │ ├── battle-table.csv │ │ └── sample_reader.py │ ├── dnd_game │ │ ├── actors.py │ │ └── program.py │ └── rps15.jpg ├── 16-18-listcomprehensions-generators │ ├── README.md │ └── list-comprehensions-generators.ipynb ├── 19-21-itertools │ ├── README.md │ └── code │ │ ├── cycle_demo.py │ │ ├── permutations.py │ │ ├── spinner.py │ │ └── traffic_lights.py ├── 22-24-decorators │ ├── README.md │ ├── decorators.ipynb │ └── stacking.png ├── 25-27-error-handling │ ├── README.md │ └── demo │ │ ├── movie_search_error_edition │ │ ├── api.py │ │ ├── program.py │ │ └── requirements.txt │ │ └── starter_movie_search_error_edition │ │ ├── api.py │ │ ├── program.py │ │ └── requirements.txt ├── 28-30-regex │ ├── README.md │ └── regex.ipynb ├── 31-33-logging │ ├── README.md │ └── demo │ │ ├── movie_search_logging_edition │ │ ├── api.py │ │ ├── program.py │ │ └── requirements.txt │ │ └── starter_movie_search │ │ ├── api.py │ │ ├── program.py │ │ └── requirements.txt ├── 34-36-refactoring │ ├── README.md │ ├── coding-horror.gif │ ├── refactoring.ipynb │ └── strings.png ├── 37-39-csv-data-analysis │ ├── README.md │ └── weather_csv_demo │ │ ├── data │ │ └── seattle.csv │ │ ├── program.py │ │ └── research.py ├── 40-42-json-data │ ├── README.md │ └── code │ │ ├── json_dicts.py │ │ ├── json_requests.py │ │ ├── mount-data.json │ │ └── mount-data.txt ├── 43-45-search-api │ ├── README.md │ ├── demo │ │ └── movie_search │ │ │ ├── api.py │ │ │ ├── program.py │ │ │ └── requirements.txt │ └── readme_resources │ │ ├── post-sm.jpg │ │ └── post.png ├── 46-48-beautifulsoup4 │ ├── README.md │ └── scraper_demo │ │ ├── scraper.py │ │ └── shell_commands.py ├── 49-51-measuring-perf │ ├── README.md │ └── demo │ │ ├── final_csv_code │ │ ├── data │ │ │ └── seattle.csv │ │ ├── program.py │ │ ├── program_pycharm.py │ │ └── research.py │ │ └── starter_csv_code │ │ ├── data │ │ └── seattle.csv │ │ ├── program.py │ │ └── research.py ├── 52-54-feedparser │ ├── README.md │ └── code │ │ ├── parser.py │ │ └── pull_xml.py ├── 55-57-uplink │ ├── README.md │ └── demo │ │ ├── blog_client.py │ │ ├── program.py │ │ ├── requirements.txt │ │ └── uplink_helpers.py ├── 58-60-twitter-api │ ├── README.md │ ├── pybites.png │ ├── twitter-api.ipynb │ └── wordcloud-image.png ├── 61-63-github-api │ ├── README.md │ ├── github-api.ipynb │ └── images │ │ ├── my_gist.png │ │ ├── token1.png │ │ ├── token2.png │ │ └── token3.png ├── 64-66-email-smtplib │ ├── README.md │ └── code │ │ ├── emailer-mime.py │ │ └── emailer.py ├── 67-69-pyperclip │ ├── README.md │ └── code │ │ ├── affiliate.py │ │ └── text-replacer.py ├── 70-72-openpyxl-excel-automation │ ├── README.md │ └── code │ │ ├── Financial Sample.xlsx │ │ ├── excel_automation.py │ │ └── openpyxl_commands.py ├── 73-75-selenium │ ├── README.md │ ├── images │ │ ├── banner1.png │ │ ├── banner2.png │ │ ├── banner3.png │ │ ├── banner4.png │ │ ├── banner5.png │ │ ├── packt1.png │ │ ├── packt2.png │ │ ├── packt3.png │ │ └── packt4.png │ └── python-selenium.ipynb ├── 76-78-flask │ ├── README.md │ └── flask-code │ │ ├── app.py │ │ ├── data.py │ │ └── templates │ │ └── index.html ├── 79-81-sqlite3 │ ├── README.md │ ├── code │ │ └── simpledb.py │ └── demos │ │ ├── generatedb.py │ │ └── populatedb.py ├── 82-84-dataviz-plotly │ ├── README.md │ ├── data-viz.ipynb │ └── images │ │ ├── plot1.png │ │ ├── plot2.png │ │ └── plot3.png ├── 85-87-full-stack-easy │ ├── README.md │ ├── pypoint-100days │ │ ├── README.md │ │ ├── anvil.yaml │ │ ├── forms │ │ │ ├── AddDocForm.py │ │ │ ├── AddDocForm.yaml │ │ │ ├── AllDocsForm.py │ │ │ ├── AllDocsForm.yaml │ │ │ ├── DocDetailsForm.py │ │ │ ├── DocDetailsForm.yaml │ │ │ ├── DocListItemTemplate.py │ │ │ ├── DocListItemTemplate.yaml │ │ │ ├── HomeDetailsForm.py │ │ │ ├── HomeDetailsForm.yaml │ │ │ ├── HomeForm.py │ │ │ └── HomeForm.yaml │ │ ├── modules │ │ │ └── utilities.py │ │ ├── server_modules │ │ │ └── data_layer.py │ │ └── theme │ │ │ ├── assets │ │ │ ├── dashboard.html │ │ │ ├── single-column.html │ │ │ └── theme.css │ │ │ ├── parameters.yaml │ │ │ └── templates.yaml │ └── readme_resources │ │ ├── code.png │ │ ├── edit-ui.png │ │ ├── pub.png │ │ ├── register.png │ │ └── tables.png ├── 88-90-home-inventory-app │ ├── README.md │ └── code │ │ └── inventory.py ├── 91-93-sqlalchemy │ ├── README.md │ └── demo │ │ ├── persistent_rps │ │ ├── battle-table.csv │ │ ├── data │ │ │ └── session_factory.py │ │ ├── db │ │ │ └── db_folder.py │ │ ├── game.py │ │ ├── game_decider.py │ │ ├── game_service.py │ │ ├── models │ │ │ ├── model_base.py │ │ │ ├── move.py │ │ │ ├── player.py │ │ │ └── roll.py │ │ ├── program.py │ │ └── requirements.txt │ │ └── persistent_rps_starter │ │ ├── battle-table.csv │ │ ├── game.py │ │ ├── game_decider.py │ │ ├── game_service.py │ │ ├── models │ │ ├── move.py │ │ ├── player.py │ │ └── roll.py │ │ └── program.py ├── 94-96-guis │ ├── README.md │ ├── demos │ │ ├── final_search_app │ │ │ ├── api.py │ │ │ ├── build.spec │ │ │ ├── program.py │ │ │ └── requirements.txt │ │ └── starter_search_app │ │ │ ├── api.py │ │ │ ├── program.py │ │ │ └── requirements.txt │ └── readme_resources │ │ └── app.png └── 97-99-online-game-api │ ├── README.md │ └── demo_app │ ├── client │ ├── api.py │ ├── game_app.py │ ├── requirements.txt │ └── uplink_helpers.py │ └── web │ ├── app.py │ ├── data │ ├── battle-table.csv │ └── db_folder.py │ ├── game_logic │ ├── game.py │ ├── game_decider.py │ ├── game_service.py │ ├── models │ │ ├── model_base.py │ │ ├── move.py │ │ ├── player.py │ │ └── roll.py │ └── session_factory.py │ ├── requirements.txt │ └── views │ ├── game_api.py │ └── home.py ├── readme_resources ├── 100days-course-flow.png └── 100days-course.png ├── requirements ├── bob-environment.yml └── bob-requirements.txt └── transcripts ├── 00-intro ├── 1.txt ├── 10.txt ├── 100days-marketing-video.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 01-datetimes ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt └── 5.txt ├── 04-collections ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 07-data-structures ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt └── 6.txt ├── 10-testing ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 100-day-one-hundred └── 1.txt ├── 101-conclusion ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt └── 6.txt ├── 13-text-games ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 16-comprehensions ├── 1.txt ├── 10.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 19-iterators ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 22-decorators ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 25-errors ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 28-regex ├── 1.txt ├── 10.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 31-logging ├── 1.txt ├── 10.txt ├── 11.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 34-refactoring ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 14.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 37-csv_data ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 40-json ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt └── 6.txt ├── 43-search-api ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 46-beautifulsoup4 ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 49-measuring-perf ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 52-feedparser ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt └── 7.txt ├── 55-uplink ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 14.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 58-tweepy ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 61-github ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 64-email-smtplib ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 67-pyperclip ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt └── 7.txt ├── 70-openpyxl ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 73-selenium ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 76-flask-app ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt └── 6.txt ├── 79-sqlite3 ├── 1.txt ├── 10.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 82-dataviz ├── 1.txt ├── 10.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 85-anvil ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 14.txt ├── 15.txt ├── 16.txt ├── 17.txt ├── 18.txt ├── 19.txt ├── 2.txt ├── 20.txt ├── 21.txt ├── 22.txt ├── 23.txt ├── 24.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 88-home-inventory-app ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt └── 8.txt ├── 900-appendix-pylang ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 14.txt ├── 15.txt ├── 16.txt ├── 17.txt ├── 18.txt ├── 19.txt ├── 2.txt ├── 20.txt ├── 21.txt ├── 22.txt ├── 23.txt ├── 24.txt ├── 25.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 91-sqlalchemy ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt ├── 94-guis ├── 1.txt ├── 2.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt └── 97-online-game-service ├── 1.txt ├── 10.txt ├── 11.txt ├── 12.txt ├── 13.txt ├── 14.txt ├── 15.txt ├── 16.txt ├── 17.txt ├── 18.txt ├── 19.txt ├── 2.txt ├── 20.txt ├── 21.txt ├── 22.txt ├── 23.txt ├── 24.txt ├── 25.txt ├── 3.txt ├── 4.txt ├── 5.txt ├── 6.txt ├── 7.txt ├── 8.txt └── 9.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Talk Python 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /days/01-03-datetimes/code/datetime_date.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from datetime import date 4 | from datetime import datetime 5 | 6 | datetime.today() 7 | # datetime.datetime(2021, 1, 19, 14, 38, 52, 133483) 8 | 9 | today = datetime.today() 10 | 11 | type(today) 12 | # 13 | 14 | 15 | today_date = date.today() 16 | 17 | today_date 18 | # datetime.date(2021, 1, 19) 19 | 20 | type(today_date) 21 | # 22 | 23 | today_date.month 24 | # 1 25 | 26 | today_date.year 27 | # 2021 28 | 29 | today_date.day 30 | # 19 31 | 32 | 33 | christmas = date(today_date.year, 12, 25) 34 | christmas 35 | # datetime.date(2021, 12, 25) 36 | 37 | # We need to use != & == rather than is / is not for comparison. Sorry for the mistake in the video. 38 | if christmas != today_date: 39 | print("Sorry there are still " + str((christmas - today_date).days) + " until Christmas!") 40 | else: 41 | print("Yay it's Christmas!") 42 | -------------------------------------------------------------------------------- /days/01-03-datetimes/code/datetime_timedelta.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from datetime import datetime 4 | from datetime import timedelta 5 | 6 | t = timedelta(days=4, hours=10) 7 | 8 | t.days 9 | #4 10 | 11 | t.seconds 12 | #36000 13 | 14 | t.hours 15 | #Traceback (most recent call last): 16 | #File "", line 1, in t.hours 17 | #AttributeError: 'datetime.timedelta' object has no attribute 'hours' 18 | 19 | t.seconds / 60 / 60 20 | #10.0 21 | 22 | t.seconds / 3600 23 | #10.0 24 | 25 | 26 | ######### 27 | 28 | eta = timedelta(hours=6) 29 | 30 | today = datetime.today() 31 | 32 | today 33 | #datetime.datetime(2018, 2, 19, 14, 55, 19, 197404 34 | 35 | today + eta 36 | #datetime.datetime(2018, 2, 19, 20, 55, 19, 197404) 37 | 38 | str(today + eta) 39 | #'2018-02-19 20:55:19.197404' 40 | -------------------------------------------------------------------------------- /days/10-12-pytest/fizzbuzz/fizzbuzz.py: -------------------------------------------------------------------------------- 1 | def fizzbuzz(n): 2 | if n % 3 == 0 and n % 5 == 0: 3 | return 'Fizz Buzz' 4 | if n % 3 == 0: 5 | return 'Fizz' 6 | if n % 5 == 0: 7 | return 'Buzz' 8 | return n 9 | -------------------------------------------------------------------------------- /days/10-12-pytest/fizzbuzz/test_fizzbuzz.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from fizzbuzz import fizzbuzz 4 | 5 | @pytest.mark.parametrize("arg, ret",[ 6 | (1, 1), 7 | (2, 2), 8 | (3, 'Fizz'), 9 | (4, 4), 10 | (5, 'Buzz'), 11 | (6, 'Fizz'), 12 | (7, 7), 13 | (8, 8), 14 | (9, 'Fizz'), 15 | (10, 'Buzz'), 16 | (11, 11), 17 | (12, 'Fizz'), 18 | (13, 13), 19 | (14, 14), 20 | (15, 'Fizz Buzz'), 21 | (16, 16), 22 | ]) 23 | def test_fizzbuzz(arg, ret): 24 | assert fizzbuzz(arg) == ret 25 | -------------------------------------------------------------------------------- /days/10-12-pytest/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | pytest-cov 3 | -------------------------------------------------------------------------------- /days/100-freestyle/README.md: -------------------------------------------------------------------------------- 1 | # Day 100 - Freestyle 2 | 3 | Today is the final day of your #100DaysOfCode. Congratulations. That is an amazing achievement. 4 | 5 | Now it's your turn to do a little freestyling. Is there a segment's project that you didn't get finished? Go back and complete that one. Is there some way you wanted to extend something you've already built? Do that. If you just want to try something entirely off-script, be our guest. You've earned it. 6 | 7 | ### Time to share what you've accomplished! 8 | 9 | This is especially relevant today! Share your last couple of days work on Twitter or Facebook. Use the hashtag **#100DaysOfCode**. 10 | 11 | Here are [some examples](https://twitter.com/search?q=%23100DaysOfCode) to inspire you. Consider including [@talkpython](https://twitter.com/talkpython) and [@pybites](https://twitter.com/pybites) in your tweets. 12 | 13 | *See a mistake in these instructions? Please [submit a new issue](https://github.com/talkpython/100daysofcode-with-python-course/issues) or fix it and [submit a PR](https://github.com/talkpython/100daysofcode-with-python-course/pulls).* 14 | -------------------------------------------------------------------------------- /days/13-15-text-games/data/battle-table.csv: -------------------------------------------------------------------------------- 1 | Attacker,Rock,Gun,Lightning,Devil,Dragon,Water,Air,Paper,Sponge,Wolf,Tree,Human,Snake,Scissors,Fire Rock,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win Gun,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win Lightning,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win Devil,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win Dragon,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win Water,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win Air,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win Paper,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose Sponge,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose Wolf,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose Tree,lose,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose Human,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose Snake,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose,lose Scissors,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose Fire,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw -------------------------------------------------------------------------------- /days/13-15-text-games/data/sample_reader.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | def read_rolls(): 4 | with open('battle-table.csv') as fin: 5 | reader = csv.DictReader(fin) 6 | for row in reader: 7 | read_roll(row) 8 | 9 | 10 | def read_roll(row: dict): 11 | name = row['Attacker'] 12 | del row['Attacker'] 13 | del row[name] 14 | 15 | print("Roll: {}".format(name)) 16 | for k in row.keys(): 17 | can_defeat = row[k].strip().lower() == 'win' 18 | print(" * {} will defeat {}? {}".format(name, k, can_defeat)) 19 | 20 | print() 21 | 22 | read_rolls() 23 | -------------------------------------------------------------------------------- /days/13-15-text-games/dnd_game/actors.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | class Creature: 5 | def __init__(self, name, level): 6 | self.name = name 7 | self.level = level 8 | 9 | def defensive_roll(self): 10 | roll = random.randint(1, 12) 11 | return roll * self.level 12 | 13 | 14 | class Dragon(Creature): 15 | def __init__(self, name, level, scaliness, breaths_fire): 16 | super().__init__(name, level) 17 | self.scaliness = scaliness 18 | self.breaths_fire = breaths_fire 19 | 20 | def defensive_roll(self): 21 | roll = super().defensive_roll() 22 | value = roll * self.scaliness 23 | if self.breaths_fire: 24 | value = value * 2 25 | 26 | return value 27 | 28 | 29 | class Wizard(Creature): 30 | 31 | def attack(self, creature): 32 | my_roll = self.defensive_roll() 33 | their_roll = creature.defensive_roll() 34 | 35 | return my_roll >= their_roll 36 | -------------------------------------------------------------------------------- /days/13-15-text-games/rps15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/13-15-text-games/rps15.jpg -------------------------------------------------------------------------------- /days/19-21-itertools/code/cycle_demo.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import sys 3 | import time 4 | 5 | symbols = itertools.cycle('-\|/') 6 | 7 | while True: 8 | sys.stdout.write('\r' + next(symbols)) 9 | sys.stdout.flush() 10 | time.sleep(0.1) 11 | -------------------------------------------------------------------------------- /days/19-21-itertools/code/permutations.py: -------------------------------------------------------------------------------- 1 | from itertools import permutations, combinations 2 | 3 | friends = 'mike bob julian'.split() 4 | # note that we get a generator so using list to consume it 5 | print(list(combinations(friends, 2))) 6 | 7 | # what if order matters? 8 | print(list(permutations(friends, 2))) 9 | -------------------------------------------------------------------------------- /days/19-21-itertools/code/spinner.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import sys 3 | import time 4 | 5 | 6 | def spinner(seconds): 7 | """Show an animated spinner while we sleep.""" 8 | symbols = itertools.cycle('-\|/') 9 | tend = time.time() + seconds 10 | while time.time() < tend: 11 | # '\r' is carriage return: return cursor to the start of the line. 12 | sys.stdout.write('\rPlease wait... ' + next(symbols)) # no newline 13 | sys.stdout.flush() 14 | time.sleep(0.1) 15 | print() 16 | 17 | 18 | if __name__ == "__main__": 19 | spinner(3) 20 | -------------------------------------------------------------------------------- /days/19-21-itertools/code/traffic_lights.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | import itertools 3 | import random 4 | 5 | colours = 'Red Green Amber'.split() 6 | rotation = itertools.cycle(colours) 7 | 8 | def rg_timer(): 9 | return random.randint(3, 7) 10 | 11 | def light_rotation(rotation): 12 | for colour in rotation: 13 | if colour == 'Amber': 14 | print('Caution! The light is %s' % colour) 15 | sleep(3) 16 | elif colour == 'Red': 17 | print('STOP! The light is %s' % colour) 18 | sleep(rg_timer()) 19 | else: 20 | print('Go! The light is %s' % colour) 21 | sleep(rg_timer()) 22 | 23 | if __name__ == '__main__': 24 | light_rotation(rotation) 25 | -------------------------------------------------------------------------------- /days/22-24-decorators/stacking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/22-24-decorators/stacking.png -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/movie_search_error_edition/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | import random 6 | 7 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 8 | 'duration, genres, rating, year, imdb_score') 9 | 10 | 11 | def find_movie_by_title(keyword: str) -> List[Movie]: 12 | if not keyword or not keyword.strip(): 13 | raise ValueError('Must specify a search term.') 14 | 15 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 16 | 17 | resp = requests.get(url) 18 | resp.raise_for_status() 19 | 20 | results = resp.json() 21 | results = create_random_errors(results) 22 | 23 | movies = [] 24 | for r in results.get('hits'): 25 | movies.append(Movie(**r)) 26 | 27 | return movies 28 | 29 | 30 | def create_random_errors(results): 31 | # This is a method to occasionally create some more 32 | # interesting errors other than simply network connectivity errors 33 | # which are the only "real" errors. This will let us test 34 | # more types. 35 | 36 | num = random.randint(1, 20) 37 | if 16 < num <= 18: 38 | return {} # Whoops! No data. 39 | elif 18 < num <= 20: 40 | raise StopIteration() 41 | 42 | return results # no errors here. 43 | -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/movie_search_error_edition/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | import requests.exceptions 3 | 4 | 5 | def main(): 6 | keyword = input('Keyword of title search: ') 7 | try: 8 | results = api.find_movie_by_title(keyword) 9 | 10 | print(f'There are {len(results)} movies found.') 11 | for r in results: 12 | print(f"{r.title} with code {r.imdb_code} has score {r.imdb_score}") 13 | except requests.exceptions.ConnectionError: 14 | print("ERROR: Could not find server. Check your network connection.") 15 | except ValueError: 16 | print("ERROR: You must specify a search term.") 17 | except Exception as x: 18 | print("Oh that didn't work!: {}".format(x)) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/movie_search_error_edition/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/starter_movie_search_error_edition/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | import random 6 | 7 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 8 | 'duration, genres, rating, year, imdb_score') 9 | 10 | 11 | def find_movie_by_title(keyword: str) -> List[Movie]: 12 | if not keyword or not keyword.strip(): 13 | raise ValueError('Must specify a search term.') 14 | 15 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 16 | 17 | resp = requests.get(url) 18 | resp.raise_for_status() 19 | 20 | results = resp.json() 21 | results = create_random_errors(results) 22 | 23 | movies = [] 24 | for r in results.get('hits'): 25 | movies.append(Movie(**r)) 26 | 27 | return movies 28 | 29 | 30 | def create_random_errors(results): 31 | # This is a method to occasionally create some more 32 | # interesting errors other than simply network connectivity errors 33 | # which are the only "real" errors. This will let us test 34 | # more types. 35 | 36 | num = random.randint(1, 20) 37 | if 16 < num <= 18: 38 | return {} # Whoops! No data. 39 | elif 18 < num <= 20: 40 | raise StopIteration() 41 | 42 | return results # no errors here. 43 | -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/starter_movie_search_error_edition/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | 3 | 4 | def main(): 5 | keyword = 'Python' # input('Keyword of title search: ') 6 | results = api.find_movie_by_title(keyword) 7 | 8 | print(f'There are {len(results)} movies found.') 9 | for r in results: 10 | print(f"{r.title} with code {r.imdb_code} has score {r.imdb_score}") 11 | 12 | 13 | if __name__ == '__main__': 14 | main() 15 | -------------------------------------------------------------------------------- /days/25-27-error-handling/demo/starter_movie_search_error_edition/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /days/31-33-logging/demo/movie_search_logging_edition/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | logbook 3 | -------------------------------------------------------------------------------- /days/31-33-logging/demo/starter_movie_search/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | import random 6 | 7 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 8 | 'duration, genres, rating, year, imdb_score') 9 | 10 | 11 | def find_movie_by_title(keyword: str) -> List[Movie]: 12 | if not keyword or not keyword.strip(): 13 | raise ValueError('Must specify a search term.') 14 | 15 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 16 | 17 | resp = requests.get(url) 18 | resp.raise_for_status() 19 | 20 | results = resp.json() 21 | results = create_random_errors(results) 22 | 23 | movies = [] 24 | for r in results.get('hits'): 25 | movies.append(Movie(**r)) 26 | 27 | return movies 28 | 29 | 30 | def create_random_errors(results): 31 | # This is a method to occasionally create some more 32 | # interesting errors other than simply network connectivity errors 33 | # which are the only "real" errors. This will let us test 34 | # more types. 35 | 36 | num = random.randint(1, 20) 37 | if 16 < num <= 18: 38 | return {} # Whoops! No data. 39 | elif 18 < num <= 20: 40 | raise StopIteration() 41 | 42 | return results # no errors here. 43 | -------------------------------------------------------------------------------- /days/31-33-logging/demo/starter_movie_search/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | import requests.exceptions 3 | 4 | 5 | def main(): 6 | keyword = input('Keyword of title search: ') 7 | try: 8 | results = api.find_movie_by_title(keyword) 9 | 10 | print(f'There are {len(results)} movies found.') 11 | for r in results: 12 | print(f"{r.title} with code {r.imdb_code} has score {r.imdb_score}") 13 | except requests.exceptions.ConnectionError: 14 | print("ERROR: Could not find server. Check your network connection.") 15 | except ValueError: 16 | print("ERROR: You must specify a search term.") 17 | except Exception as x: 18 | print("Oh that didn't work!: {}".format(x)) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /days/31-33-logging/demo/starter_movie_search/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /days/34-36-refactoring/coding-horror.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/34-36-refactoring/coding-horror.gif -------------------------------------------------------------------------------- /days/34-36-refactoring/strings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/34-36-refactoring/strings.png -------------------------------------------------------------------------------- /days/37-39-csv-data-analysis/weather_csv_demo/program.py: -------------------------------------------------------------------------------- 1 | import research 2 | 3 | 4 | def main(): 5 | print("Weather research for Seattle, 2014-2015") 6 | print() 7 | research.init() 8 | 9 | print("The hottest 5 days:") 10 | days = research.hot_days() 11 | for idx, d in enumerate(days[:5]): 12 | print("{}. {} F on {}".format(idx+1, d.actual_max_temp, d.date)) 13 | print() 14 | print("The coldest 5 days:") 15 | days = research.cold_days() 16 | for idx, d in enumerate(days[:5]): 17 | print("{}. {} F on {}".format(idx+1, d.actual_min_temp, d.date)) 18 | print() 19 | print("The wettest 5 days:") 20 | 21 | days = research.wet_days() 22 | for idx, d in enumerate(days[:5]): 23 | print("{}. {} inches of rain on {}".format(idx+1, d.actual_precipitation, d.date)) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /days/40-42-json-data/code/json_dicts.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import json 4 | import requests 5 | from pprint import pprint 6 | 7 | r = requests.get('https://us.api.battle.net/wow/character/Cenarion%20Circle/Ardy?fields=mounts&locale=en_US&apikey=') 8 | 9 | data = json.loads(r.text) 10 | 11 | for item in data['mounts']: 12 | pprint(item) 13 | 14 | #Only the first level is printed. 15 | 16 | for item in data['mounts']['collected']: 17 | pprint(item) 18 | 19 | #Prints ALL the data associated with 'collected mounts'. 20 | 21 | 22 | for item in data['mounts']['collected']: 23 | pprint(item['name']) 24 | 25 | #Prints just the data associated with the 'name' key. 26 | 27 | 28 | is_flying = [] 29 | for mount in data['mounts']['collected']: 30 | if mount['isFlying']: 31 | is_flying.append(mount) 32 | 33 | #Collects all of the applicable mounts and stores them as a list of dicts 34 | 35 | #You can then work with the data as normal: 36 | 37 | len(is_flying) 38 | 65 39 | 40 | for i in is_flying: 41 | print(i) 42 | 43 | for i in is_flying: 44 | print(i['name']) 45 | 46 | -------------------------------------------------------------------------------- /days/40-42-json-data/code/json_requests.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import json 4 | import requests 5 | from pprint import pprint 6 | 7 | r = requests.get('https://us.api.battle.net/wow/character/Cenarion%20Circle/Ardy?fields=mounts&locale=en_US&apikey=') 8 | 9 | data = json.loads(r.text) 10 | 11 | for item in data.items(): 12 | print(item) 13 | 14 | #Hard to read 15 | 16 | for item in data.items(): 17 | pprint(item) 18 | 19 | #easier to read 20 | -------------------------------------------------------------------------------- /days/43-45-search-api/demo/movie_search/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | 6 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 7 | 'duration, genres, rating, year, imdb_score') 8 | 9 | 10 | def find_movie_by_title(keyword: str) -> List[Movie]: 11 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 12 | 13 | resp = requests.get(url) 14 | resp.raise_for_status() 15 | 16 | results = resp.json() 17 | movies = [] 18 | for r in results.get('hits'): 19 | movies.append(Movie(**r)) 20 | 21 | return movies 22 | -------------------------------------------------------------------------------- /days/43-45-search-api/demo/movie_search/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | 3 | 4 | def main(): 5 | keyword = input('Keyword of title search: ') 6 | results = api.find_movie_by_title(keyword) 7 | 8 | print(f'There are {len(results)} movies found.') 9 | for r in results: 10 | print(f"{r.title} with code {r.imdb_code} has score {r.imdb_score}") 11 | 12 | 13 | if __name__ == '__main__': 14 | main() 15 | -------------------------------------------------------------------------------- /days/43-45-search-api/demo/movie_search/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /days/43-45-search-api/readme_resources/post-sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/43-45-search-api/readme_resources/post-sm.jpg -------------------------------------------------------------------------------- /days/43-45-search-api/readme_resources/post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/43-45-search-api/readme_resources/post.png -------------------------------------------------------------------------------- /days/46-48-beautifulsoup4/scraper_demo/scraper.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import bs4 3 | 4 | # URL of site we want to scrape 5 | URL = "https://pybit.es/pages/projects.html" 6 | 7 | def pull_site(): 8 | raw_site_page = requests.get(URL) #Pull down the site. 9 | raw_site_page.raise_for_status() #Confirm site was pulled. Error if not 10 | return raw_site_page 11 | 12 | def scrape(site): 13 | header_list = [] 14 | #Create BeautifulSoup object 15 | soup = bs4.BeautifulSoup(site.text, 'html.parser') 16 | html_header_list = soup.select('.projectHeader') 17 | 18 | for headers in html_header_list: 19 | header_list.append(headers.getText()) 20 | for headers in header_list: 21 | print(headers) 22 | 23 | 24 | if __name__ == "__main__": 25 | site = pull_site() 26 | scrape(site) 27 | -------------------------------------------------------------------------------- /days/46-48-beautifulsoup4/scraper_demo/shell_commands.py: -------------------------------------------------------------------------------- 1 | #Python Shell Commands 2 | #Day 2 - BeautifulSoup4 3 | 4 | import bs4 5 | import requests 6 | 7 | site = requests.get("https://pybit.es/pages/articles.html") 8 | site.raise_for_status() 9 | soup = bs4.BeautifulSoup(site.text, 'html.parser') 10 | 11 | #Search for first
    tag on the page 12 | soup.ul 13 | 14 | #Search for all
      tags on the page 15 | soup.find_all('ul') 16 | 17 | #Search for all
        tags within the
        tag 18 | soup.main.ul 19 | 20 | #Search for all
      • tags within the
        tag and assign to variable 21 | all_li = soup.main.find_all('li') 22 | 23 | #Print out the text data for all of the
      • tags (titles of URLs) 24 | for title in all_li: 25 | print(title.string) 26 | -------------------------------------------------------------------------------- /days/49-51-measuring-perf/demo/final_csv_code/program.py: -------------------------------------------------------------------------------- 1 | import cProfile 2 | 3 | profiler = cProfile.Profile() 4 | profiler.disable() 5 | 6 | import research 7 | 8 | 9 | def main(): 10 | print("Weather research for Seattle, 2014-2015") 11 | print() 12 | profiler.enable() 13 | 14 | research.init() 15 | 16 | hot_days = research.hot_days() 17 | cold_days = research.cold_days() 18 | wet_days = research.wet_days() 19 | 20 | profiler.disable() 21 | 22 | print("The hottest 5 days:") 23 | for idx, d in enumerate(hot_days[:5]): 24 | print("{}. {} F on {}".format(idx + 1, d.actual_max_temp, d.date)) 25 | print() 26 | print("The coldest 5 days:") 27 | 28 | for idx, d in enumerate(cold_days[:5]): 29 | print("{}. {} F on {}".format(idx + 1, d.actual_min_temp, d.date)) 30 | print() 31 | print("The wettest 5 days:") 32 | 33 | for idx, d in enumerate(wet_days[:5]): 34 | print("{}. {} inches of rain on {}".format(idx + 1, d.actual_precipitation, d.date)) 35 | 36 | 37 | if __name__ == '__main__': 38 | for _ in range(1, 100): 39 | main() 40 | 41 | profiler.print_stats(sort='cumtime') 42 | -------------------------------------------------------------------------------- /days/49-51-measuring-perf/demo/final_csv_code/program_pycharm.py: -------------------------------------------------------------------------------- 1 | import research 2 | 3 | 4 | def main(): 5 | print("Weather research for Seattle, 2014-2015") 6 | print() 7 | 8 | research.init() 9 | 10 | hot_days = research.hot_days() 11 | cold_days = research.cold_days() 12 | wet_days = research.wet_days() 13 | 14 | print("The hottest 5 days:") 15 | for idx, d in enumerate(hot_days[:5]): 16 | print("{}. {} F on {}".format(idx + 1, d.actual_max_temp, d.date)) 17 | print() 18 | print("The coldest 5 days:") 19 | 20 | for idx, d in enumerate(cold_days[:5]): 21 | print("{}. {} F on {}".format(idx + 1, d.actual_min_temp, d.date)) 22 | print() 23 | print("The wettest 5 days:") 24 | 25 | for idx, d in enumerate(wet_days[:5]): 26 | print("{}. {} inches of rain on {}".format(idx + 1, d.actual_precipitation, d.date)) 27 | 28 | 29 | if __name__ == '__main__': 30 | for _ in range(1, 100): 31 | main() 32 | -------------------------------------------------------------------------------- /days/49-51-measuring-perf/demo/starter_csv_code/program.py: -------------------------------------------------------------------------------- 1 | import research 2 | 3 | 4 | def main(): 5 | print("Weather research for Seattle, 2014-2015") 6 | print() 7 | research.init() 8 | 9 | print("The hottest 5 days:") 10 | days = research.hot_days() 11 | for idx, d in enumerate(days[:5]): 12 | print("{}. {} F on {}".format(idx+1, d.actual_max_temp, d.date)) 13 | print() 14 | print("The coldest 5 days:") 15 | days = research.cold_days() 16 | for idx, d in enumerate(days[:5]): 17 | print("{}. {} F on {}".format(idx+1, d.actual_min_temp, d.date)) 18 | print() 19 | print("The wettest 5 days:") 20 | 21 | days = research.wet_days() 22 | for idx, d in enumerate(days[:5]): 23 | print("{}. {} inches of rain on {}".format(idx+1, d.actual_precipitation, d.date)) 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /days/52-54-feedparser/code/parser.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import feedparser 4 | 5 | FEED_FILE = "newreleases.xml" 6 | 7 | feed = feedparser.parse(FEED_FILE) 8 | 9 | if 'title' in feed.entries[0]: 10 | for entry in feed.entries: 11 | print(entry.published + " - " + entry.title + ": " + entry.link) 12 | -------------------------------------------------------------------------------- /days/52-54-feedparser/code/pull_xml.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | #pull_xml.py uses the requests module to pull down the feed xml file for use in the xml parser script. 3 | #This will result in just one call/request to the Steam webserver hosting this XML file. 4 | 5 | import requests 6 | 7 | URL = "http://store.steampowered.com/feeds/newreleases.xml" 8 | 9 | if __name__ == "__main__": 10 | r = requests.get(URL) 11 | with open('newreleases.xml', 'wb') as f: 12 | f.write(r.content) 13 | -------------------------------------------------------------------------------- /days/55-57-uplink/demo/program.py: -------------------------------------------------------------------------------- 1 | from blog_client import BlogClient 2 | 3 | 4 | def main(): 5 | val = 'RUN' 6 | 7 | while val: 8 | print("What would you like to do next?") 9 | val = input('[w]rite a post or [r]ead them?') 10 | 11 | if val == 'w': 12 | write_post() 13 | elif val == 'r': 14 | read_posts() 15 | 16 | 17 | def read_posts(): 18 | svc = BlogClient() 19 | response = svc.all_entries() 20 | 21 | posts = response.json() 22 | print() 23 | for idx, p in enumerate(posts, 1): 24 | print(" {}. [{:,} views] {}".format( 25 | idx, p.get('view_count'), p.get('title') 26 | )) 27 | print() 28 | selected = int(input('Which number to view? ')) 29 | 30 | selected_id = posts[selected - 1].get('id') 31 | 32 | response = svc.entry_by_id(selected_id) 33 | 34 | selected_post = response.json() 35 | print("Details for selected_post: {}".format(selected_post.get('id'))) 36 | print("Title: " + selected_post.get('title')) 37 | print("Written: " + selected_post.get('published')) 38 | print("Content: " + selected_post.get('content')) 39 | print() 40 | print() 41 | 42 | 43 | def write_post(): 44 | svc = BlogClient() 45 | 46 | title = input("Title: ") 47 | content = input("Body contents: ") 48 | view_count = int(input("view count (int): ")) 49 | 50 | resp = svc.create_new_entry(title, content, view_count) 51 | 52 | print() 53 | resp = resp.json() 54 | print("Created new post successfully: {}".format(resp.get('id'))) 55 | print() 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /days/55-57-uplink/demo/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | # Moving to the latest version of uplink to keep things fresh and relevant. 3 | uplink==0.9.4 -------------------------------------------------------------------------------- /days/55-57-uplink/demo/uplink_helpers.py: -------------------------------------------------------------------------------- 1 | import uplink 2 | 3 | 4 | @uplink.response_handler 5 | def raise_for_status(response): 6 | response.raise_for_status() 7 | return response 8 | -------------------------------------------------------------------------------- /days/58-60-twitter-api/pybites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/58-60-twitter-api/pybites.png -------------------------------------------------------------------------------- /days/58-60-twitter-api/wordcloud-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/58-60-twitter-api/wordcloud-image.png -------------------------------------------------------------------------------- /days/61-63-github-api/README.md: -------------------------------------------------------------------------------- 1 | # Using Python + Github API 2 | 3 | In this lesson I will show you how to use [PyGithub](https://github.com/PyGithub/PyGithub) to retrieve public data from Github profiles and how to automatically create [a gist](https://help.github.com/en/articles/creating-gists). 4 | 5 | ## Day 1: Exploring the PyGithub module 6 | 7 | Today you watch the videos, the accompanying notebook is [here](https://github.com/talkpython/100daysofcode-with-python-course/blob/master/days/61-63-github-api/github-api.ipynb). 8 | 9 | ## Day 2 and 3: Practice 10 | 11 | Now you got the basics down, it's time to start using the Github API with Python yourself, some ideas for projects to work on you can find [in my notebook](https://github.com/talkpython/100daysofcode-with-python-course/blob/master/days/61-63-github-api/github-api.ipynb). 12 | 13 | You can use PyGithub or any other wrapper module, as long as you use Python :) 14 | 15 | ## Time to share what you've accomplished! 16 | 17 | Be sure to share your last couple of days work on Twitter or Facebook. Use the hashtag **#100DaysOfCode**. 18 | 19 | Here are [some examples](https://twitter.com/search?q=%23100DaysOfCode) to inspire you. Consider including [@talkpython](https://twitter.com/talkpython) and [@pybites](https://twitter.com/pybites) in your tweets. 20 | 21 | See a mistake in these instructions? Please [submit a new issue](https://github.com/talkpython/100daysofcode-with-python-course/issues) or fix it and [submit a PR](https://github.com/talkpython/100daysofcode-with-python-course/pulls). 22 | -------------------------------------------------------------------------------- /days/61-63-github-api/images/my_gist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/61-63-github-api/images/my_gist.png -------------------------------------------------------------------------------- /days/61-63-github-api/images/token1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/61-63-github-api/images/token1.png -------------------------------------------------------------------------------- /days/61-63-github-api/images/token2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/61-63-github-api/images/token2.png -------------------------------------------------------------------------------- /days/61-63-github-api/images/token3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/61-63-github-api/images/token3.png -------------------------------------------------------------------------------- /days/64-66-email-smtplib/code/emailer-mime.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | #emailer.py is a simple script for sending emails using smtplib 3 | 4 | import smtplib 5 | from email.mime.multipart import MIMEMultipart 6 | from email.mime.text import MIMEText 7 | 8 | from_addr = 'pybitesblog@gmail.com' 9 | to_addr = 'pybitesblog@gmail.com' 10 | bcc = ['pybitesblog@gmail.com', 'myemail@gmail.com', 'email@gmail.com'] 11 | 12 | msg = MIMEMultipart() 13 | msg['From'] = from_addr 14 | msg['To'] = to_addr 15 | msg['Subject'] = 'New Releases and Sales on Steam' 16 | 17 | body = """New Releases and Sales on Steam 18 | 19 | Click the links below to check them out! 20 | 21 | """ 22 | 23 | msg.attach(MIMEText(body, 'plain')) 24 | 25 | smtp_server = smtplib.SMTP('smtp.gmail.com', 587) 26 | 27 | smtp_server.ehlo() 28 | 29 | smtp_server.starttls() 30 | 31 | smtp_server.login(' pybitesblog@gmail.com ', ' ') 32 | 33 | text = msg.as_string() 34 | 35 | smtp_server.sendmail(from_addr, [to_addr] + bcc, text) 36 | 37 | smtp_server.quit() 38 | 39 | print('Email sent successfully') 40 | -------------------------------------------------------------------------------- /days/64-66-email-smtplib/code/emailer.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | #emailer.py is a simple script for sending emails using smtplib 3 | 4 | import smtplib 5 | 6 | from_addr = 'pybitesblog@gmail.com' 7 | to_addr = 'pybitesblog@gmail.com' 8 | 9 | body = """New Releases and Sales on Steam 10 | 11 | Click the links below to check them out! 12 | 13 | """ 14 | 15 | smtp_server = smtplib.SMTP('smtp.gmail.com', 587) 16 | 17 | smtp_server.ehlo() 18 | 19 | smtp_server.starttls() 20 | 21 | smtp_server.login(' pybitesblog@gmail.com ', ' ') 22 | 23 | smtp_server.sendmail(from_addr, to_addr, body) 24 | 25 | smtp_server.quit() 26 | 27 | print('Email sent successfully') 28 | -------------------------------------------------------------------------------- /days/67-69-pyperclip/code/affiliate.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import pyperclip 4 | 5 | AFFILIATE_CODE = '&tag=pyb0f-20' 6 | 7 | url = pyperclip.paste() 8 | 9 | if 'amazon' not in url: 10 | print('Sorry, invalid link.') 11 | else: 12 | new_link = url + AFFILIATE_CODE 13 | pyperclip.copy(new_link) 14 | print('Affiliate Link generated and copied to clipboard') 15 | -------------------------------------------------------------------------------- /days/67-69-pyperclip/code/text-replacer.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import pyperclip 4 | 5 | def paste_from_clipboard(): 6 | text = pyperclip.paste() 7 | return text 8 | 9 | 10 | def copy_to_clipboard(new_text): 11 | pyperclip.copy(new_text) 12 | print("The new string is now copied to the clipboard. Hit CTRL V to paste.") 13 | 14 | 15 | def replace_text(old_text): 16 | target = input('What would you like to replace? ') 17 | replacement = input('And what would you like to replace it with? ') 18 | new_text = old_text.replace(target, replacement) 19 | return new_text 20 | 21 | if __name__ == "__main__": 22 | old_text = paste_from_clipboard() 23 | new_text = replace_text(old_text) 24 | copy_to_clipboard(new_text) 25 | input() 26 | -------------------------------------------------------------------------------- /days/70-72-openpyxl-excel-automation/code/Financial Sample.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/70-72-openpyxl-excel-automation/code/Financial Sample.xlsx -------------------------------------------------------------------------------- /days/70-72-openpyxl-excel-automation/code/excel_automation.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from openpyxl import load_workbook 4 | 5 | wb = load_workbook('Financial Sample.xlsx') 6 | ws1 = wb['Finances 2017'] 7 | maxrow = ws1.max_row 8 | 9 | def insert_sum(): 10 | ws1['L' + str(maxrow)] = "=SUM(L2:L" + str(maxrow - 1) + ")" 11 | 12 | 13 | if __name__ == "__main__": 14 | insert_sum() 15 | wb.save('Financial Sample.xlsx') 16 | -------------------------------------------------------------------------------- /days/70-72-openpyxl-excel-automation/code/openpyxl_commands.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from openpyxl import load_workbook 4 | 5 | wb = load_workbook('Financial Sample.xlsx') 6 | 7 | wb.sheetnames 8 | 9 | ws1 = wb.active 10 | 11 | ws1['C9'].value 12 | 13 | ws1['B9'].value 14 | 15 | for row in range(2, ws1.max_row): 16 | cell = 'B' + str(row) 17 | print(ws1[cell].value) 18 | 19 | ##### 20 | 21 | profit_total = 0 22 | for col in list('L'): 23 | for row in range(2, 101): 24 | cell = col + str(row) 25 | profit_total += float(ws1[cell].value) 26 | 27 | print(profit_total) 28 | 29 | 30 | ##### 31 | 32 | 33 | wb = load_workbook('Financial Sample.xlsx') 34 | ws1 = wb['Finances 2017'] 35 | 36 | ws1['L703'] = "=SUM(L2:L701)" 37 | wb.save('Financial Sample.xlsx') 38 | 39 | ws1['L' + str(ws1.max_row)] = "=SUM(L2:L" + str(ws1.max_row - 1) + ")" 40 | wb.save('Financial Sample.xlsx') 41 | -------------------------------------------------------------------------------- /days/73-75-selenium/images/banner1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/banner1.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/banner2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/banner2.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/banner3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/banner3.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/banner4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/banner4.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/banner5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/banner5.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/packt1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/packt1.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/packt2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/packt2.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/packt3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/packt3.png -------------------------------------------------------------------------------- /days/73-75-selenium/images/packt4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/73-75-selenium/images/packt4.png -------------------------------------------------------------------------------- /days/76-78-flask/flask-code/app.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | from flask import Flask, render_template 4 | from data import fave_beer 5 | 6 | app = Flask(__name__) 7 | 8 | @app.route("/") 9 | def index(): 10 | return render_template("index.html", 11 | fave_beer=fave_beer) 12 | 13 | if __name__ == "__main__": 14 | app.run() 15 | -------------------------------------------------------------------------------- /days/76-78-flask/flask-code/data.py: -------------------------------------------------------------------------------- 1 | fave_beer = {"Julian": "White Rabbit Dark Ale", 2 | "Bob": "Some sort of light beer I assume", 3 | "Mike": "Oregano Beer", 4 | "Cornelius": "Ekim Afterbattle Pale Ale", 5 | "Dan": "Coopers"} 6 | -------------------------------------------------------------------------------- /days/76-78-flask/flask-code/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Favourite Beer Tracker 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

        Favourite Beers

        16 | 17 |
        18 | 19 | 20 | 21 | 22 | 23 | {% for name, beer in fave_beer.items() %} 24 | 25 | 26 | 27 | 28 | {% endfor %} 29 |
        NameBeer of Choice
        {{name}}{{beer}}
        30 |
        31 | 32 | -------------------------------------------------------------------------------- /days/79-81-sqlite3/code/simpledb.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import sqlite3 4 | 5 | connection = sqlite3.connect('addressbook.db') 6 | 7 | c = connection.cursor() 8 | 9 | c.execute("""CREATE TABLE Details 10 | (name TEXT, address TEXT, phone_number INT) 11 | """) 12 | 13 | connection.close() 14 | -------------------------------------------------------------------------------- /days/79-81-sqlite3/demos/generatedb.py: -------------------------------------------------------------------------------- 1 | from contextlib import contextmanager 2 | import sqlite3 3 | 4 | name = "" 5 | 6 | @contextmanager 7 | def create_db(name): 8 | try: 9 | conn = sqlite3.connect('%s.db' % name) 10 | cursor = conn.cursor() 11 | yield cursor 12 | finally: 13 | conn.close() 14 | 15 | 16 | def prompt_for_name(): 17 | name = input("What would you like to name your test db file?: ") 18 | return name 19 | 20 | if __name__ == "__main__": 21 | name = prompt_for_name() 22 | with create_db(name) as cursor: 23 | cursor.execute("""CREATE TABLE test_table 24 | (col1 TEXT, col2 TEXT, col3 TEXT, col4 INT) 25 | """) 26 | print('%s.db has been created' % name) 27 | -------------------------------------------------------------------------------- /days/79-81-sqlite3/demos/populatedb.py: -------------------------------------------------------------------------------- 1 | #!python3 2 | 3 | import sqlite3 4 | 5 | def enter_details(): 6 | while True: 7 | info = [] 8 | name = input('Enter a name: ') 9 | address = input('Enter an address: ') 10 | number = input('Enter a phone number: ') 11 | for i in (name, address, number): 12 | info.append(i) 13 | 14 | with sqlite3.connect("addressbook.db") as connection: 15 | c = connection.cursor() 16 | c.execute("INSERT INTO Details VALUES(?, ?, ?)", info) 17 | print('Data inserted to database.\n') 18 | 19 | stop = input("Hit Q to to quit.\n") 20 | if stop.upper() == 'Q': 21 | break 22 | else: 23 | continue 24 | 25 | if __name__ == "__main__": 26 | enter_details() 27 | -------------------------------------------------------------------------------- /days/82-84-dataviz-plotly/images/plot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/82-84-dataviz-plotly/images/plot1.png -------------------------------------------------------------------------------- /days/82-84-dataviz-plotly/images/plot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/82-84-dataviz-plotly/images/plot2.png -------------------------------------------------------------------------------- /days/82-84-dataviz-plotly/images/plot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/82-84-dataviz-plotly/images/plot3.png -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/README.md: -------------------------------------------------------------------------------- 1 | # Demo app details 2 | 3 | The code included here is exported from Anvil. 4 | 5 | To use this app, you'll first need an account. Be sure to use our link so you get a discount: 6 | 7 | Create an account via: [**talkpython.fm/anvil100**](https://talkpython.fm/anvil100) 8 | 9 | If you want to use this demo app in your account, the easiest way is to "clone it online" using this link: 10 | 11 | [anvil.works/ide#clone:5CHGY3Q6SBHQGA27=7WPAVZAGTUKSFK3QVI2XGV5U](https://anvil.works/ide#clone:5CHGY3Q6SBHQGA27=7WPAVZAGTUKSFK3QVI2XGV5U) 12 | 13 | You can also see the live, read-only version at: 14 | 15 | [pypoint-100days.anvilapp.net](https://pypoint-100days.anvilapp.net/) -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/anvil.yaml: -------------------------------------------------------------------------------- 1 | package_name: pypoint100days 2 | name: pypoint-100days 3 | startup_form: HomeForm 4 | renamed: true 5 | runtime_options: {server_version: python2-sandbox} 6 | services: 7 | - source: /runtime/services/tables.yml 8 | client_config: {} 9 | server_config: {auto_create_missing_columns: false} 10 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/AddDocForm.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | import utilities 6 | 7 | class AddDocForm (AddDocFormTemplate): 8 | def __init__(self, **properties): 9 | # You must call self.init_components() before doing anything else in this function 10 | self.init_components(**properties) 11 | 12 | # Any code you write here will run when the form opens. 13 | self.drop_down_categories.items = [('select a category', None)] + [(c, c) for c in utilities.categories] 14 | self.label_errors.text = "" 15 | 16 | def button_save_click (self, **event_args): 17 | errors = self.validate() 18 | if errors: 19 | self.label_errors.text = "\n".join(errors) 20 | return 21 | 22 | name = self.text_box_doc_name.text.strip() 23 | category = self.drop_down_categories.selected_value 24 | contents = self.text_area_contents.text.strip() 25 | 26 | utilities.create_doc(name, category, contents) 27 | utilities.go_home() 28 | 29 | 30 | def validate(self): 31 | self.label_errors.text = "" 32 | errors = [] 33 | if not self.text_box_doc_name.text or not self.text_box_doc_name.text.strip(): 34 | errors.append('Document name is required') 35 | 36 | if not self.drop_down_categories.selected_value: 37 | errors.append('Document category is required') 38 | 39 | if not self.text_area_contents.text or not self.text_area_contents.text.strip(): 40 | errors.append('Cannot create empty documents') 41 | 42 | return errors 43 | 44 | 45 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/AllDocsForm.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | import utilities 6 | 7 | class AllDocsForm (AllDocsFormTemplate): 8 | def __init__(self, **properties): 9 | # You must call self.init_components() before doing anything else in this function 10 | self.init_components(**properties) 11 | 12 | # Any code you write here will run when the form opens. 13 | self.repeating_panel_docs.items = utilities.docs 14 | 15 | def text_box_filter_change (self, **event_args): 16 | self.repeating_panel_docs.items = self.filtered_docs() 17 | 18 | def doc_to_text(self, d): 19 | return "{} {} {}".format(d["name"], d["contents"], d["category"]["name"]) 20 | 21 | def filtered_docs(self): 22 | txt = self.text_box_filter.text 23 | if not txt: 24 | return utilities.docs 25 | 26 | txt = txt.lower() 27 | 28 | return [ 29 | d 30 | for d in utilities.docs 31 | if self.doc_to_text(d).lower().find(txt) >= 0 32 | ] 33 | 34 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/DocDetailsForm.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | 6 | class DocDetailsForm (DocDetailsFormTemplate): 7 | def __init__(self, **properties): 8 | # You must call self.init_components() before doing anything else in this function 9 | self.init_components(**properties) 10 | 11 | # Any code you write here will run when the form opens. 12 | doc = self.item 13 | self.label_category.text = doc['category']['name'] 14 | self.label_date.text = doc["created"].strftime("%B %d, %Y") -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/DocListItemTemplate.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | import utilities 6 | 7 | class DocListItemTemplate (DocListItemTemplateTemplate): 8 | def __init__(self, **properties): 9 | # You must call self.init_components() before doing anything else in this function 10 | self.init_components(**properties) 11 | 12 | # Any code you write here will run when the form opens. 13 | 14 | 15 | def form_show (self, **event_args): 16 | # This method is called when the column panel is shown on the screen 17 | self.label_created.text = self.item["created"].strftime("%B %d, %Y") 18 | 19 | def link_details_click (self, **event_args): 20 | # This method is called when the link is clicked 21 | utilities.go_details(self.item) 22 | 23 | 24 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/DocListItemTemplate.yaml: -------------------------------------------------------------------------------- 1 | container: 2 | type: ColumnPanel 3 | properties: {col_widths: '{"JKNUPK":30,"TIDSGW":20,"KEEGAO":10}'} 4 | event_bindings: {show: form_show} 5 | components: 6 | - type: Label 7 | properties: {role: null, width: default, align: left, border: '', foreground: '', 8 | visible: true, text: '', font_size: null, font: '', spacing_above: small, icon_align: left, 9 | spacing_below: small, italic: false, background: '', bold: true, underline: false, 10 | icon: ''} 11 | name: label_title 12 | layout_properties: {grid_position: 'KYKPJJ,JKNUPK'} 13 | data_bindings: 14 | - {property: text, code: 'self.item[''name'']'} 15 | - type: Label 16 | properties: {} 17 | name: label_created 18 | layout_properties: {grid_position: 'KYKPJJ,TIDSGW'} 19 | data_bindings: [] 20 | - type: Link 21 | properties: {role: null, width: default, align: left, border: '', foreground: '', 22 | visible: true, text: details, font_size: null, row_spacing: 10, wrap_on: mobile, 23 | font: '', spacing_above: small, icon_align: left, col_widths: '', spacing_below: small, 24 | italic: false, background: '', bold: false, underline: false, icon: ''} 25 | name: link_details 26 | layout_properties: {grid_position: 'KYKPJJ,KEEGAO'} 27 | event_bindings: {click: link_details_click} 28 | item_type: {table_id: 9224} 29 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/HomeDetailsForm.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | import utilities 6 | 7 | class HomeDetailsForm (HomeDetailsFormTemplate): 8 | def __init__(self, **properties): 9 | # You must call self.init_components() before doing anything else in this function 10 | self.init_components(**properties) 11 | 12 | # Any code you write here will run when the form opens. 13 | self.repeating_panel_1.items = utilities.docs[:3] -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/HomeDetailsForm.yaml: -------------------------------------------------------------------------------- 1 | container: 2 | type: ColumnPanel 3 | properties: {col_widths: '{}'} 4 | components: 5 | - type: Label 6 | properties: {role: null, width: default, align: center, border: '', foreground: '', 7 | visible: true, text: PyPoint Home, font_size: 28, font: '', spacing_above: small, 8 | icon_align: left, spacing_below: small, italic: false, background: '', bold: true, 9 | underline: false, icon: ''} 10 | name: label_subtitle 11 | layout_properties: {grid_position: 'PMAGCL,EMKFQV'} 12 | - type: Label 13 | properties: {role: null, width: default, align: center, border: '', foreground: '', 14 | visible: true, text: Recent documents, font_size: 18, font: '', spacing_above: small, 15 | icon_align: left, spacing_below: small, italic: false, background: '', bold: true, 16 | underline: false, icon: ''} 17 | name: label_1 18 | layout_properties: {grid_position: 'GSZYCE,GPPGQE'} 19 | - type: RepeatingPanel 20 | properties: {role: null, width: default, border: '', foreground: '', items: null, 21 | visible: true, spacing_above: small, spacing_below: small, item_template: DocListItemTemplate, 22 | background: ''} 23 | name: repeating_panel_1 24 | layout_properties: {grid_position: 'QXRTLU,YUTPPU'} 25 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/forms/HomeForm.py: -------------------------------------------------------------------------------- 1 | from anvil import * 2 | import anvil.server 3 | import tables 4 | from tables import app_tables 5 | from AddDocForm import AddDocForm 6 | from DocDetailsForm import DocDetailsForm 7 | from AllDocsForm import AllDocsForm 8 | from HomeDetailsForm import HomeDetailsForm 9 | import utilities 10 | 11 | class HomeForm (HomeFormTemplate): 12 | def __init__(self, **properties): 13 | # You must call self.init_components() before doing anything else in this function 14 | self.init_components(**properties) 15 | 16 | # Any code you write here will run when the form opens. 17 | utilities.refresh_data() 18 | self.link_home_click() 19 | utilities.home_form = self 20 | 21 | 22 | def link_home_click (self, **event_args): 23 | self.label_title.text = "PyPoint: Home" 24 | self.content_panel.clear() 25 | self.content_panel.add_component(HomeDetailsForm()) 26 | 27 | def link_all_docs_click (self, **event_args): 28 | self.label_title.text = "PyPoint: All Documents" 29 | self.content_panel.clear() 30 | self.content_panel.add_component(AllDocsForm()) 31 | 32 | def link_add_doc_click (self, **event_args): 33 | self.label_title.text = "PyPoint: Add a document" 34 | self.content_panel.clear() 35 | self.content_panel.add_component(AddDocForm()) 36 | 37 | def go_details(self, doc): 38 | self.label_title.text = "PyPoint: Details" 39 | self.content_panel.clear() 40 | self.content_panel.add_component(DocDetailsForm(item=doc)) 41 | 42 | 43 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/modules/utilities.py: -------------------------------------------------------------------------------- 1 | import anvil.server 2 | import tables 3 | from tables import app_tables 4 | 5 | home_form = None 6 | 7 | docs = [] 8 | categories = [] 9 | 10 | def refresh_data(): 11 | global docs, categories 12 | 13 | raw_cats = anvil.server.call('all_categories') 14 | categories = [c["name"] for c in raw_cats] 15 | docs = anvil.server.call('all_docs') 16 | 17 | 18 | def go_home(): 19 | home_form.link_home_click() 20 | 21 | 22 | def go_details(doc): 23 | home_form.go_details(doc) 24 | 25 | 26 | def create_doc(name, category, contents): 27 | anvil.server.call('add_doc', name, category, contents, 0) 28 | refresh_data() -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/server_modules/data_layer.py: -------------------------------------------------------------------------------- 1 | import tables 2 | from tables import app_tables 3 | import anvil.server 4 | import datetime 5 | 6 | @anvil.server.callable 7 | def all_docs(): 8 | results = list(app_tables.documents.search(tables.order_by("created", ascending=False))) 9 | return results 10 | 11 | 12 | @anvil.server.callable 13 | def all_categories(): 14 | return list(app_tables.categories.search(tables.order_by("name"))) 15 | 16 | 17 | @anvil.server.callable 18 | def doc_by_name(name): 19 | return app_tables.documents.get(name=name) 20 | 21 | 22 | @anvil.server.callable 23 | def category_by_name(category_name): 24 | return app_tables.categories.get(name=category_name) 25 | 26 | @anvil.server.callable 27 | def add_doc(doc_name, category_name, contents, views): 28 | now = datetime.datetime.now() 29 | print("Server: Creating new document: {} {} {} {}".format(doc_name, category_name, views, contents, now)) 30 | category = category_by_name(category_name) 31 | app_tables.documents.add_row(name=doc_name, category=category, contents=contents, views=views, created=now) 32 | return doc_by_name(doc_name) 33 | 34 | 35 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/theme/parameters.yaml: -------------------------------------------------------------------------------- 1 | roles: 2 | - name: title 3 | components: [Label] 4 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/pypoint-100days/theme/templates.yaml: -------------------------------------------------------------------------------- 1 | - name: Card-based layout with sidebar 2 | description: A page with a card-based layout, and a sidebar menu for links 3 | img: img/form-templates/dashboard.png 4 | form: 5 | class_name: Form 6 | container: 7 | type: HtmlTemplate 8 | properties: {html: '@theme:dashboard.html'} 9 | components: 10 | - type: ColumnPanel 11 | properties: {} 12 | name: content_panel 13 | layout_properties: {slot: default} 14 | code: "from anvil import *\n\nclass $NAME$($NAME$Template):\n\n def __init__(self,\ 15 | \ **properties):\n # You must call self.init_components() before doing anything\ 16 | \ else in this function\n self.init_components(**properties)\n\n # Any\ 17 | \ code you write here will run when the form opens.\n \n" 18 | - name: Single-column layout 19 | description: A page with a single-column layout and a large header 20 | img: img/form-templates/material-single-column.png 21 | form: 22 | class_name: Form 23 | container: 24 | type: HtmlTemplate 25 | properties: {html: '@theme:single-column.html'} 26 | components: [] 27 | code: "from anvil import *\n\nclass $NAME$($NAME$Template):\n\n def __init__(self,\ 28 | \ **properties):\n # You must call self.init_components() before doing anything\ 29 | \ else in this function\n self.init_components(**properties)\n\n # Any\ 30 | \ code you write here will run when the form opens.\n" 31 | -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/readme_resources/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/85-87-full-stack-easy/readme_resources/code.png -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/readme_resources/edit-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/85-87-full-stack-easy/readme_resources/edit-ui.png -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/readme_resources/pub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/85-87-full-stack-easy/readme_resources/pub.png -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/readme_resources/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/85-87-full-stack-easy/readme_resources/register.png -------------------------------------------------------------------------------- /days/85-87-full-stack-easy/readme_resources/tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/85-87-full-stack-easy/readme_resources/tables.png -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/battle-table.csv: -------------------------------------------------------------------------------- 1 | Attacker,Rock,Gun,Lightning,Devil,Dragon,Water,Air,Paper,Sponge,Wolf,Tree,Human,Snake,Scissors,Fire Rock,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win Gun,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win Lightning,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win Devil,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win Dragon,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win Water,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win Air,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win Paper,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose Sponge,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose Wolf,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose Tree,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win,win Human,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win Snake,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win Scissors,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose Fire,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/data/session_factory.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy 2 | import sqlalchemy.orm 3 | # noinspection PyPackageRequirements 4 | import db.db_folder as db_folder 5 | # noinspection PyPackageRequirements 6 | from models.model_base import ModelBase 7 | # noinspection PyUnresolvedReferences,PyPackageRequirements 8 | from models import move, player, roll 9 | 10 | __factory = None 11 | 12 | 13 | def global_init(): 14 | global __factory 15 | 16 | full_file = db_folder.get_db_path('rock_paper_scissors.sqlite') 17 | conn_str = 'sqlite:///' + full_file 18 | 19 | engine = sqlalchemy.create_engine(conn_str, echo=False) 20 | ModelBase.metadata.create_all(engine) 21 | 22 | __factory = sqlalchemy.orm.sessionmaker(bind=engine) 23 | 24 | 25 | def create_session(): 26 | global __factory 27 | 28 | if __factory is None: 29 | global_init() 30 | 31 | return __factory() 32 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/db/db_folder.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_db_path(base_file): 5 | base_folder = os.path.dirname(__file__) 6 | return os.path.join(base_folder, base_file) 7 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/game_decider.py: -------------------------------------------------------------------------------- 1 | import csv 2 | from enum import Enum 3 | 4 | from models.roll import Roll 5 | 6 | __winner_lookup = {} 7 | 8 | 9 | class Decision(Enum): 10 | tie = 1 11 | win = 2 12 | lose = 3 13 | 14 | 15 | def decide(roll1: Roll, roll2: Roll) -> Decision: 16 | __build_decisions() 17 | 18 | if roll1.name == roll2.name: 19 | return Decision.tie 20 | 21 | roll1_wins = roll2.name in __winner_lookup[roll1.name] 22 | 23 | if roll1_wins: 24 | return Decision.win 25 | else: 26 | return Decision.lose 27 | 28 | 29 | def __build_decisions(): 30 | if __winner_lookup: 31 | return 32 | 33 | with open('battle-table.csv') as fin: 34 | reader = csv.DictReader(fin) 35 | for row in reader: 36 | __build_roll(row) 37 | 38 | 39 | def __build_roll(row: dict): 40 | row = dict(row) 41 | name = row['Attacker'] 42 | 43 | del row['Attacker'] 44 | del row[name] 45 | 46 | __winner_lookup[name] = set() 47 | for k in row.keys(): 48 | can_defeat = row[k].strip().lower() == 'win' 49 | if can_defeat: 50 | __winner_lookup[name].add(k) 51 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/models/model_base.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.declarative import declarative_base 2 | 3 | ModelBase = declarative_base() 4 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/models/move.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import sqlalchemy 3 | 4 | # noinspection PyPackageRequirements 5 | from models.model_base import ModelBase 6 | 7 | 8 | class Move(ModelBase): 9 | __tablename__ = 'moves' 10 | 11 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 12 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True) 13 | roll_id = sqlalchemy.Column(sqlalchemy.Integer, index=True) 14 | game_id = sqlalchemy.Column(sqlalchemy.String, index=True) 15 | roll_number = sqlalchemy.Column(sqlalchemy.Integer, index=True) 16 | player_id = sqlalchemy.Column(sqlalchemy.Integer, index=True) 17 | is_winning_play = sqlalchemy.Column(sqlalchemy.Boolean, index=True, default=False) 18 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/models/player.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import sqlalchemy 4 | 5 | # noinspection PyPackageRequirements 6 | from models.model_base import ModelBase 7 | 8 | 9 | class Player(ModelBase): 10 | __tablename__ = 'players' 11 | 12 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 13 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now) 14 | name = sqlalchemy.Column(sqlalchemy.String, nullable=False) 15 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/models/roll.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import sqlalchemy 4 | 5 | # noinspection PyPackageRequirements 6 | from models.model_base import ModelBase 7 | 8 | 9 | class Roll(ModelBase): 10 | __tablename__ = 'rolls' 11 | 12 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 13 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now) 14 | name = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False) 15 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps/requirements.txt: -------------------------------------------------------------------------------- 1 | sqlalchemy -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/battle-table.csv: -------------------------------------------------------------------------------- 1 | Attacker,Rock,Gun,Lightning,Devil,Dragon,Water,Air,Paper,Sponge,Wolf,Tree,Human,Snake,Scissors,Fire Rock,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win Gun,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win Lightning,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win Devil,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win Dragon,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win Water,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win Air,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win Paper,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose Sponge,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose Wolf,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose Tree,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win,win Human,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win Snake,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win Scissors,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose Fire,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/game_decider.py: -------------------------------------------------------------------------------- 1 | import csv 2 | from enum import Enum 3 | 4 | from models.roll import Roll 5 | 6 | __winner_lookup = {} 7 | 8 | 9 | class Decision(Enum): 10 | tie = 1 11 | win = 2 12 | lose = 3 13 | 14 | 15 | def decide(roll1: Roll, roll2: Roll) -> Decision: 16 | __build_decisions() 17 | 18 | if roll1.name == roll2.name: 19 | return Decision.tie 20 | 21 | roll1_wins = roll2.name in __winner_lookup[roll1.name] 22 | 23 | if roll1_wins: 24 | return Decision.win 25 | else: 26 | return Decision.lose 27 | 28 | 29 | def __build_decisions(): 30 | if __winner_lookup: 31 | return 32 | 33 | with open('battle-table.csv') as fin: 34 | reader = csv.DictReader(fin) 35 | for row in reader: 36 | __build_roll(row) 37 | 38 | 39 | def __build_roll(row: dict): 40 | row = dict(row) 41 | name = row['Attacker'] 42 | 43 | del row['Attacker'] 44 | del row[name] 45 | 46 | __winner_lookup[name] = set() 47 | for k in row.keys(): 48 | can_defeat = row[k].strip().lower() == 'win' 49 | if can_defeat: 50 | __winner_lookup[name].add(k) 51 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/game_service.py: -------------------------------------------------------------------------------- 1 | from typing import List, Optional 2 | 3 | from models.move import Move 4 | from models.player import Player 5 | from models.roll import Roll 6 | 7 | 8 | def get_game_history(game_id: str) -> List[Move]: 9 | # TODO: Return list of moves 10 | 11 | return [] 12 | 13 | 14 | def get_win_count(player: Player) -> int: 15 | # TODO: Count wins 16 | 17 | return 0 18 | 19 | 20 | def find_or_create_player(name: str) -> Player: 21 | player = Player() 22 | player.name = name 23 | return player 24 | 25 | 26 | def all_players() -> List[Player]: 27 | return [] 28 | 29 | 30 | def record_roll(player, roll: 'Roll', game_id: str, is_winning_play: bool, roll_num: int): 31 | move = Move() 32 | # move.player_id = player.id 33 | # move.roll_id = roll.id 34 | move.game_id = game_id 35 | move.is_winning_play = is_winning_play 36 | move.roll_number = roll_num 37 | 38 | # TODO: Record 39 | 40 | 41 | def all_rolls() -> List[Roll]: 42 | # TODO: Find all rolls. 43 | pass 44 | 45 | 46 | def find_roll(name: str) -> Optional['Roll']: 47 | # TODO: Find roll 48 | pass 49 | 50 | 51 | def create_roll(name: str) -> 'Roll': 52 | roll = Roll(name) 53 | # TODO: Save 54 | return roll 55 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/models/move.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | 4 | class Move: 5 | def __init__(self): 6 | self.roll_id = None 7 | self.game_id = None 8 | self.roll_number = None 9 | self.player_id = None 10 | self.is_winning_play = False 11 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/models/player.py: -------------------------------------------------------------------------------- 1 | class Player: 2 | 3 | def __init__(self): 4 | self.name = None 5 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/models/roll.py: -------------------------------------------------------------------------------- 1 | class Roll: 2 | 3 | def __init__(self, name: str): 4 | self.name = name 5 | -------------------------------------------------------------------------------- /days/91-93-sqlalchemy/demo/persistent_rps_starter/program.py: -------------------------------------------------------------------------------- 1 | import csv 2 | from typing import List 3 | 4 | import game_service 5 | from models.roll import Roll 6 | import game 7 | 8 | 9 | def main(): 10 | print_header() 11 | print_high_scores() 12 | print() 13 | 14 | rolls = build_rolls() 15 | 16 | name = input("What is your name? ") 17 | 18 | player1 = game_service.find_or_create_player(name) 19 | player2 = game_service.find_or_create_player("computer") 20 | 21 | game.game_loop(player1, player2, rolls) 22 | 23 | 24 | def build_rolls() -> List[Roll]: 25 | rolls = [] 26 | with open('battle-table.csv') as fin: 27 | reader = csv.DictReader(fin) 28 | for row in reader: 29 | rolls.append(build_roll(row)) 30 | 31 | return rolls 32 | 33 | 34 | def build_roll(row: dict): 35 | row = dict(row) 36 | name = row['Attacker'] 37 | roll = game_service.find_roll(name) 38 | if not roll: 39 | roll = game_service.create_roll(name) 40 | 41 | return roll 42 | 43 | 44 | def print_header(): 45 | print("----------------------------------------") 46 | print(" ROCK PAPER SCISSORS (DB Edition)") 47 | print("----------------------------------------") 48 | print() 49 | 50 | 51 | def print_high_scores(): 52 | players = game_service.all_players() 53 | wins = [ 54 | (p, game_service.get_win_count(p)) 55 | for p in players 56 | ] 57 | 58 | wins.sort(key=lambda wn: -wn[1]) 59 | for idx, w in enumerate(wins[:10], start=1): 60 | print(f" {idx}. {w[0].name} {w[1]} wins") 61 | 62 | 63 | if __name__ == '__main__': 64 | main() 65 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/final_search_app/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | 6 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 7 | 'duration, genres, rating, year, imdb_score') 8 | 9 | 10 | def find_movie_by_keyword(keyword: str) -> List[Movie]: 11 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 12 | return __get_results(url) 13 | 14 | 15 | def find_movie_by_director(director_name: str) -> List[Movie]: 16 | url = f'https://movieservice.talkpython.fm/api/director/{director_name}' 17 | return __get_results(url) 18 | 19 | 20 | def find_movie_by_imdb_code(imdb_code: str) -> List[Movie]: 21 | url = f'https://movieservice.talkpython.fm/api/movie/{imdb_code}' 22 | resp = requests.get(url) 23 | resp.raise_for_status() 24 | result = resp.json() 25 | if not result.get('imdb_code'): 26 | return [] 27 | 28 | return [Movie(**result)] 29 | 30 | 31 | def __get_results(url): 32 | resp = requests.get(url) 33 | resp.raise_for_status() 34 | results = resp.json() 35 | movies = [] 36 | for r in results.get('hits'): 37 | movies.append(Movie(**r)) 38 | return movies 39 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/final_search_app/build.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['build'], 7 | pathex=['/Users/mkennedy/github/talk-python/courses/100daysofcode/100days-course/days/94-96-guis/demos/final_search_app'], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | pyz = PYZ(a.pure, a.zipped_data, 18 | cipher=block_cipher) 19 | exe = EXE(pyz, 20 | a.scripts, 21 | exclude_binaries=True, 22 | name='build', 23 | debug=False, 24 | strip=False, 25 | upx=True, 26 | console=True ) 27 | coll = COLLECT(exe, 28 | a.binaries, 29 | a.zipfiles, 30 | a.datas, 31 | strip=False, 32 | upx=True, 33 | name='build') 34 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/final_search_app/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | from gooey import GooeyParser, Gooey 3 | 4 | 5 | @Gooey(program_name='Movie Search App', 6 | program_description="Search Talk Python's demo data for movies") 7 | def main(): 8 | print("--------------------------------------") 9 | print(" MOVIE SEARCH APP (GUI EDITION)") 10 | print("--------------------------------------") 11 | print() 12 | mode, value = get_params() 13 | 14 | if mode == 'Director': 15 | results = api.find_movie_by_director(value) 16 | elif mode == 'IMDB Code': 17 | results = api.find_movie_by_imdb_code(value) 18 | else: # mode == 'Keyword' 19 | results = api.find_movie_by_keyword(value) 20 | 21 | print(f'There are {len(results)} movies found.') 22 | for r in results: 23 | print(f"{r.title} with code {r.imdb_code} and director {r.director} has score {r.imdb_score}") 24 | 25 | 26 | def get_params(): 27 | parser = GooeyParser() 28 | parser.add_argument('search_term', help="The search term") 29 | parser.add_argument( 30 | dest='mode', 31 | widget='Dropdown', 32 | choices=['Director', 'IMDB Code', 'Keyword'] 33 | ) 34 | args = parser.parse_args() 35 | return args.mode, args.search_term 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/final_search_app/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | gooey -------------------------------------------------------------------------------- /days/94-96-guis/demos/starter_search_app/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | import requests 4 | import collections 5 | 6 | Movie = collections.namedtuple('Movie', 'imdb_code, title, director, keywords, ' 7 | 'duration, genres, rating, year, imdb_score') 8 | 9 | 10 | def find_movie_by_keyword(keyword: str) -> List[Movie]: 11 | url = f'https://movieservice.talkpython.fm/api/search/{keyword}' 12 | return __get_results(url) 13 | 14 | 15 | def find_movie_by_director(director_name: str) -> List[Movie]: 16 | url = f'https://movieservice.talkpython.fm/api/director/{director_name}' 17 | return __get_results(url) 18 | 19 | 20 | def find_movie_by_imdb_code(imdb_code: str) -> List[Movie]: 21 | url = f'https://movieservice.talkpython.fm/api/movie/{imdb_code}' 22 | resp = requests.get(url) 23 | resp.raise_for_status() 24 | result = resp.json() 25 | if not result.get('imdb_code'): 26 | return [] 27 | 28 | return [Movie(**result)] 29 | 30 | 31 | def __get_results(url): 32 | resp = requests.get(url) 33 | resp.raise_for_status() 34 | results = resp.json() 35 | movies = [] 36 | for r in results.get('hits'): 37 | movies.append(Movie(**r)) 38 | return movies 39 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/starter_search_app/program.py: -------------------------------------------------------------------------------- 1 | import api 2 | 3 | 4 | def main(): 5 | print("--------------------------------------") 6 | print(" MOVIE SEARCH APP (CLI EDITION)") 7 | print("--------------------------------------") 8 | print() 9 | print('How do you want to search?') 10 | mode = input("By [d]irector, [i]mdb code, or [k]eyword? ").strip().lower() 11 | 12 | if mode == 'd': 13 | director = input("Enter the director's name: ") 14 | results = api.find_movie_by_director(director) 15 | elif mode == 'i': 16 | code = input('Enter the IMDB code: ') 17 | results = api.find_movie_by_imdb_code(code) 18 | else: # mode == 'k' 19 | keyword = input('Enter your (single) keyword: ') 20 | results = api.find_movie_by_keyword(keyword) 21 | 22 | print(f'There are {len(results)} movies found.') 23 | for r in results: 24 | print(f"{r.title} with code {r.imdb_code} and director {r.director} has score {r.imdb_score}") 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /days/94-96-guis/demos/starter_search_app/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /days/94-96-guis/readme_resources/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/days/94-96-guis/readme_resources/app.png -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/client/api.py: -------------------------------------------------------------------------------- 1 | import uplink 2 | 3 | from uplink_helpers import raise_for_status, response_to_data 4 | 5 | 6 | @response_to_data 7 | @raise_for_status 8 | @uplink.json 9 | class GameService(uplink.Consumer): 10 | def __init__(self): 11 | super().__init__(base_url='http://localhost:5000') 12 | 13 | @uplink.get('/api/game/users/{username}') 14 | def find_user(self, username): 15 | pass 16 | 17 | @uplink.put('/api/game/users') 18 | def create_user(self, **kwargs: uplink.Body): 19 | pass 20 | 21 | @uplink.post('/api/game/games') 22 | def create_game(self, **kwargs: uplink.Body): 23 | pass 24 | 25 | @uplink.get('/api/game/rolls') 26 | def all_rolls(self): 27 | pass 28 | 29 | @uplink.get('/api/game/{game_id}/status') 30 | def game_status(self, game_id): 31 | pass 32 | 33 | @uplink.get('/api/game/top_scores') 34 | def top_scores(self): 35 | pass 36 | 37 | @uplink.post('/api/game/play_round') 38 | def play_round(self, **kwargs: uplink.Body): 39 | pass 40 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/client/game_app.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from api import GameService 4 | 5 | 6 | def main(): 7 | svc = GameService() 8 | 9 | print("Game app! (client)") 10 | print() 11 | print() 12 | print("TOP SCORES") 13 | for s in svc.top_scores(): 14 | print("{} scored {}".format(s.get('player').get('name'), s.get('score'))) 15 | print() 16 | 17 | game_id = svc.create_game().get('game_id') 18 | rolls = svc.all_rolls() 19 | player = svc.find_user("Charles") 20 | 21 | is_over = False 22 | while not is_over: 23 | name = player.get('name') 24 | roll = random.choice(rolls) 25 | rnd = svc.play_round(game_id=game_id, user=name, roll=roll) 26 | is_over = rnd.get('is_final_round') 27 | print("Round {}".format(rnd.get('round_number'))) 28 | print("{} rolls {}".format(name, roll)) 29 | print("{} rolls {}".format(rnd.get('opponent').get('name'), rnd.get('computer_roll').get('name'))) 30 | print("Resulting in {}".format(rnd.get('round_outcome'))) 31 | print("") 32 | 33 | game_status = svc.game_status(game_id) 34 | print("Game is over, outcome: Winner: {}".format(game_status.get('winner').get('name'))) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/client/requirements.txt: -------------------------------------------------------------------------------- 1 | uplink -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/client/uplink_helpers.py: -------------------------------------------------------------------------------- 1 | import uplink 2 | from requests import Response 3 | 4 | 5 | class FormatError(Exception): 6 | pass 7 | 8 | 9 | @uplink.response_handler 10 | def raise_for_status(response: Response): 11 | response.raise_for_status() 12 | return response 13 | 14 | 15 | @uplink.response_handler 16 | def response_to_data(response: Response): 17 | try: 18 | return response.json() 19 | except Exception as x: 20 | raise FormatError("Invalid format, could not parse JSON. Error: {}, status={}, text={}".format( 21 | x, response.status_code, response.text 22 | )) from x 23 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/app.py: -------------------------------------------------------------------------------- 1 | import flask 2 | from game_logic import game_decider, game_service 3 | from views import game_api, home 4 | 5 | app = flask.Flask(__name__) 6 | 7 | 8 | def main(): 9 | build_starter_data() 10 | build_views() 11 | run_web_app() 12 | 13 | 14 | def build_views(): 15 | game_api.build_views(app) 16 | home.build_views(app) 17 | 18 | 19 | def build_starter_data(): 20 | roll_names = game_decider.all_roll_names() 21 | game_service.init_rolls(roll_names) 22 | 23 | computer = game_service.find_player('computer') 24 | if not computer: 25 | game_service.create_player('computer') 26 | 27 | 28 | def run_web_app(): 29 | app.run(debug=True) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/data/battle-table.csv: -------------------------------------------------------------------------------- 1 | Attacker,Rock,Gun,Lightning,Devil,Dragon,Water,Air,Paper,Sponge,Wolf,Tree,Human,Snake,Scissors,Fire Rock,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win Gun,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win Lightning,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win Devil,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win,win Dragon,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win,win Water,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win,win Air,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose,win Paper,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose,lose Sponge,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose,lose Wolf,lose,lose,win,win,win,win,win,win,win,draw,lose,lose,lose,lose,lose Tree,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win,win Human,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win,win Snake,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,win,win Scissors,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw,lose Fire,lose,lose,lose,lose,lose,lose,lose,win,win,win,win,win,win,win,draw -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/data/db_folder.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_db_path(base_file): 5 | base_folder = os.path.dirname(__file__) 6 | return os.path.join(base_folder, base_file) 7 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/game_logic/models/model_base.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.ext.declarative import declarative_base 2 | 3 | ModelBase = declarative_base() 4 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/game_logic/models/move.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import sqlalchemy 3 | 4 | # noinspection PyPackageRequirements 5 | from game_logic.models.model_base import ModelBase 6 | 7 | 8 | class Move(ModelBase): 9 | __tablename__ = 'moves' 10 | 11 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 12 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now, index=True) 13 | roll_id = sqlalchemy.Column(sqlalchemy.Integer, index=True) 14 | game_id = sqlalchemy.Column(sqlalchemy.String, index=True) 15 | roll_number = sqlalchemy.Column(sqlalchemy.Integer, index=True) 16 | player_id = sqlalchemy.Column(sqlalchemy.Integer, index=True) 17 | is_winning_play = sqlalchemy.Column(sqlalchemy.Boolean, index=True, default=False) 18 | 19 | def to_json(self, roll: 'Roll', player: 'Player'): 20 | if self.roll_id != roll.id: 21 | raise Exception("Mismatched roll values") 22 | if self.player_id != player.id: 23 | raise Exception("Mismatched player values") 24 | 25 | return { 26 | 'id': self.id, 27 | 'created': self.created.isoformat(), 28 | 'roll_id': self.roll_id, 29 | 'roll': roll.name, 30 | 'player_id': self.player_id, 31 | 'player': player.name, 32 | 'roll_number': self.roll_number, 33 | 'is_winning_play': self.is_winning_play, 34 | } 35 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/game_logic/models/player.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import sqlalchemy 4 | 5 | # noinspection PyPackageRequirements 6 | from game_logic.models.model_base import ModelBase 7 | 8 | 9 | class Player(ModelBase): 10 | __tablename__ = 'players' 11 | 12 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 13 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now) 14 | name = sqlalchemy.Column(sqlalchemy.String, nullable=False) 15 | 16 | def to_json(self): 17 | return { 18 | 'id': self.id, 19 | 'created': self.created.isoformat(), 20 | 'name': self.name, 21 | } 22 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/game_logic/models/roll.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | import sqlalchemy 4 | 5 | # noinspection PyPackageRequirements 6 | from game_logic.models.model_base import ModelBase 7 | 8 | 9 | class Roll(ModelBase): 10 | __tablename__ = 'rolls' 11 | 12 | id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) 13 | created = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.datetime.now) 14 | name = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False) 15 | 16 | def to_json(self): 17 | return { 18 | 'id': self.id, 19 | 'created': self.created.isoformat(), 20 | 'name': self.name, 21 | } -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/game_logic/session_factory.py: -------------------------------------------------------------------------------- 1 | import sqlalchemy 2 | import sqlalchemy.orm 3 | # noinspection PyPackageRequirements 4 | from data import db_folder 5 | # noinspection PyPackageRequirements 6 | from game_logic.models.model_base import ModelBase 7 | # noinspection PyUnresolvedReferences,PyPackageRequirements 8 | from game_logic.models import move, player, roll 9 | 10 | __factory = None 11 | 12 | 13 | def global_init(): 14 | global __factory 15 | 16 | full_file = db_folder.get_db_path('rock_paper_scissors.sqlite') 17 | conn_str = 'sqlite:///' + full_file 18 | 19 | engine = sqlalchemy.create_engine(conn_str, echo=False) 20 | ModelBase.metadata.create_all(engine) 21 | 22 | __factory = sqlalchemy.orm.sessionmaker(bind=engine) 23 | 24 | 25 | def create_session(): 26 | global __factory 27 | 28 | if __factory is None: 29 | global_init() 30 | 31 | return __factory() 32 | -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | sqlalchemy -------------------------------------------------------------------------------- /days/97-99-online-game-api/demo_app/web/views/home.py: -------------------------------------------------------------------------------- 1 | import flask 2 | 3 | 4 | def build_views(app): 5 | @app.route('/') 6 | def index(): 7 | return "Hello world!!!" 8 | 9 | @app.errorhandler(404) 10 | def not_found(_): 11 | return flask.Response("The page was not found.", status=404) 12 | 13 | 14 | -------------------------------------------------------------------------------- /readme_resources/100days-course-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/readme_resources/100days-course-flow.png -------------------------------------------------------------------------------- /readme_resources/100days-course.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/talkpython/100daysofcode-with-python-course/233fc03ef1d44faf415d396e2e9ab810f2b036ab/readme_resources/100days-course.png -------------------------------------------------------------------------------- /requirements/bob-environment.yml: -------------------------------------------------------------------------------- 1 | # This file can be used by Anaconda users in order to create their virtual 2 | # environment. If you open up the command prompt/shell in the 3 | # 100daysofcode-with-python-course directory, simply use this command: 4 | # 5 | # conda env create -f requirements/bob-environment.yml 6 | name: 100days 7 | channels: 8 | - defaults 9 | dependencies: 10 | - cython 11 | - feedparser 12 | - ipykernel 13 | - jupyter 14 | - matplotlib 15 | - numpy 16 | - pillow 17 | - plotly 18 | - pytest 19 | - pytest-cov 20 | - python=3.6.6 21 | - requests 22 | - selenium 23 | - pip: 24 | - tweepy 25 | - wordcloud 26 | - PyGithub 27 | -------------------------------------------------------------------------------- /requirements/bob-requirements.txt: -------------------------------------------------------------------------------- 1 | # all notebooks 2 | jupyter 3 | ipykernel 4 | # list comprehensions 5 | requests 6 | # twitter API 7 | matplotlib 8 | numpy 9 | Pillow 10 | tweepy 11 | wordcloud 12 | # github api 13 | PyGithub 14 | # selenium 15 | selenium 16 | # data viz 17 | feedparser 18 | plotly 19 | # pytest 20 | pytest 21 | pytest-cov 22 | -------------------------------------------------------------------------------- /transcripts/00-intro/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 There are a lot of things that people do 2 | 00:01 to support each other and encourage themselves 3 | 00:04 to stay focused and keep going on #100DaysOfCode. 4 | 00:07 But there's really just two main rules 5 | 00:09 and they're really really simple. 6 | 00:11 The first rule is to code a minimum of an hour 7 | 00:15 every day for the next 100 days. 8 | 00:17 And I would say taking a coding class 9 | 00:20 like learning the lessons in this course 10 | 00:22 and then coding a little bit counts, right? 11 | 00:24 You're immersing yourself in code 12 | 00:25 for at least an hour a day every single day 13 | 00:28 for the 100 days. 14 | 00:29 And if you got sick, like you saw the person before 15 | 00:31 had gotten sick, had to take a day off, 16 | 00:33 that's okay you just add some days on the end. 17 | 00:35 Have sick days and just move it to the end. 18 | 00:38 The second rule is a public commitment 19 | 00:40 to making progress and keeping with it. 20 | 00:43 And they way that works is to tweet 21 | 00:45 or to put onto somewhere like Facebook 22 | 00:47 #100DaysOfCode with an update every day. 23 | 00:51 The PyBytes platform actually is going 24 | 00:53 to help you a lot with this, but however you want to do it 25 | 00:55 it's code an hour a day and 26 | 00:57 share your progress every day. 27 | 01:00 Super simple rules, and we hope this course 28 | 01:02 really makes this work for you. 29 | -------------------------------------------------------------------------------- /transcripts/00-intro/7.txt: -------------------------------------------------------------------------------- 1 | 00:00 Do you need a little help with the Python language? 2 | 00:02 Of course, we'll cover much of the little details 3 | 00:05 and definitely the advanced features 4 | 00:07 as we go through this course, 5 | 00:08 but we don't start from the absolute beginning. 6 | 00:10 What is a variable? 7 | 00:11 What is a loop? 8 | 00:12 Instead, we've included a Python language primer. 9 | 00:15 So when you look at Python, 10 | 00:16 if it's, you know, a little fuzzy, 11 | 00:17 maybe you've done it a long time ago, but you've forgotten. 12 | 00:20 You haven't done very much of it. 13 | 00:21 Well, we put something in here to help clear it up. 14 | 00:24 So anytime you're confused about something in the language, 15 | 00:28 just jump down to the appendix, Python Language Concepts. 16 | 00:32 Find that thing, watch the one to two-minute video. 17 | 00:35 Hopefully, that'll clear things right up. 18 | 00:37 You'll find this at the end of the course. 19 | -------------------------------------------------------------------------------- /transcripts/01-datetimes/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day, this is Julian Sequeira 2 | 00:02 and welcome to the course. 3 | 00:03 We're going to open things up with playing with datetimes. 4 | 00:07 Probably not the most interesting thing for most of us 5 | 00:10 and if you're like me, you probably hate it 6 | 00:13 because they can be very finicky. 7 | 00:15 So, with datetimes I wanted to run us through 8 | 00:19 some of the more basic concepts of it. 9 | 00:21 Just go with it, there will be more advanced stuff coming up 10 | 00:25 but for now we're going to stick with 11 | 00:26 just the basics to get you through with datetimes 12 | 00:29 specifically around datetimes.date 13 | 00:33 and then datetimes.timedelta. 14 | 00:36 So, we'll flick through into that, 15 | 00:38 carry on, and let's get started. 16 | -------------------------------------------------------------------------------- /transcripts/04-collections/1.txt: -------------------------------------------------------------------------------- 1 | 00:01 Welcome back to the 100 days of Python. 2 | 00:03 In the coming three days I will guide you 3 | 00:04 through the collections module, 4 | 00:06 a very convenient module 5 | 00:08 to work with more advanced data structures. 6 | 00:10 First we look at namedtuples 7 | 00:12 and how they can make your code 8 | 00:13 more readable and elegant. 9 | 00:15 Next we look at defaultdict, 10 | 00:17 which is convenient to build up 11 | 00:18 a nested data structure. 12 | 00:20 Third, counter, saves a lot of code 13 | 00:22 to find the most common thing in a collection, 14 | 00:26 and lastly, deque, which can tremendously improve 15 | 00:29 your performance based on the operations 16 | 00:31 you want to do on your sequence, 17 | 00:33 and for the second and third day 18 | 00:35 I got a movie dataset 19 | 00:36 where you can put the collections module into practice. 20 | -------------------------------------------------------------------------------- /transcripts/04-collections/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 Get Pythonic with a collections module. 2 | 00:03 We are all familiar with dict, list, set, and tuple. 3 | 00:05 The collections module 4 | 00:07 adds a few other specialized ones that are very useful. 5 | 00:12 Let's import the modules we're going to use. 6 | 00:20 A namedtuple is a convenient way 7 | 00:22 to define a class without methods. 8 | 00:24 We all familiar with a normal tuple, 9 | 00:28 which you can define with parenthesss, 10 | 00:30 and one or more elements. 11 | 00:35 The thing with the classic tuple, 12 | 00:36 though, is that the order is not 13 | 00:38 really meaningful, so if you print 14 | 00:43 the user name and the user role, 15 | 00:48 user index zero is a user index one, 16 | 00:54 and you already notice that the indexing 17 | 00:56 is not really saying that much. 18 | 00:59 Is there a more readable way 19 | 01:00 to define these kinds of tuples? 20 | 01:04 And yes, you can use a namedtuple, so let's define one. 21 | 01:08 User equals namedtuple, and you give it a name, 22 | 01:14 and the fields or arguments it takes, so name and role. 23 | 01:22 And let's create a user, 24 | 01:27 with user and I give it a name 25 | 01:32 Bob and role equals coder. 26 | 01:36 The nice thing, then, is that you can 27 | 01:38 access the entries like this, instead of 28 | 01:41 indexing with zero, one, etc. 29 | 01:44 So this is much more meaningful 30 | 01:49 And to see that in a print statement. 31 | 01:57 So, use namedtuples. 32 | 02:00 It's very easy to set up, 33 | 02:02 and it definitely makes your code more readable. 34 | -------------------------------------------------------------------------------- /transcripts/04-collections/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's move on with Counter. 2 | 00:02 Let's say we have a text which is split into words, 3 | 00:06 and we want to count the most common words. 4 | 00:11 Before I knew about collections, 5 | 00:14 I would write something like this. 6 | 00:26 There you go. 7 | 00:28 I had to loop over words, keep a dictionary, 8 | 00:32 see if the key was in the dictionary, 9 | 00:35 if not, initialize to zero. 10 | 00:38 If it's in there do plus one. 11 | 00:39 Then I had to loop over the items over the key value pairs, 12 | 00:45 sort them and use lambda to sort by value. 13 | 00:49 In reversed order and take a slice to get it to five. 14 | 00:53 Now compare that with using Counter, 15 | 00:55 and its most common method. 16 | 01:00 It's like magic, right? 17 | 01:02 One line of code, you pass the words list into the Counter, 18 | 01:06 and you call most common and you give the number 19 | 01:09 of top words you want to see and compare that 20 | 01:13 with all the work I had to do here and how easy it gets 21 | 01:17 by using the collections, Counter. 22 | -------------------------------------------------------------------------------- /transcripts/04-collections/5.txt: -------------------------------------------------------------------------------- 1 | 00:00 So a quick overview of we've learned so far, 2 | 00:02 namedtuples, an elegant and readable way to create tuples, 3 | 00:07 and instead of user index zero, and index one, 4 | 00:10 you can say user.name and user.role. 5 | 00:13 A defaultdict is great way 6 | 00:15 to buildup a nested data structure, 7 | 00:18 you don't get key errors, because the internals 8 | 00:20 make sure that the value gets initialized 9 | 00:23 before appending to it. 10 | 00:25 Counter, don't reinvent the wheel, 11 | 00:28 so here at the top you see all the code 12 | 00:30 I needed to get the top five words in a string, 13 | 00:34 and below we did the same, 14 | 00:35 but only with one line of code, very powerful. 15 | 00:38 A deque, so lists are your best friend, 16 | 00:41 but if you have to insert at them at the start, 17 | 00:45 for example, they get very slow. 18 | 00:48 So deques are great if you need to insert 19 | 00:50 and remove at both ends of the sequence. 20 | 00:52 And now it's your turn. 21 | -------------------------------------------------------------------------------- /transcripts/04-collections/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 days of Python, 2 | 00:02 and the third day of the collections module. 3 | 00:05 Now it's time to get some more practice yourself, 4 | 00:07 so I encourage you to try to use 5 | 00:10 the new collection's data types in your scripts. 6 | 00:13 We did the #100DaysOfCode ourselves 7 | 00:15 and we made a module index script 8 | 00:18 which lists all the modules we used 9 | 00:21 and the days we used them, 10 | 00:22 so you can go to our log and look up those days 11 | 00:25 and look at the scripts that used the collections 12 | 00:28 in one way or the other. 13 | 00:30 This was the script to identify if a tip 14 | 00:32 was already submitted to pytip, 15 | 00:34 and here we use the name namedtuple. 16 | 00:37 And this was the script I was just showed you 17 | 00:38 about the module indexer, 18 | 00:40 and here we used defaultdict and Counter. 19 | 00:43 So you can look at more examples 20 | 00:44 for where we used those data types, 21 | 00:46 but maybe you can refer to some of your code 22 | 00:48 to start using collections more. 23 | 00:51 And don't forget to mention 100 days of Python 24 | 00:54 when you tweet out your progress. 25 | 00:56 That's a great way to keep on track. 26 | 00:58 Good luck, enjoy, and remember, 27 | 01:01 keep calm and code in Python. 28 | -------------------------------------------------------------------------------- /transcripts/07-data-structures/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day everyone. 2 | 00:01 This is Julian Sequeira and welcome 3 | 00:03 to Python Data Structures. 4 | 00:05 So this series of lessons in going to walk you through 5 | 00:08 the basics of lists, tuples, and dictionaries. 6 | 00:13 So hopefully stuff you've seen before, 7 | 00:16 but this should be a good refresher. 8 | 00:17 There'll be a couple of videos to watch, 9 | 00:20 but then there'll be some exercises as well. 10 | 00:22 So, nothing left to say. 11 | 00:24 Let's get cracking. 12 | -------------------------------------------------------------------------------- /transcripts/10-testing/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the Hundred Days of Python. 2 | 00:02 In the coming three days I will show you 3 | 00:04 how you can test the program with pytest. 4 | 00:06 It's a popular testing framework, 5 | 00:08 often preferred over the standard libraries unittest. 6 | 00:11 And you will see why. 7 | 00:13 For this lesson I prepared a guessing game, 8 | 00:15 which lets you guess a number from the command line. 9 | 00:18 And although is a simple program, 10 | 00:20 it has a lot to offer in showing how to use pytest, 11 | 00:24 for example to validate errors, 12 | 00:26 capture standard output, 13 | 00:28 mocking certain functionality, and more. 14 | 00:31 By writing the test, I will also show you 15 | 00:34 how you can use coverage, to see how much 16 | 00:37 of your code base, or in this case, 17 | 00:39 the script is covered by tests. 18 | 00:41 And by the end of this session, 19 | 00:42 it should be easy for you 20 | 00:44 to write tests for your code, an important skill. 21 | -------------------------------------------------------------------------------- /transcripts/100-day-one-hundred/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Wow, look where you are! 2 | 00:02 It's Day 100. 3 | 00:03 This is literally the last day of your #100DaysOfCode. 4 | 00:08 Congratulations, it's time to freestyle! 5 | 00:10 You've earned a little bit of freedom. 6 | 00:12 So is there some project that you've worked on so far 7 | 00:15 that maybe you didn't finish, you really wanted to? 8 | 00:17 Go back and finish that one. 9 | 00:19 Is there some derivative type thing you want to create? 10 | 00:22 Like maybe you'd like a web version of The Wizard game? 11 | 00:25 Then go build that. 12 | 00:27 Of course it's your time to freestyle, 13 | 00:28 so if you would rather just go do something 14 | 00:30 totally different, something you wanted explore 15 | 00:33 as part of this journey, here's your final day 16 | 00:35 to go work on that project. 17 | 00:37 Whatever it is you want to do. 18 | 00:38 You've earned this, go have fun 19 | 00:41 and celebrate this by working for the final day 20 | 00:43 on something you're super excited about. 21 | -------------------------------------------------------------------------------- /transcripts/101-conclusion/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Look at that, you've done 100 days. 2 | 00:03 You've made it! 3 | 00:04 Can you believe you've actually done 4 | 00:05 a #100DaysOfCode and completed this entire journey? 5 | 00:10 Well, your adventure is both done 6 | 00:12 and also just beginning. 7 | 00:14 Congratulations. 8 | 00:15 There's so much more code you can write, 9 | 00:18 so many more projects and things that you can start 10 | 00:21 with all the experience you've gained in this course, 11 | 00:24 and I hope you do so, and I hope you share it 12 | 00:26 with us on social media. 13 | 00:27 We love hear about our students being successful. 14 | -------------------------------------------------------------------------------- /transcripts/101-conclusion/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Right now, you're certainly familiar 2 | 00:01 with the GitHub Repository. 3 | 00:03 That's where all the instructions and the starter code 4 | 00:05 and the data and what not has been for 5 | 00:08 all the 100 Days projects. 6 | 00:10 But I still want to emphasize one more time: 7 | 00:13 maybe you haven't starred, maybe haven't forked this, 8 | 00:15 I want you to at least go to GitHub and start 9 | 00:18 and probably fork it, 10 | 00:19 so you have a permanent history of this. 11 | 00:21 You've done 100 days! 12 | 00:23 You've gone on this entire journey. 13 | 00:24 Make sure you take the source code with you. 14 | 00:26 I'm sure you'll find it useful down the line. 15 | -------------------------------------------------------------------------------- /transcripts/101-conclusion/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now that you're just about to complete this class, 2 | 00:02 I want to give you a couple of resources 3 | 00:04 to help you dig deeper 4 | 00:05 and connect further with the community. 5 | 00:08 First of all, the Talk Python to Me podcast. 6 | 00:10 You probably know this podcast, 7 | 00:11 maybe you subscribe to it but if you don't, 8 | 00:14 head over to talkpython.fm and check out the podcast. 9 | 00:18 You will the hear the stories and the people behind 10 | 00:21 so many of the projects that you worked with. 11 | 00:23 You want to hear about SQLAlchemy? 12 | 00:26 Well, I had Mike Bayer on the show, 13 | 00:28 who was the guy who created it and continues to maintain it. 14 | 00:30 Want to learn about contributing to open source? 15 | 00:32 I did a whole panel on that. 16 | 00:34 Looking to get your first job in Python? 17 | 00:36 I actually did a two episode, 12-person panel, 18 | 00:40 both people who just got their jobs 19 | 00:42 and who are hiring managers. 20 | 00:45 Whatever it is you want to dig deeper 21 | 00:47 into in Python and the community, 22 | 00:49 you can probably find it over here. 23 | 00:52 Also, stay up on the latest news, 24 | 00:53 check out my other podcast Python Bytes. 25 | 00:55 Over at Python Bytes, Brian Okken and I 26 | 00:58 share the latest headlines and news 27 | 01:00 in what's hot and what's happening in the Python space. 28 | 01:03 A great way to keep up on new packages in libraries 29 | 01:06 that maybe you haven't heard of. 30 | -------------------------------------------------------------------------------- /transcripts/101-conclusion/5.txt: -------------------------------------------------------------------------------- 1 | 00:00 Finishing the 100 Days of Python is both 2 | 00:03 an ending and a start of a great Python journey. 3 | 00:07 We encourage you to go to PyBites 4 | 00:10 and subscribe to our monthly newsletter. 5 | 00:13 And keep an eye on the articles, news and code challenges 6 | 00:17 we launch on our website. 7 | 00:19 We are here to teach you Python. 8 | 00:21 Of course, we are learning Python ourselves. 9 | 00:24 It's a never ending journey, 10 | 00:26 and we're super passionate about it. 11 | 00:28 And we are not planning to stop any time soon. 12 | 00:31 So, we hope to salute you at PyBites. 13 | 00:34 Additionally, a couple of months ago, 14 | 00:36 we launched Code Challenges, 15 | 00:38 where we integrated a year of blog challenges. 16 | 00:41 And we also launched a new line of Bites of Py, 17 | 00:44 which are smaller exercises you can code up in a browser. 18 | 00:47 We are stoked about this platform. 19 | 00:49 It's not only teaching you programming and Python, 20 | 00:52 it also shows how to do it in the most Pythonic way. 21 | 00:55 And we are rapidly expanding this platform 22 | 00:58 adding bites and code challenges. 23 | 01:00 So this is a great way to keep up the momentum you gained 24 | 01:03 throughout this course 25 | 01:04 by keeping calm and code in Python, 26 | 01:07 every single day. 27 | 01:09 Good luck and we hope to see you there. 28 | -------------------------------------------------------------------------------- /transcripts/101-conclusion/6.txt: -------------------------------------------------------------------------------- 1 | 00:00 You made it to the end, congratulations. 2 | 00:02 I hope you had as much fun inspiration 3 | 00:05 as we had preparing the course 4 | 00:07 and you got practice on a lot of different topics 5 | 00:09 which you can now take to the next level. 6 | 00:12 And I hope that you keep using Python in your daily work. 7 | 00:16 Feel free to reach out on Twitter 8 | 00:18 and share what you're working on 9 | 00:19 and good luck on your further Python adventure. 10 | 00:23 Congratulations on completing the 11 | 00:24 #100DaysOfCode in Python. 12 | 00:26 This is a huge milestone and huge achievement 13 | 00:29 so you should be very proud. 14 | 00:31 It's important though to continue coding. 15 | 00:33 Don't let this be the end. 16 | 00:35 Make sure just like with any other skill 17 | 00:37 you keep practicing, you keep coding, 18 | 00:39 and you keep working on it and you'll only get better. 19 | 00:42 So we look forward to seeing all the cool things 20 | 00:44 you come up with going forward. 21 | 00:45 Make sure to ping us on Twitter and Facebook 22 | 00:48 and wherever else you can think to message us. 23 | 00:51 As I've said in the course, keep calm and code in Python. 24 | 00:54 Thank you for taking our course. 25 | 00:55 It was a pleasure to put it together for you. 26 | 00:58 We hope you accomplish amazing things 27 | 00:59 with what you've learned here. 28 | 01:01 If you enjoyed the course, 29 | 01:02 please share it with your coworkers 30 | 01:03 and friends on social media. 31 | 01:06 Thanks and goodbye. 32 | 01:08 Thanks and goodbye. 33 | 01:10 Thanks and goodbye. 34 | -------------------------------------------------------------------------------- /transcripts/13-text-games/6.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's quickly review the concepts around classes 2 | 00:02 and remember that classes 3 | 00:03 are the blueprints from which we create objects 4 | 00:06 and those objects are the things that act 5 | 00:09 and take on the data of our application. 6 | 00:12 So we start by using them in the class keyword 7 | 00:14 and then we just make up a name, 8 | 00:15 this is going to be the name of the blueprint, 9 | 00:18 or the type that we create, here we called it a creature. 10 | 00:21 And then we add a dunder init, 11 | 00:24 in one of these magic methods here 12 | 00:25 and every method that is on a class 13 | 00:27 has this self message what's called 14 | 00:29 a static method or a class method 15 | 00:31 and they always have self but, 16 | 00:33 but we don't have to explicitly pass those, 17 | 00:34 Python takes care of that for us. 18 | 00:36 If we want additional premiers, they go after self, 19 | 00:38 so name and the level and we're going to assign new fields 20 | 00:43 to this by saying self.name equals name 21 | 00:45 and the new ones for self.level equals the level. 22 | 00:49 We also can add behaviors by adding additional functions, 23 | 00:52 so get_defensive_role() for example. 24 | -------------------------------------------------------------------------------- /transcripts/13-text-games/9.txt: -------------------------------------------------------------------------------- 1 | 00:00 Alright third day, 2 | 00:01 if you're not done with the first two days, 3 | 00:03 just finish that up. 4 | 00:04 Just get your standard 3-way 5 | 00:06 Rock, Paper, Scissors working. 6 | 00:07 However, if you feel like you want to like, 7 | 00:09 take this to the next level and you got done really quickly, 8 | 00:12 if you've got some extra time left over, 9 | 00:13 try this 15-way Rock, Paper, Scissors. 10 | 00:16 This diagram is actually really hard to understand, 11 | 00:19 so I put together a battle CSV here 12 | 00:23 that tells you if the attacker is a gun 13 | 00:25 and the attacker attacks a dragon, 14 | 00:27 will a gun defeat a dragon? 15 | 00:29 Or does the dragon, over here dragon defeat a gun, 16 | 00:33 note the dragon loses to the gun, 17 | 00:35 but the gun defeats the dragon. 18 | 00:37 So you can think of this like, 19 | 00:38 sort of halfway redundant. 20 | 00:40 You really only need half this table, 21 | 00:42 but having that table is super helpful. 22 | 00:45 And here's a little bit of code, 23 | 00:46 we haven't gotten to CSVs yet, 24 | 00:47 but here's a little bit of code that will read that in 25 | 00:50 and you can use it to sort of parse that 26 | 00:52 and probably build from. 27 | 00:54 Okay, so if you're feeling super adventurous 28 | 00:57 and you've got extra time, 29 | 00:58 work on this Rock, Paper, Scissors 15-way, 30 | 01:01 otherwise just build standard 3-way rock-paper-scissor 31 | 01:03 and hope you have a lot of fun modeling these little games 32 | 01:06 with classes. 33 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 days of Python. 2 | 00:02 In the coming three days I will guide you 3 | 00:04 through list comprehensions and generators 4 | 00:07 two of my favorite features of the language. 5 | 00:09 We're going to look at how you can make 6 | 00:12 a for loop with an embedded if statement 7 | 00:15 more Pythonic by using list comprehensions, 8 | 00:19 then we will load in Harry Potter 9 | 00:21 and use list comprehensions to filter out 10 | 00:23 non valid and stop words. 11 | 00:26 Next up, generators. 12 | 00:28 We start very simple with the concept 13 | 00:31 of the yield statement writing a simple generator, 14 | 00:34 we look at the stop iteration exception, 15 | 00:37 and how the for loop catches that for you. 16 | 00:40 We move on to more interesting examples 17 | 00:43 and finally compare performance of lists 18 | 00:46 and generators, because if your data set grows 19 | 00:50 you definitely want to know about generators. 20 | 00:52 The second day I have practical exercises 21 | 00:56 to train your new gained list comprehension 22 | 00:59 and generator skills. 23 | 01:01 The third day I will show you solutions to those 24 | 01:04 exercises and I challenge you to take 25 | 01:07 a more advanced generator exercise 26 | 01:10 replicating Unix pipelines and it will be a lot of fun. 27 | 01:14 So, lets dive straight into those two Python power tools. 28 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/10.txt: -------------------------------------------------------------------------------- 1 | 00:00 Alright, you're almost there. 2 | 00:02 To get some more practice, I put together 3 | 00:04 two smaller exercises, or bites, 4 | 00:08 and one bigger co-challenge. 5 | 00:11 This one, you will recognize the name's list 6 | 00:14 but it's a little different 7 | 00:15 because you have to take duplicate names out 8 | 00:17 and sort the names and find the shortest first name 9 | 00:21 and, of course, you will be using this comprehensions. 10 | 00:24 Secondly, what we did not touch upon, 11 | 00:27 is dictionary comprehensions, 12 | 00:29 so, you might look that up 13 | 00:31 and go through bite 26, where you have to 14 | 00:34 do some operations on this dictionary 15 | 00:38 and this set using a dictionary comprehension. 16 | 00:41 And the co-challenge is Generators for Fun 17 | 00:44 and Profit, a challenge we run some time ago. 18 | 00:46 And this will be a fun one because you have to 19 | 00:48 turn this Unix pipline into multiple generators. 20 | 00:51 So, I think that's a great way to get some 21 | 00:54 more practice using generators. 22 | 00:56 Three exercises, see how far you can get 23 | 00:59 during this third day of this lesson 24 | 01:02 and, of course, share your work. 25 | 01:03 Put a tweet out with #100DaysOfCode. 26 | 01:06 It's a great way to get visibility of your work 27 | 01:09 and, of course, we'll be happy to see 28 | 01:11 how you progressed this section. 29 | 01:13 Good luck. Have fun. Keep calm and code in Python. 30 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/5.txt: -------------------------------------------------------------------------------- 1 | 00:00 A common use case I find for generators 2 | 00:02 is to build up my sequence. 3 | 00:04 So, let's define a list of options. 4 | 00:07 Red, yellow, blue, white, black, green, purple. 5 | 00:12 And in my older code, I will do something like, 6 | 00:22 And that's fine, we just keep an internal list, 7 | 00:26 and append to it and return it. 8 | 00:30 Just to show you how you can do this in a more 9 | 00:32 concise way with a generator. 10 | 00:35 I'm just calling it the same name, 11 | 00:38 but appending _gen. 12 | 00:40 It's the same for loop, 13 | 00:42 but instead of building up a new list, 14 | 00:44 I'm going to use the yield keyword 15 | 00:46 to yield the values one by one. 16 | 00:52 Alright, let's see what that gives us, a generator. 17 | 00:59 And a way to materialize the generator 18 | 01:03 at one go is to convert it into a list, 19 | 01:12 and there you go. So this is a shorter, more concise way 20 | 01:14 to build up a list or sequence, 21 | 01:16 and it's also faster if your data set grows, 22 | 01:20 because it's evaluated lazily. 23 | 01:23 And actually to show that in practice, 24 | 01:24 in the next section, I will compare a list 25 | 01:27 and a generator in performance. 26 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/6.txt: -------------------------------------------------------------------------------- 1 | 00:00 I've said it a couple of times now that generators 2 | 00:03 can gain you performance when your data set grows. 3 | 00:06 So why not see that in action, and define a million years, 4 | 00:10 and loop over them and see which years are leap years. 5 | 00:14 So let me write it out and I will explain it next. 6 | 00:28 Okay so, first I have a leap years list 7 | 00:31 that builds up the list of a million years, 8 | 00:34 checking the isleap(), and I'm using calendar.isleap(), 9 | 00:37 which is a nice built in way to do that. 10 | 00:39 And the second function uses a generator, 11 | 00:41 so it's the same loop, but it yields the year. 12 | 00:44 So it's not building up the whole list in one go. 13 | 00:47 So let's use the timeit module tool, 14 | 00:49 time both functions. 15 | 00:56 And it's taking a bit. 16 | 00:58 Let's do the same for the generator. 17 | 01:06 Wow, look at that, that's milliseconds 18 | 01:09 versus nanoseconds. 19 | 01:11 So the generator is way faster. 20 | 01:14 And again, that's because it's not taking up 21 | 01:17 so much memory. 22 | 01:18 It's yielding the years one by one, 23 | 01:21 doing that lazily and saving you memory. 24 | 01:24 So that's why generator's faster. 25 | 01:27 And when you're working with large data sets, 26 | 01:29 you should definitely know about them. 27 | 01:32 And that's a wrap of day one of the list comprehension 28 | 01:35 generators lesson. 29 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/7.txt: -------------------------------------------------------------------------------- 1 | 00:01 Let's look at what we've learned so far. 2 | 00:03 List comprehensions. 3 | 00:05 For both ways of doing a loop and conditional, 4 | 00:09 we loop over list and store all the modifications 5 | 00:12 in a new list. 6 | 00:13 Five lines of code. 7 | 00:15 The more Pythonic ways to use a list comprehension. 8 | 00:19 One line of code. 9 | 00:20 And it reads like English. 10 | 00:22 We went through another sample cleaning up a word list, 11 | 00:25 and you can do multiple checks. 12 | 00:28 in the conditional part over list comprehension. 13 | 00:32 Secondly, generators. 14 | 00:35 The simplest generator would be something like this. 15 | 00:39 For in range, yield the value. 16 | 00:42 Generators, pause. 17 | 00:44 So, after every call it stops at the yield, 18 | 00:47 and comes back. 19 | 00:50 Use a generator to build up a sequence. 20 | 00:53 Here I made a bunch of options for a fictional website. 21 | 00:57 And instead of building up a list in the function, 22 | 01:01 we use the yield statement 23 | 01:02 to just generate a sequence of items. 24 | 01:06 And lastly, 25 | 01:07 we look at list and generators, 26 | 01:12 and we saw that when your data set grows 27 | 01:15 your really want to know about generators 28 | 01:17 because the items are lazily loaded, 29 | 01:20 not taking up the whole memory footprint. 30 | 01:23 And that's it for the basics. 31 | 01:26 And now it's your turn for day two and three 32 | 01:29 to get more practical exercise. 33 | -------------------------------------------------------------------------------- /transcripts/16-comprehensions/8.txt: -------------------------------------------------------------------------------- 1 | 00:01 Welcome back to 100 Days of Python. 2 | 00:03 The second day of list comprehensions and generators. 3 | 00:06 Now that we've got some theory down, 4 | 00:08 it's all about getting practice. 5 | 00:10 I've got some small exercises to get practice. 6 | 00:14 So, here you're provided with a names list 7 | 00:18 of names and surnames. 8 | 00:19 And can you write a simple list comprehension 9 | 00:22 to convert those names to title case, and reverse the 10 | 00:25 first and the last name? 11 | 00:27 Then we use that data to make a simple 12 | 00:30 generator that generates output like this. 13 | 00:35 So, we initialize the generator. 14 | 00:37 We look through a range of 10, 15 | 00:40 and call next on the generator. 16 | 00:42 And every time we call next 17 | 00:44 it returns name one teams up with name two. 18 | 00:47 And those names are randomly chosen 19 | 00:50 That should not be too hard 20 | 00:52 after yesterday's lesson. 21 | 00:54 So have fun, and tomorrow 22 | 00:55 we'll show you the solution to 23 | 00:56 these two exercises. 24 | -------------------------------------------------------------------------------- /transcripts/19-iterators/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day guys, this is Julian Sequeira, 2 | 00:02 and welcome to iteration with itertools. 3 | 00:06 This is going to be a three day series 4 | 00:08 just touching on the more common, 5 | 00:11 arguably more common, usages of itertools. 6 | 00:15 We'll start off with a bit of a coverage 7 | 00:17 of what iteration is, very basic stuff, 8 | 00:20 and then we'll get straight on into itertools. 9 | 00:23 So carry on, move on to the three day overview 10 | 00:26 for some more detail, 11 | 00:28 and then we'll get straight into the code. 12 | -------------------------------------------------------------------------------- /transcripts/22-decorators/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 days of Python. 2 | 00:02 Today we look at an important concept which are decorators. 3 | 00:05 It might be daunting at first, 4 | 00:07 but they're not that hard to grasp, 5 | 00:09 and they take your Python knowledge to the next level. 6 | 00:11 First we write a simple decorator 7 | 00:13 and see how we can decorate a function 8 | 00:16 to add additional behavior. 9 | 00:18 Then we make a quick detour 10 | 00:19 to explain the different ways functions 11 | 00:21 and Python can receive different kind of arguments. 12 | 00:24 Then we write a second decorator 13 | 00:26 and see how they can be stacked up. 14 | 00:28 Then we look at some further references, 15 | 00:30 and for the second and third day, 16 | 00:32 I got a couple of practical exercises 17 | 00:35 to hone your newly gained decorator skills. 18 | 00:38 All right, let's do this. 19 | -------------------------------------------------------------------------------- /transcripts/22-decorators/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's do a more realistic 2 | 00:02 and interesting example, let's write a timeit decorator. 3 | 00:14 And as we said before, we call the decorated function, 4 | 00:17 and we add some behavior before and after calling it. 5 | 00:29 Alright, we got that defined, so we 6 | 00:32 have a decorator called timeit. 7 | 00:34 It receives a function, it wraps the function, 8 | 00:37 and we will see in a bit why that is. 9 | 00:39 We pass it the args and the keyword args. 10 | 00:42 We start a timer, we call the function, 11 | 00:45 we end the timer, and then we print 12 | 00:47 how much time that function took. 13 | 00:49 We return the wrapper, and that's it. 14 | 00:52 Let's then define a function that 15 | 00:53 we can use this decorator on. 16 | 01:02 So that in itself is not decorated yet, 17 | 01:05 so let's define it again using the decorator. 18 | 01:12 And look at that, how cool is that? 19 | 01:14 So the decorator started the timer, 20 | 01:16 it ran the function, it measured the time, 21 | 01:20 and after the function was complete, 22 | 01:22 it reported back how long it took. 23 | 01:24 So it took two seconds which of course is not a surprise. 24 | 01:27 A final note about wraps, so what if 25 | 01:29 I wouldn't have done wraps function? 26 | 01:33 So let's take that temporarily out. 27 | 01:40 And let's inspect that function. 28 | 01:45 Hey, where is my doc string? 29 | 01:50 It disappeared. 30 | Not good, let's put it back. 31 | 01:55 Let's define the function again using the decorator. 32 | 02:00 And there you go, so that's why you should always use wraps 33 | 02:04 from the functools module, to preserve your doc strings. 34 | -------------------------------------------------------------------------------- /transcripts/22-decorators/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the second day of decorators. 2 | 00:03 Today, you get your hands dirty writing a decorator, 3 | 00:06 and I got an exercise here that you can do 4 | 00:10 on the PyBites Code Challenge Platform. 5 | 00:12 The goal is to make this work, basically. 6 | 00:15 So we have a gettext function 7 | 00:18 that takes a text, and you're going to decorate it 8 | 00:22 with a make_html that basically adds a tag. 9 | 00:26 So you can stack it to add various tags, 10 | 00:30 so when I call it like this, it should output 11 | 00:32 p strong, the text of the function, 12 | 00:35 and closing strong, and closing p. 13 | 00:38 And that's all there is for today. 14 | 00:40 If that's easy for you, you can already 15 | 00:42 try to look at Day 3. 16 | 00:44 Good luck. 17 | -------------------------------------------------------------------------------- /transcripts/25-errors/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Probably time that we talked about error handling. 2 | 00:02 I'm sure that you've encountered some issues 3 | 00:05 with your Python code and you may wonder 4 | 00:08 what is the right way to catch these errors in Python. 5 | 00:12 Well, that's what this next three day section is all about. 6 | 00:16 Have you encountered Python's errors? 7 | 00:18 Have you seen what's called a traceback here? 8 | 00:21 This is the report from trying to run the Python program 9 | 00:25 when something actually went wrong on line 21 of api.py. 10 | 00:30 Let me get a little info here, 11 | 00:31 there's a type error : and this 12 | 00:34 gives us a description of what that is. 13 | 00:35 The type thing on the left here, the type error 14 | 00:37 is an exception type and it tells us the category of error. 15 | 00:41 On the right is the actual message 16 | 00:43 of what went wrong within that category. 17 | 00:45 So None type, object is not iterable. 18 | 00:48 Turns out that in this case, the data return 19 | 00:51 from the server was empty and we tried to loop over it. 20 | 00:53 That doesn't work so well. 21 | 00:55 So we're going to see how to deal with a variety of errors 22 | 00:58 the proper way in Python. 23 | -------------------------------------------------------------------------------- /transcripts/25-errors/7.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 2, your goal is to discover all the 2 | 00:02 error conditions that you might need to catch, 3 | 00:05 and actually determine the exception type that 4 | 00:08 that results in, in Python. 5 | 00:10 Are you working with something that talks to a database? 6 | 00:12 What kind of errors could you get from the database? 7 | 00:15 Are you talking to something that goes across the network? 8 | 00:18 What type of errors come across, from say, the 9 | 00:20 network being down or DNS not working, 10 | 00:22 or the network being on, 11 | 00:24 but not being able to reach the host, 12 | 00:26 all those sorts of things. 13 | 00:28 So come up with that list, 14 | 00:29 and figure out what type, 15 | 00:31 what actual exception type in Python does it surface as. 16 | 00:35 All right, if it's a connection error it could be 17 | 00:37 something built into the standard library, 18 | 00:38 or it could be something in say, requests, 19 | 00:41 as we saw in our example. 20 | 00:42 So, you're going to have know exactly what those types are 21 | 00:44 so that you can actually write the 22 | 00:46 probably error handling code. 23 | 00:47 That's it for today, 24 | 00:49 it might be a little bit tricky to get your app 25 | 00:51 into all the different situations that it's going 26 | 00:53 to encounter, all right? 27 | 00:55 Some of these errors are hard to trigger, 28 | 00:56 but do your best to figure out all the various 29 | 00:58 error cases you're going to run into. 30 | -------------------------------------------------------------------------------- /transcripts/25-errors/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 3, it's time to take those 2 | 00:02 errors that you've discovered 3 | 00:03 and put in specific error handling for each one of them. 4 | 00:07 So here I've written out a little try-except block 5 | 00:10 that shows the standard error handling 6 | 00:12 in Python, you can use this as a template, 7 | 00:14 take the various types of errors you found on Day 2, 8 | 00:17 figure out how you might either deal with them or at least 9 | 00:19 let the user know, keep your application running. 10 | 00:23 Add the error handling to your code, 11 | 00:25 make sure that it actually does handle the errors, 12 | 00:27 you know, get the thing to fail in whatever ways 13 | 00:30 you were doing before to find the errors, 14 | 00:31 but now you should have some kind of nice response 15 | 00:35 that's not a full-on crash, 16 | 00:36 maybe it even keeps running 17 | 00:37 and just asks the question again, something like that. 18 | 00:40 Now that you know how to do error handling, 19 | 00:42 you have some practice with it, 20 | 00:43 when you're writing your applications, 21 | 00:45 be sure to think of the errors that can happen, 22 | 00:47 put the error handling in place, and fail gracefully. 23 | -------------------------------------------------------------------------------- /transcripts/28-regex/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to 100 Days of Python. 2 | 00:02 In the coming three days I will be your guide 3 | 00:04 explaining regular expressions in Python. 4 | 00:07 First we will look at when not to use them 5 | 00:09 when we can use simple string methods. 6 | 00:12 Then we will dive into search and match, 7 | 00:15 capturing strings. 8 | 00:17 Final, compiling your regexes, 9 | 00:21 and advanced string replacements. 10 | 00:23 Day 2 I will give you some more material 11 | 00:26 to read and practice online, 12 | 00:29 and the third day I have some really good exercises 13 | 00:32 to get your hands dirty with regular expressions. 14 | -------------------------------------------------------------------------------- /transcripts/28-regex/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now those string operations were pretty basic, 2 | 00:03 but usually we need something more advanced. 3 | 00:06 Meet, regex. 4 | 00:07 The re module has two main methods. 5 | 00:11 search and match. 6 | 00:14 match, matches from start to end. 7 | 00:17 Search can match a substring. 8 | 00:19 It's best to use an example. 9 | 00:23 I'm using raw strings by the way, 10 | 00:25 because then I can just use special characters 11 | 00:27 with a single backslash and not having to escape them 12 | 00:31 which makes my regexes more readable. 13 | 00:34 So again, we have the same awesome I'm doing a 100 days 14 | 00:37 of code challenge and let's... 15 | 00:41 do a re.search first. 16 | 00:43 So I'm going to... 17 | 00:46 match a... 18 | 00:48 part of that string 19 | 00:50 and you can do this as well with just I am in 20 | 00:53 but the point is to just show how you would make a regular 21 | 00:57 expression and what a match object would look like. 22 | 01:02 To contrast that with match, 23 | 01:07 this won't work. 24 | 01:09 Oops. 25 | 01:10 Match takes two arguments. 26 | 01:13 So this is None because match ends end to end 27 | 01:17 so I am is not the full string. 28 | 01:21 So to do a proper match we would be doing, 29 | 01:27 start with awesome, 30 | 01:30 end with challenge. 31 | 01:33 On text and that works. 32 | 01:37 And here you see the first part of a pattern 33 | 01:40 which is '.' which matches any character, 34 | 01:44 zero or more of them 35 | 01:47 up until challenge. 36 | -------------------------------------------------------------------------------- /transcripts/31-logging/10.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 2 you're goal will be to take the application 2 | 00:03 you chose yesterday and look at the flow, 3 | 00:07 and think about what type of things 4 | 00:11 do you want to keep track of. 5 | 00:12 Do you want to track errors? 6 | 00:14 Would you want to track timing? 7 | 00:15 Do you want to track inputs, outputs? 8 | 00:17 All that kind of stuff. 9 | 00:19 So think about what you're going to try to log 10 | 00:21 and how you're going to do it. 11 | 00:22 Do you want this to go to a file system, 12 | 00:24 do you want it to go to the console, 13 | 00:26 all those considerations. 14 | 00:27 So just kind of plan out what you're going to do the next day. 15 | -------------------------------------------------------------------------------- /transcripts/31-logging/9.txt: -------------------------------------------------------------------------------- 1 | 00:00 All right, it's your turn to do some logging. 2 | 00:02 Let's look at all the steps that I'm recommending for you. 3 | 00:06 So there's a little summary of why you care about logging, 4 | 00:09 but we're going to focus on the three things, 5 | 00:12 the three days, and what you're going to do on them. 6 | 00:13 Today, you're basically done. 7 | 00:15 It's watch the videos as usual. 8 | 00:18 What you're going to do is you're going to pick an application 9 | 00:20 that either you've built in this course or previously built 10 | 00:23 that you think could use some logging. 11 | 00:25 It would be nicer if it had some logging 12 | 00:27 much like we just added to the movie search app. 13 | 00:29 So your goal for today is just to pick an app 14 | 00:32 that you're going to study and add logging to 15 | 00:34 over today and the next two days that follow. 16 | -------------------------------------------------------------------------------- /transcripts/34-refactoring/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 Days of Python. 2 | 00:02 In the coming 3 days I will guide you 3 | 00:04 through refractoring and writing Phythonic code. 4 | 00:08 One thing is to write Python, the other thing 5 | 00:10 is to really leverage all the great stuff Python has. 6 | 00:14 The Zen of Python states there should be one 7 | 00:17 and preferably one way to do something, 8 | 00:20 and that's great because in Python there usually is one best 9 | 00:24 way to something, and the more you know these constructs 10 | 00:27 and idioms, the more readable and elegant 11 | 00:30 your code will become. 12 | 00:31 For this lesson I've prepared a Jupyter notebook 13 | 00:34 with 10 practical examples how you can improve your code. 14 | 00:38 For example use a with statement 15 | 00:40 instead of a try, accept, finally block. 16 | 00:43 Or use enumerate to not keep a manual counter 17 | 00:47 or what about refractoring a long if, 18 | 00:50 elif else statement using a dictionary. 19 | 00:53 We will touch upon list comprehensions, 20 | 00:56 generators, using explicit is better than implicit 21 | 00:59 in your exceptions, string formatting, tuple unpacking, 22 | 01:03 PEP 8, the Zen of Python, and even some common 23 | 01:06 best practices writing maintainable code. 24 | 01:09 And for day two and three I have you refractor 25 | 01:12 your code or the code of somebody else 26 | 01:14 to really put into practice what you've learned. 27 | 01:17 So there's a lot to cover, I'm really excited. 28 | 01:19 Let's dive straight in. 29 | -------------------------------------------------------------------------------- /transcripts/34-refactoring/14.txt: -------------------------------------------------------------------------------- 1 | 00:01 Welcome back. 2 | 00:02 In this second and third day, 3 | 00:04 I encourage you to take our Code Challenge 30. 4 | 00:07 It's The Art of Refactoring: Improve Your Code. 5 | 00:11 And, the task of today and tomorrow is 6 | 00:13 to get some of your code, run tests 7 | 00:16 and do some refactorings, making it more Pythonic. 8 | 00:20 Also, I would recommend to start looking at Flake8, 9 | 00:23 or Pylint. 10 | 00:24 I personally use Flake8. 11 | 00:27 And integrate that into your editor. 12 | 00:29 And have a check upon each save. 13 | 00:31 Or, what I did, for example, in the vimrc, 14 | 00:34 I have a shortcut: , f. 15 | 00:36 And when I press that, 16 | 00:38 it runs Flake8 and it opens a new editor window 17 | 00:41 where it highlights my PEP8 violations. 18 | 00:44 So that way I keep my files clean during development. 19 | 00:47 Optionally, you can look at Code Challenge 35 20 | 00:52 and use Better Code Hub 21 | 00:54 to look at your code quality overall. 22 | 00:59 Using how we use the tool 23 | 01:02 to improve a couple of our projects. 24 | 01:16 And don't forget to tweet out your progress. 25 | 01:19 You can mention Talk Python and PyBites in your tweets, 26 | 01:22 and we would love to see what refactorings you come up with, 27 | 01:25 or what your favorite Pythonic concept is 28 | 01:27 you learned from this lesson. 29 | 01:29 Alright, good luck and have fun. 30 | -------------------------------------------------------------------------------- /transcripts/34-refactoring/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Next up, counting inside a loop. 2 | 00:03 So sometimes you want to keep track of an index 3 | 00:06 when you loop over a sequence, 4 | 00:07 and when you come from C or another language 5 | 00:11 you would typically do something like this. 6 | 00:14 Let's define a list of days 7 | 00:16 and let's loop through them showing the day 8 | 00:19 prepended by the number. 9 | 00:26 Alright, so that's straightforward. 10 | 00:30 Now, and this is correct, right? 11 | 00:31 I mean you can do it like this, 12 | 00:33 it's all 100% correct. 13 | 00:35 But the more idiomatic or Pythonic way 14 | 00:38 is to use enumerate. 15 | 00:40 And a way to do it is to wrap your sequence in enumerate, 16 | 00:46 which returns the index and the item 17 | 00:48 in the sequence on every loop. 18 | 00:49 So I can just, 19 | 00:52 now, 20 | 00:53 print those, 21 | 00:57 and it should give me, oops, 22 | 00:58 obviously, I should not hard code days. 23 | 01:02 So I'm using f-strings by the way because I'm on 24 | 01:05 Python 3.6. 25 | 01:06 And yes, this gives me the same result, 26 | 01:08 and there's even a nice little trick with enumerate, 27 | 01:12 which is, you can give it a starting point. 28 | 01:14 So I can just copy this, 29 | 01:17 and again give enumerate a second argument of 1. 30 | 01:20 So I want to start the counter at 1, 31 | 01:23 and then I don't have to do this menu 32 | 01:25 plus 1 inside the loop. 33 | 01:26 And that gives me the same result. 34 | -------------------------------------------------------------------------------- /transcripts/34-refactoring/9.txt: -------------------------------------------------------------------------------- 1 | 00:00 Number 8. 2 | 00:01 PEP 8 and the Zen of Python. 3 | 00:03 Any Python developer should become familiar 4 | 00:06 with PEP 8 and use it in their code. 5 | 00:09 So here's the Style Guide for Python 6 | 00:11 and you really should read this end-to-end 7 | 00:14 and make a habit of formatting your code 8 | 00:16 in the proper way, using variable names with underscore, 9 | 00:19 so all these conventions. 10 | 00:20 There's even a recent initiative, pep8.org, 11 | 00:24 which should make this even easier to digest. 12 | 00:26 And it's really nicely formatted 13 | 00:28 and gives you some more context. 14 | 00:31 And, of course, if you do import this from your Python REPL, 15 | 00:35 you get the Zen of Python. 16 | 00:36 And the more you write Python, 17 | 00:38 the more you see how this applies 18 | 00:40 to the language and it's design. 19 | 00:42 It's really where you start to better understand 20 | 00:45 and appreciate the language. 21 | -------------------------------------------------------------------------------- /transcripts/37-csv_data/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Hello, it's Michael Kennedy, 2 | 00:01 and I'm going to be your guide for day 37, 38, and 39. 3 | 00:06 And this time we're going to work with structured data 4 | 00:10 called CSV files. 5 | 00:12 So anything that can be stored in something like Excel 6 | 00:15 or Tabular, data like that that you might work with 7 | 00:19 in some kind of Excel spreadsheet. 8 | 00:21 Much of the data you'll find out 9 | 00:23 on the internet lives in this form, 10 | 00:25 and we're going to find some really, 11 | 00:27 really interesting data sets, 12 | 00:28 and we're going to build some programs to ask 13 | 00:30 and answer some pretty powerful questions. 14 | 00:34 Let's get started. 15 | -------------------------------------------------------------------------------- /transcripts/37-csv_data/11.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 2 or Day 38, if you're adding them, 2 | 00:03 is to actually create the skeleton of that program 3 | 00:07 and just open a CSV reader to that file. 4 | 00:11 If you can just load it up and just print out the rows, 5 | 00:14 you're done with day 2. 6 | -------------------------------------------------------------------------------- /transcripts/37-csv_data/12.txt: -------------------------------------------------------------------------------- 1 | 00:00 And on Day 3 you're going to want to 2 | 00:02 actually work with the data. 3 | 00:04 So you need to transform it into 4 | 00:05 a way that you can work with. 5 | 00:06 If you need to work with that particular field, 6 | 00:09 I think my Thanksgiving example might not actually need it 7 | 00:12 because of the way that that works. 8 | 00:14 Depending on your data you might have to, you know, 9 | 00:16 sort of upgrade it to the numbers or numbers 10 | 00:19 and then, you know, ask the user questions 11 | 00:21 and try to basically provide an answer based on the data. 12 | 00:25 When you're done, share what you learned 13 | 00:27 as always, and thanks, hopefully you enjoyed this section. 14 | -------------------------------------------------------------------------------- /transcripts/37-csv_data/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 For the learning section of today, 2 | 00:01 what we're going to do is we're going to write an app 3 | 00:03 that takes a CSV file, and answers a 4 | 00:05 set of questions around it. 5 | 00:08 The data that we're going to use is 6 | 00:10 from the 538 data set, data/us-weather-history. 7 | 00:16 It's not very clear what this means, 8 | 00:17 but this is the weather history from different cities. 9 | 00:20 You can even actually see here's the 10 | 00:22 the data that they, 11 | 00:24 the code that they used to visualize it. 12 | 00:26 Here's the web scraping, they go to Wunderground 13 | 00:29 which is the weather site to get the data, pretty awesome. 14 | 00:32 So we're going to use this data set, 15 | 00:33 this is the Seattle weather data 16 | 00:36 for 2014 and 2015, I believe. 17 | 00:39 Yeah, there's the dates right there. 18 | 00:41 This should look familiar, right? 19 | 00:42 Date, actual mean, actual man, actual temp and so on. 20 | 00:45 So we're going to take this data and 21 | 00:47 we're going to work with it. 22 | 00:48 Now, let's make sure we start with the raw, 23 | 00:51 we do not want GitHub html, you want the raw. 24 | 00:54 So we're going to save this. 25 | 00:55 And I'll just save this as seattle.csv. 26 | 00:59 Now let's go write some code to work with this data file. 27 | -------------------------------------------------------------------------------- /transcripts/40-json/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Hi everyone and welcome to JSON in Python. 2 | 00:04 This is Julian Sequeira and I'm going to be walking you 3 | 00:06 through some of the more interesting ways 4 | 00:09 of dealing with detailed JSON output. 5 | 00:13 So JSON, if you're not familiar with it, 6 | 00:15 stands for JavaScript Object Notation 7 | 00:18 and it's pretty much just a way 8 | 00:20 of formatting data, okay. 9 | 00:22 One of the most common ways of seeing JSON 10 | 00:25 when you're working with Python 11 | 00:27 is through contacting APIs. 12 | 00:30 Through working with numerous APIs out 13 | 00:33 through the web. 14 | 00:34 And one of the things about that 15 | 00:37 is that you actually get 16 | 00:38 really complex dictionary nested situations going on. 17 | 00:43 So the JSON output, 18 | 00:44 if you haven't seen it before, 19 | 00:45 just looks like a little dictionaries and lists 20 | 00:48 and if you get 21 | 00:49 really deeply nested lists and dictionaries, 22 | 00:53 it gets really complicated 23 | 00:55 to try and pull out that data, 24 | 00:57 which is why JSON can sort of screw with you, pretty much. 25 | 01:00 So, what we're going to do 26 | 01:01 is we're going to go through that 27 | 01:02 in the next couple of days, 28 | 01:04 have some fun with it and see what other cool APIs 29 | 01:08 you can talk to by the end of it. 30 | 01:10 So, let's move on. 31 | -------------------------------------------------------------------------------- /transcripts/43-search-api/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Hello, this is Michael Kennedy 2 | 00:01 and I will be your guide for Day 10, 11 and 12. 3 | 00:05 And during these three days you're 4 | 00:06 going to work with JSON APIs and 5 | 00:09 in particular with a couple of search-based APIs. 6 | 00:12 But of course, what you'll learn here 7 | 00:13 you'll be able to apply to pretty much any JSON API. 8 | 00:18 APIs are really important. 9 | 00:20 These are the way that you reach out and 10 | 00:21 you add superpowers to your code, to your application. 11 | 00:25 You might write an application that has 12 | 00:27 some data in the database, 13 | 00:28 it's got some information that users have input, 14 | 00:31 but maybe you want to add weather information, 15 | 00:34 or integrate with Github or talk to Twitter. 16 | 00:36 All of these use APIs. 17 | 00:38 And so we're going to look at 18 | 00:39 the foundation of APIs in this challenge, 19 | 00:42 which is basically HTTP and JSON. 20 | 00:45 And we're going to do that from Python, of course. 21 | 00:47 So we're going to work with two services. 22 | 00:50 One service I'm going to demonstrate 23 | 00:52 how we write code against it, 24 | 00:54 and then I'll give you another service 25 | 00:55 for your code challenge that you can play with, 26 | 00:58 and if you don't like either of those services 27 | 00:59 for your code challenge, feel free to 28 | 01:01 just go find another one. 29 | 01:02 You'll probably have enough information 30 | 01:04 to do something pretty interesting 31 | 01:06 after this series of videos. 32 | 01:08 So let's go look at this movie db search service. 33 | -------------------------------------------------------------------------------- /transcripts/43-search-api/10.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now you've seen me build an application 2 | 00:02 using requests to consume a JSON API. 3 | 00:05 It's your turn to consume a different API. 4 | 00:10 So drop over here in GitHub, 5 | 00:12 and we're going to go through the various things 6 | 00:16 and the read me here for what you do 7 | 00:17 for this particular day. 8 | 00:19 We're going to start out by basically just making the skeleton, 9 | 00:23 create a virtual environment, 10 | 00:24 create a program .py and an api.py, 11 | 00:27 and just make sure that you can import one 12 | 00:29 from the other, and we're going to install Postman. 13 | 00:33 So make sure you install the Postman application. 14 | 00:35 Most of what today was 15 | 00:37 was just watching the corresponding videos. 16 | 00:40 So get everything setup and get ready 17 | 00:42 for the next day. 18 | -------------------------------------------------------------------------------- /transcripts/43-search-api/12.txt: -------------------------------------------------------------------------------- 1 | 00:00 The last day is adding polish. 2 | 00:02 We're going to use a namedtuple. 3 | 00:04 Now here's an example from our movie one. 4 | 00:06 You want to create a corresponding one 5 | 00:08 for a search result. 6 | 00:10 The other thing we're going to do, 7 | 00:11 this is really, really simple and slick, 8 | 00:13 is, if we look over here 9 | 00:14 you'll see that there is a URL 10 | 00:16 that you can get to for every result. 11 | 00:19 What you're going to do is you're going to write 12 | 00:20 a little bit of code that asks the user 13 | 00:24 which one of these would you like to view 14 | 00:25 in your web browser. 15 | 00:27 Maybe give 'em a number, 16 | 00:28 and they can put 3, and so then you're goal 17 | 00:30 is to write a little bit of code 18 | 00:31 that will open the web browser 19 | 00:33 and a new window at that URL, 20 | 00:35 and literally those two lines of code 21 | 00:37 is all it takes across platform. 22 | -------------------------------------------------------------------------------- /transcripts/43-search-api/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 We've seen how to poke at our API 2 | 00:02 with just doing a GET request. 3 | 00:03 We've seen Postman lets us explore better 4 | 00:06 but if we want to access it from code, we need another way. 5 | 00:09 Now, Python has a built in mechanism 6 | 00:12 for accessing HTTP APIs 7 | 00:14 but it's not the prettiest thing in the world. 8 | 00:16 So a guy named Kenneth Reitz created 9 | 00:19 this thing called Requests. 10 | 00:20 Maybe you've heard of it. 11 | 00:21 It's definitely one of the most popular packages, period. 12 | 00:25 And to use it is really, really simple. 13 | 00:27 We're going to use it in just a moment. 14 | 00:28 If you want to get a URL, you just say GET. 15 | 00:30 Here you can even pass the auth, 16 | 00:31 check the status code, check the encoding, check the text, 17 | 00:34 and even convert the JSON back to Python dictionaries. 18 | 00:37 So this is a very popular library. 19 | 00:39 It's definitely the most-used for accessing HTTP services 20 | 00:43 or Python directly. 21 | 00:44 So, unless for some reason, you are very adverse 22 | 00:46 to having a dependency on an external package, 23 | 00:48 this is the way, 24 | 00:49 this is the way we're going to do it in Python. 25 | 00:51 So, next up, let's get started 26 | 00:53 and actually write some code. 27 | -------------------------------------------------------------------------------- /transcripts/46-beautifulsoup4/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Okay, everyone welcome back. 2 | 00:02 This is web scraping with BeautifulSoup 4. 3 | 00:05 I'm Julian Sequeira, again, 4 | 00:07 and just a disclaimer, this has nothing to do with dinner. 5 | 00:11 This has everything to do with web scraping. 6 | 00:14 If you're hungry, go get something to eat. 7 | 00:16 If not, crack on, because what we're going to do now 8 | 00:19 is this is going to be a very quick module. 9 | 00:21 We're going to run through 10 | 00:23 pulling down a webpage with requests, 11 | 00:25 not in any detail because we've done that before. 12 | 00:28 Then we're going to parse that webpage information 13 | 00:32 with BeautifulSoup 4. 14 | 00:33 You can do some really cool stuff, 15 | 00:35 so I'm very excited to show you this one. 16 | 00:37 Just set up your environment and the next video, 17 | 00:40 and then we'll get straight to some code. 18 | -------------------------------------------------------------------------------- /transcripts/46-beautifulsoup4/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 Okay, we just have a little bit of setup 2 | 00:02 to do for this one. 3 | 00:03 First things first, as always, 4 | 00:05 let's create our virtual environment. 5 | 00:09 Same thing, venv. 6 | 00:12 Once that's installed, we need to install 7 | 00:14 Beautiful Soup 4, of course, 8 | 00:16 but we also need to pip install requests. 9 | 00:19 So let's do that quickly. 10 | 00:21 We'll just activate, 11 | 00:24 the virtual environment here. 12 | 00:27 Okay, now we can do pip install requests, 13 | 00:32 and once that's done, we can then do 14 | 00:35 pip install bs4 15 | 00:39 You can probably type in beautifulsoup4, 16 | 00:41 but bs4 is fine, and that's it. 17 | 00:45 We have that installed. 18 | 00:46 The last thing I'd like you to do is just create 19 | 00:50 a file called scraper.py, 20 | 00:53 and throw that into your project directory. 21 | 00:56 When you run it, it will look something like this, 22 | 00:58 scraper.py, just here. 23 | 01:01 Okay, and that's it. 24 | 01:02 So once you've got all that set up, 25 | 01:04 launch your file and let's move on to do some coding. 26 | -------------------------------------------------------------------------------- /transcripts/49-measuring-perf/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 As you advance further in your Python projects, 2 | 00:03 you're inevitably going to hit a point 3 | 00:05 where you write some code and it's just slower 4 | 00:08 than you want it to be. 5 | 00:09 This happens all the time, 6 | 00:11 when you're doing scientific computation, 7 | 00:13 you're calling services, 8 | 00:14 maybe you're talking to a database. 9 | 00:16 It really happens a lot on the web 'cause, 10 | 00:18 for popular websites, performance is critical. 11 | 00:21 We're going to spend the next couple of days focusing 12 | 00:24 on how to get Python to tell us exactly 13 | 00:29 where it's spending its time. 14 | 00:31 Making things faster, that's a different problem. 15 | 00:33 How do we optimize our code, use the right data structures, 16 | 00:36 and so on? That's what you might do after this, 17 | 00:39 but this will tell you where things are slow, 18 | 00:41 where you need to focus your effort. 19 | 00:43 This whole concept is called profiling 20 | 00:45 and you'll see a lot of it is built right into Python. 21 | 00:47 And there's some great external tools, as well. 22 | -------------------------------------------------------------------------------- /transcripts/49-measuring-perf/11.txt: -------------------------------------------------------------------------------- 1 | 00:00 You've seen how profiling 2 | 00:01 can make your application faster. 3 | 00:04 It turns you into a detective, 4 | 00:06 hunting for performance problems in your application. 5 | 00:08 Now, it's your turn to work on your applications 6 | 00:12 using the cProfile and the techniques 7 | 00:14 that you've learned here. 8 | 00:15 We're going to start on Day 1 9 | 00:17 by just watching these videos, of course, 10 | 00:20 and then picking an application 11 | 00:22 that you're going to optimize. 12 | 00:23 Pick some app that you've previously built. 13 | 00:25 At this point in the course 14 | 00:26 you should have built many little applications. 15 | 00:28 You can totally pick one of those. 16 | 00:29 Or if you've built something outside the course, use that. 17 | 00:32 That's all fine, as long as it's the Python app, 18 | 00:34 this should work just fine. 19 | 00:36 So for today just think about the app 20 | 00:38 that you want to work with, 21 | 00:39 that you want to try to profile 22 | 00:40 and understand the performance, 23 | 00:42 and we're going to work on the next two days 24 | 00:43 on making it faster. 25 | -------------------------------------------------------------------------------- /transcripts/49-measuring-perf/12.txt: -------------------------------------------------------------------------------- 1 | 00:00 Second day, you've already chosen your application. 2 | 00:03 So what we're going to do is we're going to use c profile 3 | 00:05 or if you're using PyCharm Pro, you can use 4 | 00:08 the visual profiling tools there, as well. 5 | 00:10 Understand your applications performance. 6 | 00:12 So run the cProfile module against your app. 7 | 00:16 You can either use the api for very fine-grained stuff 8 | 00:19 or just run it against your entire application 9 | 00:21 like we saw in the command line. 10 | 00:23 Sort probably by cumulative time, cumtime. 11 | 00:27 That'll make it much easier to understand 12 | 00:29 actually where it's slow. 13 | 00:30 So you're job for today is to use cProfile 14 | 00:33 to find the five slowest methods in your application. 15 | 00:37 Write them down, make a little chart, 16 | 00:39 put them in a text file, something like that. 17 | 00:40 And be sure to include the millisecond times 18 | 00:43 that were recorded. 19 | 00:45 That way when you try to improve it on the next day 20 | 00:47 you could actually see if that's an improvement 21 | 00:50 or maybe even makes it worse. 22 | 00:51 So just go through, do a little bit of detective work 23 | 00:54 and find the five slowest methods that you control, 24 | 00:56 that you might be able to change. 25 | -------------------------------------------------------------------------------- /transcripts/49-measuring-perf/13.txt: -------------------------------------------------------------------------------- 1 | 00:00 Third day, it's time to improve 2 | 00:02 the performance of your application. 3 | 00:03 You've chosen it. 4 | 00:04 You've gone through and found out where it's slow. 5 | 00:06 So what you're going to do is focus one by one 6 | 00:08 on the five slow functions and try to make it faster. 7 | 00:12 Look at it, try to understand where it's slow, 8 | 00:14 and if you can change something 9 | 00:16 about the way that it works, right, 10 | 00:18 in our example we said, well, 11 | 00:19 we're parsing the CSV and we're actually converting 12 | 00:21 12 columns of data and actually we're only using four. 13 | 00:24 Let's just throw away the other eight columns 14 | 00:26 because we're never using them, 15 | 00:28 and that conversion is entirely wasteful. 16 | 00:31 We'll look for things like that. 17 | 00:32 Go through each one of the five functions, 18 | 00:34 change 'em one at a time, 19 | 00:36 rerun the profiler compared against 20 | 00:38 your times from the previous day, 21 | 00:40 and if it gets better, keep that change. 22 | 00:43 If it actually gets slower, forget it. 23 | 00:44 Just leave it alone or try something different. 24 | 00:46 All right, that's it. 25 | 00:47 So now you should have an app that's faster. 26 | 00:49 Hopefully, much faster than it was before 27 | 00:52 and you now have this new skill 28 | 00:54 with profiling to understand 29 | 00:55 the performance of Python applications. 30 | -------------------------------------------------------------------------------- /transcripts/49-measuring-perf/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now something that will probably 2 | 00:01 catch you off guard at some point 3 | 00:03 is that your intuition is actually really bad 4 | 00:07 for guessing where program is slow 5 | 00:09 and where it spends its time. 6 | 00:11 This has happened to me many, many times 7 | 00:13 and I've been doing programming for a long while. 8 | 00:17 Sometimes you get it right, but often you don't. 9 | 00:19 So the first thing that you need to do 10 | 00:21 before you try to improve 11 | 00:22 the performance of your application, 12 | 00:24 is measure, measure, measure, and that's profiling. 13 | 00:28 So what we're going to do is we're going to run 14 | 00:29 a built in command that's built in to Python itself 15 | 00:33 to measure where our code is working. 16 | 00:35 And we're going to do this in two particular ways. 17 | 00:38 We're also going to have some nice output. 18 | 00:40 Now in the beginning the output that we're going to work with 19 | 00:43 is actually going to be just sort of a 20 | 00:45 text table type thing in the terminal 21 | 00:48 or just in the program output. 22 | 00:50 And at the end, I'll show you actually how to get 23 | 00:52 PyCharm to draw these little graphs 24 | 00:55 where it shows you we start up program and call main, 25 | 00:58 main calls go, and then go is calling these 3 functions 26 | 01:01 and even the color tells you where you're spending the time. 27 | 01:03 Like, the red is worse than the yellow 28 | 01:05 which is worse than the green, and so on. 29 | 01:07 So we're going to be able to get this 30 | 01:08 kind of output and understanding from our program. 31 | -------------------------------------------------------------------------------- /transcripts/52-feedparser/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day everyone, I'm Julian Sequeira. 2 | 00:02 Welcome back and this time we're going to look at Feedparser. 3 | 00:06 This is a library that is really cool 4 | 00:08 and I absolutely love it. 5 | 00:10 I use it in a few scripts 6 | 00:12 and it's actually designed to parse RSS feeds. 7 | 00:15 Go figure. 8 | 00:16 It's really, really fun to use, 9 | 00:18 very simple, very satisfying. 10 | 00:20 So let's move on to the first video 11 | 00:22 and what we're going to do 12 | 00:24 is first we're going to pull down an XML file 13 | 00:26 in our RSS feed. 14 | 00:27 And in the next video after that, 15 | 00:29 we're then going to parse it. 16 | 00:31 Really simple and quick. 17 | 00:33 Let's get to it! 18 | -------------------------------------------------------------------------------- /transcripts/52-feedparser/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 Okay, very quick setup for this project, 2 | 00:02 we're going to create the feedparser folder, 3 | 00:04 just like I have, and we're going to install our 4 | 00:08 virtual environment, very good practice as always. 5 | 00:12 Once it's up and running, we can launch it, venv\scripts\activate, 6 | 00:18 it because I'm a Windows junkie, 7 | 00:21 alright, now we can install feedparser, 8 | 00:27 alright, that might take a minute or two 9 | 00:29 to install, depending on your speed, and everything. 10 | 00:33 Once that's done, we will try and install requests, 11 | 00:37 and that's pretty much all we need for this project. 12 | 00:40 After that, we're going, we're actually going to use requests 13 | 00:43 to pull down the XML file, 14 | 00:45 and then use feedparser to parse the XML feed, 15 | 00:49 so install requests. 16 | 00:53 Alright, off it goes, 17 | 00:55 and we are done, now folder-wise, 18 | 00:58 inside your directory, I would like you to create 19 | 01:03 two Python files, one called parser.py, 20 | 01:07 and one called pull_xml.py. 21 | 01:10 Okay, just do that, empty files, 22 | 01:13 and we will continue in the next video. 23 | -------------------------------------------------------------------------------- /transcripts/55-uplink/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Recall way back 2 | 00:01 when we worked on the search API, 3 | 00:03 consuming the search API, 4 | 00:05 and we were using requests to interact with HTTP services. 5 | 00:10 That worked pretty well, 6 | 00:12 but it turns out if you're working with complex APIs, 7 | 00:16 and they're very structured, 8 | 00:18 they want you to do things like pass certain headers, 9 | 00:21 some things go into query parameters, 10 | 00:23 others go into a JSON body, 11 | 00:25 and it's this sort of rich, known, fixed API, 12 | 00:29 you may well be better off using this thing called Uplink. 13 | 00:32 And that's what we're going to focus on now. 14 | 00:35 Instead of consuming HTTP services in an ad hoc fashion, 15 | 00:39 we're going to use the Uplink library to create 16 | 00:40 very structured and predictable APIs. 17 | 00:43 So once you implement it, 18 | 00:44 you kind of forget that it's there, 19 | 00:46 and you just treat it like another part of Python. 20 | 00:49 So, Uplink is a really great API for building 21 | 00:53 what here they describe as declarative http clients. 22 | 00:57 So instead of implementing all the details, 23 | 00:59 you just say, 24 | 01:00 "I want to do a get request against this URL 25 | 01:03 with these variables and parameters, 26 | 01:05 and Uplink, make that happen. 27 | 01:07 Make this all work for us." 28 | -------------------------------------------------------------------------------- /transcripts/55-uplink/12.txt: -------------------------------------------------------------------------------- 1 | 00:00 You've seen how fun it is 2 | 00:01 to build API clients with uplink. 3 | 00:04 Now it's your turn, 4 | 00:05 and we're going to have you build an API client against 5 | 00:08 an API which has several endpoints. 6 | 00:10 You've seen this service before, 7 | 00:11 over at movie_service.talkpython.fm, 8 | 00:14 and it has these three endpoints. 9 | 00:16 Recall we did this in one of our service demos previously 10 | 00:19 but we're going to take an entirely different approach 11 | 00:21 and you're going to write that from scratch. 12 | 00:23 So over here, 13 | 00:24 we've seen that we can go /api/search/something, 14 | 00:29 here we're searching for all movies that have Run 15 | 00:32 as a substring on keywords, 16 | 00:34 or we can find them by director. 17 | 00:36 Here's all of the movies written by, 18 | 00:38 or directed by James Cameron. Things like that. 19 | 00:40 So we're going to take this 20 | 00:42 and let you model it with uplink. 21 | 00:45 So the first day, 22 | 00:46 really is just mostly watching the videos 23 | 00:49 and if you've gotten this far, you're pretty much there. 24 | 00:51 So you're mostly done. 25 | 00:52 Go ahead and just create a shell project, 26 | 00:56 an empty project that has a virtual environment, 27 | 00:59 it has uplink installed, 28 | 01:01 and program.py and an api.py. 29 | 01:05 And then just you know import uplink inside the api.py, 30 | 01:07 import api inside program.py, run program. 31 | 01:09 Make sure it's all hanging together, right? 32 | 01:11 So you'll be ready to start for the next day. 33 | -------------------------------------------------------------------------------- /transcripts/55-uplink/13.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now, for Day 2, you're going to 2 | 00:01 work with this movie service. 3 | 00:03 Now, I just copied these over for you. 4 | 00:06 Here are the three API endpoints. 5 | 00:08 So, /api/search/{keyword}, 6 | 00:11 /api/director/{directorname}, 7 | 00:14 things like that. 8 | 00:15 So, I've kind of laid out the goals of what I 9 | 00:18 would like you to do on this particular day. 10 | 00:21 On the second day, what I want is for you to 11 | 00:23 more or less create the movie search client class. 12 | 00:26 This is the uplink client. 13 | 00:27 Don't have to test it, you don't have to use it, 14 | 00:29 but you're going to need to add three methods to it, 15 | 00:32 one for each endpoint. 16 | 00:33 All right, and there's a few other steps about 17 | 00:35 like setting the base URL, and things like this. 18 | 00:38 And here's just a reminder of how this generally looks. 19 | 00:41 This is not what you do for this one but, 20 | 00:42 you'll have a class, interactional consumer, 21 | 00:44 you have a method, 22 | 00:46 it derives from uplink.get, and you can pass parameters. 23 | 00:50 So, shouldn't be a huge effort for you, I hope. 24 | 00:53 But, fill this out to match these three end 25 | 00:55 points as you see fit. 26 | -------------------------------------------------------------------------------- /transcripts/55-uplink/14.txt: -------------------------------------------------------------------------------- 1 | 00:00 Third day, you have your API client built. 2 | 00:03 You've got your program ready. 3 | 00:04 Now you need to use it. 4 | 00:06 So just fill out program.py. 5 | 00:08 Add a simple UI that just asks 6 | 00:11 the user a questions like, hey, what, 7 | 00:13 or how do you want to search for your movie? 8 | 00:14 By director, by keyword, and so on. 9 | 00:17 And then just use your client to do that search 10 | 00:20 and then present the results to the user, right? 11 | 00:23 Should be pretty straightforward. 12 | 00:25 Remember, you get the response back, 13 | 00:26 you have to make sure that it's valid 14 | 00:28 and then you call json to actually get the data, right? 15 | 00:31 That's it, so hope you enjoyed learning about uplink. 16 | 00:33 It's a really unique and interesting way to models APIs. 17 | -------------------------------------------------------------------------------- /transcripts/55-uplink/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now, let me just put one final warning out there 2 | 00:02 before we jump into building these API's with Uplink. 3 | 00:05 Uplink is great for creating structured clients 4 | 00:07 against HTTP services, 5 | 00:08 works really, really well. 6 | 00:10 However, if the API you're working with already has 7 | 00:14 a Python implementation, use that. 8 | 00:17 It's likely implemented and maintained by the company 9 | 00:20 that actually controls the API. 10 | 00:22 It'll continually be upgraded, and so on. 11 | 00:26 So, for example, over here at Stripe, they have an API. 12 | 00:28 We could use Uplink to build our very 13 | 00:31 own client to talk to it. 14 | 00:32 But, we can just pip install stripe, 15 | 00:34 and they'll maintain that and upgrade that over time, 16 | 00:37 and we don't have to worry about it. 17 | 00:39 So, Uplink really fits in the place where you have this 18 | 00:41 structured API you want to work with, 19 | 00:43 however, it doesn't have like an official 20 | 00:46 PyPI package that is the API wrapper. 21 | 00:49 Which there are many, many of those of course, 22 | 00:51 but first check and see if there's something from the 23 | 00:54 company or organization to already access that API 24 | 00:57 and use that, but if not, Uplink, that's where we're goin'. 25 | -------------------------------------------------------------------------------- /transcripts/58-tweepy/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Hello and welcome back to the 100 Days of Python. 2 | 00:03 The next three days, I will be your guide, 3 | 00:05 teaching you how you can do 4 | 00:07 Twitter data analysis with Python. 5 | 00:09 First, we set up an application with the Twitter API. 6 | 00:12 Next, we set up a virtual environment and import 7 | 00:15 the Twitter key secret and access tokens. 8 | 00:18 Then, we dive straight in using the cursor object 9 | 00:21 of the tweepy module to get all our tweets. 10 | 00:24 Then we show our most popular tweets 11 | 00:26 based on an average of the number of likes and retweets. 12 | 00:29 Then we look at the top hashtags and mentions, 13 | 00:32 and finally, we feed all our tweets into an awesome module 14 | 00:36 called Wordcloud, which makes a nice visual representation 15 | 00:40 of our Twitter usage. 16 | 00:42 And the second and third day, I got a lot of 17 | 00:44 interesting projects lined up to solidify 18 | 00:47 your newly gained Twitter data analysis skills. 19 | 00:50 This will be a lot of fun 20 | 00:52 and I'm exciting to teach you this. 21 | 00:54 See you in the next video. 22 | -------------------------------------------------------------------------------- /transcripts/58-tweepy/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 First we want to make an app using the Twitter API, 2 | 00:04 so head over to apps.twitter.com/app/new, 3 | 00:09 I'm going to call it Twitter API Demo 4 | 00:13 to work on the small Tweepy Python code example. 5 | 00:17 We can just put in our website and callback 6 | 00:19 URL's not needed. 7 | 00:21 After I agree with the terms and create your 8 | 00:25 Twitter application. 9 | 00:26 With the app created you'll want to head over 10 | 00:28 to keys and access tokens, 11 | 00:31 and note down the consumer key, consumer secret, 12 | 00:35 and your access token, and secret. 13 | 00:37 And we will need to export those as variables, 14 | 00:40 which I will show you in the next video. 15 | -------------------------------------------------------------------------------- /transcripts/61-github/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 Days of Python, Day 61. 2 | 00:04 Wow, that means you're already 60% in. 3 | 00:07 Way to go and keep going. 4 | 00:09 I hope you enjoy it. 5 | 00:10 The next 3 days, I will be your guide, 6 | 00:13 showing you how you can use the GitHub API with Python. 7 | 00:17 We will be using a module called PyGitHub, 8 | 00:20 which makes it pretty easy to work with the API. 9 | 00:23 We will both retrieve data from the API, 10 | 00:26 as well as post data to the API. 11 | 00:29 While doing that, I will also show you 12 | 00:32 the builtin help and their functions in Python, 13 | 00:35 to retrieve more documentation from the API. 14 | 00:38 And finally, I will also show you how to use pdb, 15 | 00:42 the debugger, to look at your code in realtime. 16 | 00:45 Working with APIs is a very useful skill to have. 17 | 00:48 So I'm very excited to show you how to do that. 18 | -------------------------------------------------------------------------------- /transcripts/64-email-smtplib/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 G'day everyone, welcome back. 2 | 00:01 This is Julian Sequeira again 3 | 00:03 and welcome to Sending Emails with SMTPLib. 4 | 00:06 This is one of my favorites 5 | 00:09 just because I love automating stuff, right. 6 | 00:12 And this is one of the first cool things 7 | 00:14 that you're going to automate with Python. 8 | 00:17 Sending emails via a script 9 | 00:19 is extremely gratifying and awesome 10 | 00:21 if you want to spam your friends 11 | 00:23 and I think you're really going to enjoy it, too. 12 | 00:26 So, the point of these videos 13 | 00:28 is to teach you how to send an email 14 | 00:30 using a script, SMPTLib 15 | 00:32 and the Python MIME modules 16 | 00:35 which I'll explain in a bit. 17 | 00:38 So, click next and carry on with the videos. 18 | 00:41 Next, we're going to set up your Gmail application ID 19 | 00:44 and then straight from there, 20 | 00:46 create a script. 21 | -------------------------------------------------------------------------------- /transcripts/64-email-smtplib/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Alrighty, this one's nice and quick, 2 | 00:02 the setup, so just go ahead 3 | 00:04 and create yourself an emailer folder. 4 | 00:06 whatever you want to call it for this project, 5 | 00:08 and install your virtual environment. 6 | 00:12 Now, with this, smtplib and the mime modules 7 | 00:16 they're all built in, it's all standard Lib. 8 | 00:19 So you actually won't need to pip install anything extra. 9 | 00:22 Not for this, but as always let's just 10 | 00:27 activate our virtual environment 11 | 00:29 just so we have a nice clean environment to run in. 12 | 00:34 And in this directory go ahead and create yourself 13 | 00:37 two files, I'm separating them just for ease 14 | 00:40 of explanation right. 15 | 00:42 So we're going to create an emailer file 16 | 00:45 and an emailer-mime file. 17 | 00:49 Call them whatever you want, 18 | 00:51 that's just what I'm naming them. 19 | 00:52 And let's populate the files. 20 | -------------------------------------------------------------------------------- /transcripts/67-pyperclip/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back, this is Julian Sequeira 2 | 00:02 and I am going to be walking you through a very simple 3 | 00:06 yet awesome module named pyperclip. 4 | 00:09 This is a module that we'll simply copy and paste 5 | 00:13 from your code, there we go, done. 6 | 00:16 May as well not watch the next three videos. 7 | 00:19 This is a module I actually can't live without. 8 | 00:21 It has made so many scripts 9 | 00:24 just that little bit easier for me 10 | 00:26 and it's just a wonderful, wonderful script. 11 | 00:30 So, module I should say. 12 | 00:32 So, I reckon you're going to enjoy the next couple of days. 13 | 00:35 We're going to do a couple of really simple scripts 14 | 00:38 after we walk through how to use pyperclip. 15 | 00:40 Don't worry that takes about two seconds, copy and paste. 16 | 00:43 So, click the next button, 17 | 00:46 watch the next video, and let's create some fun scripts. 18 | -------------------------------------------------------------------------------- /transcripts/67-pyperclip/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Righty oh, let's get cracking. 2 | 00:02 All right, so a quick setup for us. 3 | 00:04 Let us quickly create our virtual environment. 4 | 00:11 Create the venv and all we have to do for this video 5 | 00:15 for it to work for the rest of 6 | 00:16 this lesson is pip install. 7 | 00:20 First let's activate it. 8 | 00:23 Okay, so, pip install pyperclip 9 | 00:27 because it isn't in standard lib. 10 | 00:30 And once that is installed, I'd like you to go through 11 | 00:33 and just create the following two files 12 | 00:36 text-replacer.py and affiliate.py. 13 | 00:41 That should give you a hint as to 14 | 00:42 what these scripts are going to be. 15 | 00:44 So once you've got everything installed, 16 | 00:47 and pip installed and whatnot, 17 | 00:49 just go ahead and move onto the next video. 18 | -------------------------------------------------------------------------------- /transcripts/70-openpyxl/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day and welcome to Excel automation with openpyxl. 2 | 00:05 I'm Julian Sequeira and I'm going to be walking you 3 | 00:07 through a couple of days of playing 4 | 00:09 with a really boring finance Excel spreadsheet. 5 | 00:14 But, unfortunately that's the way, 6 | 00:16 that's its trial by fire, right. 7 | 00:18 We need to be able to play with an actual, 8 | 00:21 really well populated spread sheet 9 | 00:23 in order to make working with openpyxl doable, really. 10 | 00:29 So get your Excel boots on and get prepared to play 11 | 00:33 with Excel, manipulate some cells, 12 | 00:35 insert some data, all with openpyxl. 13 | -------------------------------------------------------------------------------- /transcripts/70-openpyxl/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Okay, so the first thing we need to do, 2 | 00:02 as usual, is set up our environment. 3 | 00:05 So we're going to create ourselves a virtual environment, 4 | 00:12 called venv, 5 | 00:14 and once that's installed, we are going to launch it. 6 | 00:21 Okay, and then we're going to pip install openpyxl 7 | 00:28 That's all we're going to need for this lesson. 8 | 00:30 The other thing you can do, if you wish, 9 | 00:33 is create a python file in this directory 10 | 00:36 called excel_automation. 11 | 00:40 Furthermore, if you want to follow along with the 12 | 00:43 commands, as I type them, 13 | 00:45 you'll want to download the financial sample. 14 | 00:49 Okay, this is a document that you'll see in the repo. 15 | 00:53 Pull that Excel file across and you should be able 16 | 00:56 to follow along with that. 17 | -------------------------------------------------------------------------------- /transcripts/73-selenium/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 Days Of Python. 2 | 00:03 Wow, Day 73, you're making great progress. 3 | 00:07 The coming 3 days I will be your guide, 4 | 00:09 to teach you how to use Selenium in Python 5 | 00:12 to automate some cool tasks. 6 | 00:14 After some basics, we dive straight into 7 | 00:17 a practical example, where I will show you how 8 | 00:19 you can use Selenium to login to a website. 9 | 00:23 In this case, Packt, where I got some E-books 10 | 00:26 piled up that we will grab with Selenium, 11 | 00:28 making them downloadable from the Command line. 12 | 00:31 That's already pretty cool, but then we will 13 | 00:34 look at a second application. 14 | 00:36 We log into the PyBites banner app, 15 | 00:38 which is a Flask app, we simulate using the 16 | 00:41 forum manually by posting the variables straight 17 | 00:44 to the server. 18 | 00:45 And it comes back with a banner, all in a 19 | 00:47 automated way. 20 | 00:48 And that's pretty powerful. 21 | 00:49 But if you need, like, to make 200 banners, 22 | 00:52 a tool like Selenium can save you 23 | 00:54 a lot of time. 24 | 00:55 So this will be a very practical lesson, 25 | 00:57 a lot of code, and will be a lot of fun. 26 | 00:59 And at the end of it, I will have some 27 | 01:01 practical exercises, so you get your hands dirty 28 | 01:04 with Selenium. 29 | 01:06 Let's dive straight in. 30 | -------------------------------------------------------------------------------- /transcripts/73-selenium/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's look at the Selenium hello world example. 2 | 00:04 And let's look quickly what happens when I run this. 3 | 00:08 And I have to move the browser into my recording area. 4 | 00:13 I put the PyCon into the search box, hits return, 5 | 00:19 looks at the results and makes an assertion. 6 | 00:22 Now how cool is that, that it just opens a browser, 7 | 00:24 does all this stuff automatically? 8 | 00:27 And when you're dealing with web pages 9 | 00:29 you probably want to inspect them so you can do that here, 10 | 00:32 and you can look at the developer tools 11 | 00:35 and here you see that input has a name of queue, 12 | 00:38 so that's Selenium here is finding. 13 | 00:41 Sending PyCon, hitting return and no results found 14 | 00:46 should not be in the driver page source. 15 | 00:48 So here to back to the results. 16 | 00:51 Yes there are results for PyCon obviously. 17 | 00:54 And the talk a lot about automating tasks, 18 | 00:56 but one of the most common use cases is actually 19 | 00:59 to automate your testing, go through your dev sites, 20 | 01:02 filling out forms, looking and returns 21 | 01:04 and automate that as part of your functional testing. 22 | 01:08 So that's the hello world example of Selenium. 23 | -------------------------------------------------------------------------------- /transcripts/73-selenium/7.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back. 2 | 00:01 In this second and third day, 3 | 00:03 it's time to get more practice with Python Selenium. 4 | 00:06 Notice that Selenium is a super important tool 5 | 00:10 often used in addition to functional testing. 6 | 00:13 I've not really explained that or demonstrated that so far, 7 | 00:16 but you're going to just play directly with it 8 | 00:19 because I have a nice code challenge for you. 9 | 00:22 First, take a quick look at this documentation section: 10 | 00:26 Using Selenium to Write Tests. 11 | 00:28 Then head straight to our Code Challenge 32. 12 | 00:31 This is our first Django app we did. 13 | 00:33 So, we made a little scraper of Planet Python, 14 | 00:37 and made a app to keep track 15 | 00:39 of what we were sharing on Twitter. 16 | 00:41 That's basically a listing of articles 17 | 00:43 where we can say we shared 'em or we skipped 'em. 18 | 00:46 Very simple, but it has a login. 19 | 00:49 So, it's a nice app to do some testing on. 20 | 00:52 So, you'll be asked to log in, look at articles, 21 | 00:55 look at various states the articles are in. 22 | 00:58 Look at the HTML of the page, etc. 23 | 01:01 And the whole write-up is here. 24 | 01:03 And I think it's a great exercise 25 | 01:05 to practice more with Selenium. 26 | 01:08 And that's it. 27 | 01:09 Try to do that one today, 28 | 01:10 or even the third day if you lack time. 29 | 01:13 And, I'll see you tomorrow. 30 | -------------------------------------------------------------------------------- /transcripts/73-selenium/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back. 2 | 00:01 This is the third day of the Python Selenium lesson. 3 | 00:04 I hope the exercise of yesterday 4 | 00:06 to test our little Django app was not too hard. 5 | 00:10 If you're still working on it, no problem. 6 | 00:12 I think it's a good workout so 7 | 00:14 then just use this third day to complete that. 8 | 00:18 If you're done or you're bored, 9 | 00:19 you want something else, 10 | 00:20 we looked at two core examples in this lesson, 11 | 00:23 Packt and automated banner generation. 12 | 00:26 Maybe you want to try those, 13 | 00:28 build them out, 14 | 00:29 or maybe even better scratch your own itch. 15 | 00:31 What are some of your boring stuff 16 | 00:33 that you can automate and write tools for? 17 | 00:35 Maybe you have a log in you want to automate to 18 | 00:38 your favorite site or social media, 19 | 00:40 retrieve some data, 20 | 00:42 or maybe even post some data. 21 | 00:43 The options are endless 22 | 00:45 and the best you can do is practice some more 23 | 00:48 because it's the practice with the new technology 24 | 00:50 that makes you a master 25 | 00:51 and it's also the most fun. 26 | 00:53 So enjoy and don't forget to share your work. 27 | 00:56 Use the #100DaysOfcode 28 | 00:57 and feel free to include @TalkPython 29 | 01:00 or @PyBites in your tweets 30 | 01:02 because we would love to see what you come up with. 31 | 01:04 Good luck and have fun. 32 | -------------------------------------------------------------------------------- /transcripts/76-flask-app/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day guys, this is Julian Sequeira again 2 | 00:03 and welcome to Day 76, 77, and 78. 3 | 00:07 In this three part segment, 4 | 00:09 we are going to be building a Flask app. 5 | 00:11 For those of you who may have taken other courses, 6 | 00:14 this is one of my favorite themes. 7 | 00:16 So, I'm really excited to be teaching you this one. 8 | 00:19 The basics here, we are going to just build 9 | 00:21 a really simple Flask app 10 | 00:23 but we're going to use Jinja2 templates 11 | 00:25 straight off the bat. 12 | 00:26 We're not just going to deal with the basics. 13 | 00:29 And then we're going to deal with dictionaries 14 | 00:31 and how to print those variables, 15 | 00:33 how to print that data straight into a Jinja2 template 16 | 00:37 that way your actual website has some functionality. 17 | 00:40 So, let's get right into it and start coding. 18 | -------------------------------------------------------------------------------- /transcripts/79-sqlite3/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome to SQLite 3 Databases. 2 | 00:03 I'm Julian Sequeira and I'll be walking you through 3 | 00:06 possibly one of the most fun and satisfying libraries 4 | 00:09 you'll deal with on your Python journey. 5 | 00:11 I say that because at this point you'll be looking 6 | 00:14 at persistent data, more so than just a simple text file 7 | 00:20 or what have you. 8 | 00:21 SQLite 3 Databases allow you to actually use your SQL 9 | 00:25 knowledge to give you self-persistent databases. 10 | 00:29 It's as simple as that. 11 | 00:30 It's exactly what you expect if you've ever dealt 12 | 00:33 with databases before and it's really, really simple. 13 | 00:37 So these three days you're going to be creating your first 14 | 00:40 SQLite 3 database 15 | 00:43 and then you'll be learning how to inject data into a... 16 | 00:47 Print the data out and I've also included a couple of really 17 | 00:50 cool scripts that you should help you automate some 18 | 00:53 of your SQL journeys and also it should help you, 19 | 00:58 help guide you through your SQLite 3 learning. 20 | 01:00 So enjoy and get cracking. 21 | -------------------------------------------------------------------------------- /transcripts/79-sqlite3/2.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's get started. 2 | 00:01 The first thing I need you to do is open up your browser 3 | 00:04 and head to sqlitebrowser.org. 4 | 00:09 It's this website here. 5 | 00:10 And this is for a database browser for SQLite. 6 | 00:14 It's a sort of GUI, a graphical user interface, 7 | 00:17 that allows you to see the contents of your database. 8 | 00:21 And this is important because sometimes 9 | 00:24 when you're checking things on the command line, 10 | 00:25 it's quite difficult to figure out. 11 | 00:28 You get that visual representation 12 | 00:29 of the columns and how everything looks like in the table. 13 | 00:33 Looking at this screenshot here, this is a Mac screenshot. 14 | 00:36 You can see there's your table here called Total Members. 15 | 00:41 There's the different columns and so on. 16 | 00:44 Now, we're going to use this a bit later on, but this is 17 | 00:47 pretty much the only setup step you're going to need to do. 18 | 00:49 So go ahead and download it 19 | 00:51 for your operating system of choice. 20 | 00:53 I'm using Windows, obviously, and my one, 21 | 00:57 once installed, looks like this. 22 | 00:59 Okay, no database is actually loaded into it. 23 | 01:02 We can use the open database button here 24 | 01:04 to load one in once we actually have it. 25 | 01:07 But for now, just get it installed. 26 | 01:10 That's sqlitebrowser.org. 27 | -------------------------------------------------------------------------------- /transcripts/79-sqlite3/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 So we'll bring up the program here. 2 | 00:03 I've got mine open already. 3 | 00:04 Control + O will actually open up our open dialogue, 4 | 00:09 and there is our address book database. 5 | 00:12 So let's open that up. 6 | 00:15 You can get a bit of information here, 7 | 00:17 although this isn't the most detailed view, 8 | 00:19 but straight away, you can see 9 | 00:21 there's one table within this database, 10 | 00:23 with the name of details, 11 | 00:25 and it's got these three columns. 12 | 00:28 So let's actually go to browse data. 13 | 00:31 This looks more like what you sort of want to see 14 | 00:33 when you visualize your database. 15 | 00:36 There's the table name, there's our name column, 16 | 00:39 address column, and our phone number column. 17 | 00:42 In the next video, I'm going to show you 18 | 00:45 how to set this up automatically. 19 | -------------------------------------------------------------------------------- /transcripts/82-dataviz/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the 100 Days of Python, 2 | 00:02 Day 82, data visualization with Plotly. 3 | 00:06 Coming three days, I will be your guide 4 | 00:08 teaching you how you can make beautiful plots 5 | 00:11 in Python using this library. 6 | 00:13 We're going to take some data from our PyBites blog 7 | 00:16 and I will show you how to first get that data 8 | 00:19 in the right shape so it's easy to 9 | 00:22 just hand it off to Plotly and make some cool graphs 10 | 00:25 that show some insights about what the blog is about, 11 | 00:29 and hopefully that will inspire you 12 | 00:32 to then roll your own, be it with Plotly, 13 | 00:35 or another awesome library, which I will mention, 14 | 00:37 which is Bokeh, and yes, this will be a lot of fun. 15 | 00:41 It's one of my favorite topics, 16 | 00:42 and having data visualization skills goes a long way. 17 | 00:46 I mean, there's a lot of data out there, 18 | 00:48 even more now with big data, 19 | 00:50 but if you can show it in a nice way, 20 | 00:52 it's way more powerful. 21 | 00:54 So, let's dive straight in and learn some new skills. 22 | -------------------------------------------------------------------------------- /transcripts/82-dataviz/10.txt: -------------------------------------------------------------------------------- 1 | 00:00 Welcome back to the third and final day 2 | 00:02 of data visualization. 3 | 00:03 I hope you are making great progress. 4 | 00:06 And let me just share you one more pointer. 5 | 00:09 Randy Olson sends out very cool Tweets 6 | 00:13 about data visualization. 7 | 00:14 And here's his Twitter account. 8 | 00:17 And it's chuck-full of awesome visualizations. 9 | 00:24 So that's probably somebody, 10 | 00:26 if you like data visualization, who you want to follow. 11 | 00:29 And you can also look at the data 12 | 00:31 of his hashtag on Twitter. 13 | 00:40 Look at that, carots , very cool. 14 | 00:43 Right, so, apart from that, keep on coding. 15 | 00:46 Keep on using these cool libraries 16 | 00:48 that I've shown you in this lesson. 17 | 00:50 And don't forget to share your work. 18 | 00:52 You can use the hashtag #100DaysOfCode 19 | 00:55 and feel free to mention TalkPython and PyBites 20 | 00:58 in your Tweets. Good luck and have fun. 21 | -------------------------------------------------------------------------------- /transcripts/85-anvil/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Hello and welcome to Day 85, Michael here again. 2 | 00:02 We're going to build a really cool interactive web application. 3 | 00:06 And we're going to do it the easy way. 4 | 00:08 You've already seen Flask, 5 | 00:09 and Flask is super powerful, and super flexible. 6 | 00:12 In fact, we're going to come back to Flask again, 7 | 00:15 maybe one or two more times in this course still, 8 | 00:18 but I want to show you an alternative way to build web apps, 9 | 00:21 and especially if you think to yourself, 10 | 00:23 I'm not a web developer, I'm not super good with CSS, 11 | 00:26 I'm not great with html, layout doesn't work for me, 12 | 00:29 I can't put together the web pieces, 13 | 00:32 these tables are crazy, I'm not great with databases. 14 | 00:35 All of these things? 15 | 00:36 I'm going to show you a way to build 16 | 00:38 quite a wide spectrum of apps 17 | 00:40 in a super easy and accessible way 18 | 00:42 that you can be up and running, literally in a day or two. 19 | -------------------------------------------------------------------------------- /transcripts/85-anvil/23.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 2, on the second day it's all about data. 2 | 00:03 So what we're going to do is going to 3 | 00:04 create a data table service, 4 | 00:06 so just go to the services and say +, 5 | 00:08 choose data tables, and then this thing down here 6 | 00:10 will pop up like this. 7 | 00:12 Create as many tables as you need up here, 8 | 00:14 define their schema, and you can even 9 | 00:16 enter down here some starter data. 10 | 00:19 For example, if it's something that's 11 | 00:20 kind of static or you just want a little data to start with. 12 | 00:23 That's great, remember no access from forms, 13 | 00:25 access from the server modules. 14 | 00:27 Once you have that you're going to need 15 | 00:28 a way to get that data down to your application 16 | 00:31 so go ahead and add a server module 17 | 00:33 and then define the functions that you're going to need 18 | 00:36 to send the data down. 19 | 00:37 You can look in the demo code 20 | 00:39 that I put in this repository in this particular day 21 | 00:42 if you want to see how we did the queries there. 22 | 00:45 It's pretty easy because they basically have 23 | 00:47 a commented section when you create a new server module 24 | 00:49 that shows you both how to use it on the client 25 | 00:51 and how to define it on the server, 26 | 00:53 so just follow along what they have in the comments. 27 | 00:55 Once you've got that going, that's Day 2. 28 | 00:57 You might want to just call those 29 | 00:58 functions from your main form 30 | 01:00 as a little test just to see that they're working 31 | 01:02 and then throw those away, 32 | 01:03 but that's what you did today, it's all about the data. 33 | -------------------------------------------------------------------------------- /transcripts/85-anvil/3.txt: -------------------------------------------------------------------------------- 1 | 00:00 Let's take a look at the app that we're going to build. 2 | 00:03 The app is called HighPoint, 3 | 00:05 kind of like SharePoint but with Python. 4 | 00:07 So it's just this knockoff off on a really simple 5 | 00:10 document management application. 6 | 00:12 But you'll see that it's quite involved. 7 | 00:14 So here on our homepage, we've got a couple operations. 8 | 00:17 You go view all the documents or create a new document. 9 | 00:20 Here's the most recent ones. 10 | 00:22 You can click and see the details. 11 | 00:24 So when it was created, all the info about it, and so on. 12 | 00:28 You go over to all the documents and you could filter. 13 | 00:31 For example, one of these has 14 | 00:33 the word atoms in it, that one. 15 | 00:36 Another one has grass-fed request for example. 16 | 00:39 So really nice and again you can see the details. 17 | 00:41 And then finally you want to add a new document, 18 | 00:43 you come down here, you pick a category, 19 | 00:46 create it, you have validation, all this kind of stuff. 20 | 00:48 So we're going to build this in a really short amount of time. 21 | 00:52 And then put it on the internet with a full deployment. 22 | 00:55 How about that? 23 | 00:56 Hopefully you're looking forward to it. 24 | 00:58 It's a cool technology and it's going to be a lot of fun. 25 | -------------------------------------------------------------------------------- /transcripts/85-anvil/4.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now that you've seen the application 2 | 00:02 that we're going to build, 3 | 00:03 our SharePoint document management knock-off thing, 4 | 00:06 you might be thinking there's no way we'll be able 5 | 00:09 to build that in like 30 minutes 6 | 00:11 or whatever this is going to take. 7 | 00:13 Well, it turns out, 8 | 00:14 if we use this thing called Anvil, we can. 9 | 00:17 So Anvil is this new product that came out 10 | 00:19 that lets you write Python code for everything that you do, 11 | 00:23 and it's really this cool visual designer 12 | 00:27 and application builder for Python web applications 13 | 00:30 with both the service side and client side component. 14 | 00:33 Now there's a free version of Anvil that you can get, 15 | 00:35 and it has some restrictions. 16 | 00:37 And so I was a little bit hesitant to use it for this course 17 | 00:40 because for it to really take full advantage of it, 18 | 00:42 you have to pay for it. 19 | 00:43 But on the other hand, it's so powerful. 20 | 00:46 I think a lot of you will really appreciate 21 | 00:48 what you can do with it 22 | 00:49 and might actually find it super useful 23 | 00:51 and not mind paying the small bit that you pay anyway. 24 | -------------------------------------------------------------------------------- /transcripts/88-home-inventory-app/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Good day everyone, welcome back. 2 | 00:02 This is Julian Sequeira and I'm going to be walking you through 3 | 00:05 the next 3 days of creating a home inventory app. 4 | 00:10 This is designed to just sort of get you thinking about 5 | 00:13 the whole app creation process, 6 | 00:16 even though I know you've done it by now. 7 | 00:18 But also to get you using a few different things in Python. 8 | 00:23 So in this specific app we are going to use SQLite3 9 | 00:27 as the database. 10 | 00:28 But we're going to cover a little bit of generators. 11 | 00:30 And we're just going to do some basic Python to get you through 12 | 00:35 creating your own sort of storage app 13 | 00:37 that recalls data, takes input, 14 | 00:39 and you can imagine what it's going to be like. 15 | 00:42 So, carryon through the next three days 16 | 00:44 and let's see what we can come up with. 17 | -------------------------------------------------------------------------------- /transcripts/88-home-inventory-app/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 Okay and that is it. 2 | 00:01 Hopefully by now you've got 3 | 00:02 a nice fully functional home inventory app going 4 | 00:05 and you learned something on the way, okay. 5 | 00:07 Especially with SQLite and with the generator 6 | 00:10 and whatever other cool little ways 7 | 00:13 you've managed to make this app your own. 8 | 00:15 I'm not going to bother going through any slides 9 | 00:17 for the finale of this lesson set, 10 | 00:20 just because we did go through 11 | 00:21 quite a lot of content. 12 | 00:23 What I will do is, 13 | 00:24 I will show you the ReadMe 14 | 00:26 one more time, 15 | 00:28 just so you know what you can do with this 16 | 00:30 if you haven't done it already, 17 | 00:32 is run yourself a GUI or a web interface. 18 | 00:36 I think that's the next logical step for this app 19 | 00:39 because it would be a lot of fun to be able 20 | 00:40 to bring up a website 21 | 00:41 and enter in your entire room into one form 22 | 00:45 and have it submitted to a database, okay. 23 | 00:48 So, this is your turn. 24 | 00:50 Obviously, go ahead and identify the pitfalls 25 | 00:53 and the bugs as per that video 26 | 00:55 and make them your own. 27 | 00:57 Solve them, resolve them. 28 | 00:59 See if you can turn it into something great 29 | 01:02 other than just a CLI app. 30 | 01:04 And that's your home inventory app. 31 | -------------------------------------------------------------------------------- /transcripts/900-appendix-pylang/2.txt: -------------------------------------------------------------------------------- 1 | 
0:02 Variables are the heart of all programming languages.  2 | 0:05 And variables in Python are no nonsense.  3 | 0:08 Let's look at the top one, I am declaring a name variable  4 | 0:11 and assigning it the value of Michael,  5 | 0:13 and age variable and assigning it the variable of 42.  6 | 0:16 Some languages you have to put type descriptors in the front  7 | 0:19 like you might say string name, integer age,  8 | 0:22 you might put semicolons at the end, things like that.  9 | 0:25 None of that happens in Python, it's about as simple as it possibly can be.  10 | 0:28 So we can declare them and assign them to constant values,  11 | 0:32 we can increment their value in this case of the birthday  12 | 0:35 and we can assign them to complex values like the hobby,  13 | 0:39 which is really the list or array of strings, the hobbies that we have.  14 | 0:42 So we assign these on creation, and we can even take the return values of functions  15 | 0:47 and assign them to these variables, like so.  16 | -------------------------------------------------------------------------------- /transcripts/900-appendix-pylang/20.txt: -------------------------------------------------------------------------------- 1 | 
0:00 By leveraging inheritance, we can crate  2 | 0:02 a wide range of types that model our world very well,  3 | 0:06 in this example on the screen we have a wizard  4 | 0:08 and the wizard knows how to battle a variety of creatures,  5 | 0:11 we have small animals that are easier to defeat,  6 | 0:13 we have standard creatures, we have dragons, we have wizards.  7 | 0:16 All of these types are derived from the creature type.  8 | 0:20 Now, the wizard class, you can see, can attack any of these creatures, 9 | 0:24 and the reason the wizard class can attack them  10 | 0:26 is it's built, it's programmed to understand what a creature is  11 | 0:30 and attack it and any of the derived classes can be used interchangeably.  12 | 0:34 So this means we can continue to evolve and generate  13 | 0:38 new and interesting creature derived types  14 | 0:41 and we don't have to change our wizard code to understand how to battle them.  15 | 0:45 That's great, polymorphism is essential in any object-oriented language,  16 | 0:50 and that's absolutely true in Python as well.  17 | 18 | -------------------------------------------------------------------------------- /transcripts/900-appendix-pylang/25.txt: -------------------------------------------------------------------------------- 1 | 
0:01 So you've reached the end of the Python refresher and reference,  2 | 0:04 if you feel like you still need more help getting started with Python, 3 | 0:08 you want to practice more, dig much more into the language features that we just talked about,  4 | 0:13 then please consider my Python Jumpstart By Building Ten Apps course.  5 | 0:17 You can find it at talkpython.fm/course,  6 | 0:20 and it covers almost exactly the same set of topics  7 | 0:23 that we covered in the refresher as well as more,  8 | 0:26 but it does it by building ten applications, seeing them in action,  9 | 0:29 writing tons of code and it's done over seven hours,  10 | 0:33 rather than packing just the concepts into a quick refresher.  11 | 0:37 So, check out the Jumpstart Course, 12 | 0:40 if you want to go deeper into Python the language  13 | 0:43 and its features so that you can get the most out of this course.  14 | -------------------------------------------------------------------------------- /transcripts/900-appendix-pylang/7.txt: -------------------------------------------------------------------------------- 1 | 0:01 Functions are reusable blocks of functionality.  2 | 0:04 And of course, they play an absolutely central role in Python.  3 | 0:07 Now, in Python we can have functions that are just stand alone, isolated functions,  4 | 0:11 and these are quite common,  5 | 0:13 or we can have functions bound to classes and objects 6 | 0:16 that bind together specific data about an object along with those behaviors,  7 | 0:21 we call those methods.  8 | 0:23 The way we define them, interact with them, is basically the same,  9 | 0:26 regardless whether they are functions or methods.  10 | 0:28 Here you can see we have a main method, we want to call it,  11 | 0:31 it takes no parameters, and returns nothing or nothing that we care about, 12 | 0:35 so we just say main open close parenthese, like so, 13 | 0:37 we can also call functions that take arguments,  14 | 0:40 here is a function called input, and it gathers input from the user, on the consoles,  15 | 0:44 it will give them a prompt, and this argument we are passing here is a string,  16 | 0:48 and this is the prompt to share to the user,  17 | 0:50 pauses the input on the console and waits for them to type something and hit enter,  18 | 0:54 when they do, the return value comes back  19 | 0:57 and is stored in this new variable called "saying".  -------------------------------------------------------------------------------- /transcripts/900-appendix-pylang/9.txt: -------------------------------------------------------------------------------- 1 | 
0:01 Working with files in Python, especially text files  2 | 0:03 is something that you are likely to need in your application.  3 | 0:06 So let's take a really simple example.  4 | 0:09 Here we are going to create a file,  5 | 0:11 we have three items in our data structure we want to save on the three separate lines,  6 | 0:15 so we have cat, hat, mat and a list, and these are just strings.  7 | 0:18 We are going to use the "open" method,  8 | 0:20 and the "open" method takes a file name and a modifier,  9 | 0:23 and then this "open" method, the open string that comes back  10 | 0:26 can be used as a context manager, so we are putting into a "with" block,  11 | 0:30 and naming the variable fout for file output,  12 | 0:33 and this automatically closes the file stream, as soon as we leave this with block.  13 | 0:38 So that's really nice and safe, makes sure we flush, it close it, all those kinds of things.  14 | 0:42 Once we get the file open, we are going to loop over each item  15 | 0:45 and we are just going to say "fout.write" and pass it the item, so cat, hat or mat.  16 | 0:50 Now, write does not append a new line, it just writes characters to the file,  17 | 0:54 so we want to say "\n" to append a new line,  18 | 0:57 so each one of these items up here is on a separate line in the file.  19 | 1:01 And notice this "w" modifier, this means write only and truncate the file if it exists.  20 | 1:06 We could also say "a" for append, "a+" for create an append  21 | 1:11 or "r" if we just wanted to read from the file but not write to it.  22 | 1:15 There is also a "b" modifier for binary files, but you'll use that less often.  23 | -------------------------------------------------------------------------------- /transcripts/91-sqlalchemy/1.txt: -------------------------------------------------------------------------------- 1 | 00:00 Are you ready to have some fun playing with the database? 2 | 00:03 Well, we're going to talk about an 3 | 00:04 amazing technology called SQLAlchemy. 4 | 00:07 And this is probably the best way, 5 | 00:09 and also, probably the most popular way 6 | 00:12 to access relational databases. 7 | 00:15 Previously, you learned about SQLite, 8 | 00:17 and SQLAlchemy will of course talk to SQLite, 9 | 00:20 but it'll talk to all kinds of databases. 10 | 00:23 You can find it at SQLAlchemy.org. 11 | 00:26 It's an object relational mapper. 12 | 00:28 So when we saw SQLite before, you just created strings, 13 | 00:31 and you said, "Create this table," 14 | 00:33 or, "Select this from wherever." 15 | 00:36 You would write in line SQL, and that was tied to SQLite. 16 | 00:40 Well, SQLAlchemy works in a much higher level. 17 | 00:42 What we're going to do is we're going to create classes, 18 | 00:44 and we're going to model the database shape in our classes. 19 | 00:49 SQLAlchemy will actually even create 20 | 00:51 the database from the classes, alright? 21 | 00:53 So this is really, really powerful. 22 | 00:55 We can point at almost any relational database, 23 | 00:57 and then we work in these high level Python constructs, 24 | 01:00 making it very, very easy for us to write the code. 25 | 01:03 We don't have to think in the SQL query language, 26 | 01:05 we just think in Python, and it just works. 27 | 01:08 It's up to SQLAlchemy to convert that 28 | 01:10 to the SQL query language. 29 | 01:12 It's really, really easy to get started. 30 | 01:14 It's extremely flexible and powerful. 31 | 01:16 And we're going to have a lot of fun building an app with it. 32 | -------------------------------------------------------------------------------- /transcripts/91-sqlalchemy/11.txt: -------------------------------------------------------------------------------- 1 | 00:00 Now you've seen SQLAlchemy in action, 2 | 00:02 it's your turn to put it in action 3 | 00:03 on whatever you want to build. 4 | 00:05 So, jump over here to the GitHub repository 5 | 00:07 and check out the SQLAlchemy section. 6 | 00:09 What we're going to start with is, 7 | 00:11 we're going to pick some application 8 | 00:13 that you've already built. 9 | 00:14 You're most of the way through this class, 10 | 00:16 so you should have a lot of apps. 11 | 00:17 You can pick one of the games. 12 | 00:18 You can pick another application. 13 | 00:20 It doesn't really matter. 14 | 00:22 And you're going to add database persistence to it. 15 | 00:25 And you're going to add the ability 16 | 00:26 to use that to run reports, 17 | 00:28 or keep sessions going across runs of the program. 18 | 00:32 Something to that effect. 19 | 00:33 So we're going to start out on the first day 20 | 00:35 by just really picking out an application, 21 | 00:37 and then creating a virtual environment and 22 | 00:40 installing SQLAlchemy. 23 | 00:42 We'll get this all set up. 24 | 00:43 If you get a program that can import 25 | 00:46 SQLAlchemy and run, then you're pretty much ready. 26 | 00:48 Today was mostly about just watching 27 | 00:51 the videos and learning. 28 | 00:52 So this is just to give you something to 29 | 00:54 start with the next day. 30 | -------------------------------------------------------------------------------- /transcripts/91-sqlalchemy/13.txt: -------------------------------------------------------------------------------- 1 | 00:00 Final day of SQLAlchemy, 2 | 00:01 you've got your app selected, 3 | 00:04 got it running, you've modeled your classes 4 | 00:06 and created your database structure. 5 | 00:08 Now you just need to work with your data. 6 | 00:10 So you're going to insert some records, 7 | 00:12 save some data and insert it, 8 | 00:14 and then somewhere do a query. 9 | 00:16 Do a session.query of the type of query you want, 10 | 00:19 and just look back at the example. 11 | 00:21 We should have a variety of types of queries. 12 | 00:23 You should be able to make one of those 13 | 00:24 adaptable to what you're doing. 14 | 00:26 So just use this database, put some data in it, 15 | 00:30 and make your application more awesome from it. 16 | 00:33 All right, I hope enjoyed SQLAlchemy. 17 | 00:34 It's really a wonderful way to work with databases, 18 | 00:37 one of the more popular and flexible ones at that. 19 | -------------------------------------------------------------------------------- /transcripts/91-sqlalchemy/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 For the grand finale, let's just play one more game, 2 | 00:02 full-screen, not stuck inside of PyCharm there. 3 | 00:04 So we'll come over here, you can see 4 | 00:06 I have my virtual environment activated, 5 | 00:07 so I'll say python program, and in here, 6 | 00:09 we're already reading from that database. 7 | 00:12 I've got Michael's wins once, Jennifer 8 | 00:14 wins once, and computer. 9 | 00:15 Now, if I say Michael, it's going to go 10 | 00:17 and find that same player again, 11 | 00:18 and I'll just play some dragon, some dragon, 12 | 00:21 a little bit of lightning. 13 | 00:22 Am I doing, doing alright, I won that last round. 14 | 00:25 Let me try a little snake, and we'll finish it 15 | 00:27 off with some fire, five to zero, amazing. 16 | 00:30 Alright, now if I run it again, 17 | 00:31 you'll see, now I have two wins, Jennifer 18 | 00:34 has one win, computer getting crushed this time. 19 | 00:36 This is the game I built, and you can see 20 | 00:39 it wasn't totally easy to build up those relational classes 21 | 00:43 and so on, but it really wasn't that hard. 22 | 00:45 And we built our little separate database service, 23 | 00:48 our game service, code, so all 24 | 00:51 of our data access is contained 25 | 00:53 within just that little set of files. 26 | -------------------------------------------------------------------------------- /transcripts/94-guis/8.txt: -------------------------------------------------------------------------------- 1 | 00:00 The next day is you're going to actually build your GUI. 2 | 00:03 So the steps to make this happen are pretty straightforward. 3 | 00:06 They're just right here. 4 | 00:07 You're going to have a main method. 5 | 00:08 You're going to put an @gooey directive decorator on it. 6 | 00:12 Somewhere near the beginning we'll create a GooeyParser. 7 | 00:15 You've seen how to add the arguments. 8 | 00:17 At the end you call parser.parse_args. 9 | 00:20 Get that back, that'll give you your data. 10 | 00:23 You should have your UI running, right? 11 | 00:25 Remember, the goal is going to be to look through 12 | 00:28 the applications that you've built 13 | 00:31 and find one that's kind of fire and forget. 14 | 00:33 You give it some information 15 | 00:34 and press go do that and it will. 16 | 00:37 So find an application that you built, 17 | 00:39 that you like along these lines 18 | 00:41 and convert it to a UI version of that same application. 19 | 00:45 Right, so through these steps here. 20 | 00:47 Here's an example of one I had 21 | 00:48 that was a sort of project creation thing 22 | 00:51 for Pearman Web Apps and it would take Cookiecutter 23 | 00:55 and the various types of templates 24 | 00:56 and ask you the questions but it does it visually right here 25 | 00:59 so you're going to end up with something like this in the end. 26 | -------------------------------------------------------------------------------- /transcripts/94-guis/9.txt: -------------------------------------------------------------------------------- 1 | 00:00 Day 3, what you're going to do is 2 | 00:01 you're going to package up your app, so you're going to 3 | 00:03 install PyInstaller, and you're going to run this 4 | 00:06 build.spec, so the way to get started with these 5 | 00:08 is to just copy one, so here I've linked to the one 6 | 00:11 that I used for my demos. 7 | 00:13 You can take this and just change it ever so slightly, 8 | 00:16 so here's where I specify the name, 9 | 00:19 here's where I specify the name of the sort of entry point, 10 | 00:23 the main Python program we're going to run. 11 | 00:25 I think those are the only two things you need to change, 12 | 00:27 right, so take this, put it there, 13 | 00:31 and then just after you've installed PyInstaller, 14 | 00:33 you're going to run this line a little bit later. 15 | 00:35 In distribution app name, you should have either 16 | 00:38 an exe or a .app or, you name it. 17 | 00:42 Right, on Linux, you'll have 18 | 00:43 a Linux binary that you can run. 19 | 00:46 Zip it up and run it. 20 | 00:47 I hope you really enjoyed this experience building 21 | 00:50 simple, fire and forget, GUI applications in Python. 22 | 00:54 When you're done, as usual, share with the world 23 | 00:57 all the fun and joy of what you've had building this thing, 24 | 01:00 and I hope you have a great time and get to it. 25 | -------------------------------------------------------------------------------- /transcripts/97-online-game-service/19.txt: -------------------------------------------------------------------------------- 1 | 00:00 So we're over here, and we're calling service all_rolls, 2 | 00:04 and then we have to, remember you have to basically say, 3 | 00:07 service.all_rolls. Store that," and another thing 4 | 00:11 you have to say, raise_for_status 5 | 00:15 and then call JSON if that worked. 6 | 00:17 So that was really cumbersome. 7 | 00:20 So we created this thing called The uplink_helpers, 8 | 00:26 which had this basically uplink response handler 9 | 00:30 raise_for_status. 10 | 00:32 So if we go over here to our game, 11 | 00:34 oh sorry, api, excuse me, and we say this, 12 | 00:38 then it won't let any code through that fails. 13 | 00:42 So we know that it's safe to say .json right here, 14 | 00:45 'cause it's already tested it. 15 | 00:47 We can do better though. 16 | 00:48 We make it all of these methods return the dot. 17 | 00:50 JSON will response a result by adding one other thing. 18 | 00:55 This response to data. 19 | 00:56 So given a response, we just call response.json. 20 | 00:59 Otherwise, they throw a format error. 21 | 01:02 If we also put this at the top, 22 | 01:06 on the outside, not the inside. 23 | 01:08 The outside; That's important. 24 | 01:10 And this one goes on the inside. 25 | 01:11 Then we can come down here, and just print this. 26 | 01:15 And we should be our little devil, all the various pieces. 27 | 01:19 We do. Very nice. So I feel like our game service is in place, 28 | 01:23 and that really makes working with it nice and easy. 29 | -------------------------------------------------------------------------------- /transcripts/97-online-game-service/20.txt: -------------------------------------------------------------------------------- 1 | 00:00 You saw how easy these are to add. 2 | 00:02 Let me just drop in the other however many more, 3 | 00:04 five methods or whatever it is. 4 | 00:07 So we've got play_round, which has the body. 5 | 00:09 We've got top_scores. 6 | 00:10 We've got game_status, and so on. 7 | 00:13 That rounds out our little game service. 8 | 00:15 And we'll come over here, 9 | 00:17 we'll create one of these. 10 | 00:19 Create the top of our main method, actually, 11 | 00:20 let's do that. 12 | 00:22 And then we can call things like all_rolls 13 | 00:24 or Top Scores, and see what we get. 14 | 00:29 There's all_rolls, these are the top scores. 15 | 00:31 Michael apparently has scored one, 16 | 00:33 which beats, I guess everything else was score zero. 17 | 00:36 Yeah, it looks like it. 18 | 00:37 Okay, so, really, really cool! 19 | 00:39 This lets us interact with this service. 20 | 00:42 Now let's add in the logic. 21 | -------------------------------------------------------------------------------- /transcripts/97-online-game-service/24.txt: -------------------------------------------------------------------------------- 1 | 00:00 On the second day, you'll create the web services. 2 | 00:03 What are the various operations 3 | 00:06 you're going to need to do? You'll probably have a create and find user, 4 | 00:08 a game status, top scores, play round, 5 | 00:12 that kind of seems like it, but think 6 | 00:14 about how you want that game to play 7 | 00:16 if you chose something other than Hi-Low, 8 | 00:18 well, then I can't really guess, I can't really help you. 9 | 00:20 You don't need to write any client code, 10 | 00:22 you can just use Postman right here 11 | 00:24 then you can get it right there. 12 | 00:25 Of course, you use Postman like we did 13 | 00:28 to get it entirely working. 14 | 00:29 Remember, by the time we even created 15 | 00:31 our client code, we never touched 16 | 00:33 the web app again, it was totally working, 17 | 00:36 and that's partly 'cause I had prepared 18 | 00:38 a few of the tricky bits beforehand, 19 | 00:40 and that's also to a large degree 20 | 00:42 'cause we tested it out with Postman. 21 | --------------------------------------------------------------------------------