Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Byte-code files
*.pyc
__pycache__/

# Virtual environments
.venv
venv/
env/

# Editor/IDE specific files
.vscode/
.idea/
*.sublime-workspace

# Build artifacts
build/
dist/
*.egg-info/

# Test-related files
.pytest_cache/
.coverage/
htmlcov/

# Sensitive information
.env
config.ini
125 changes: 124 additions & 1 deletion User.py
Original file line number Diff line number Diff line change
@@ -1 +1,124 @@
# your User class goes here
from abc import ABC, abstractmethod
# your User class goes here


class Users(ABC):
@abstractmethod
def make_the_squiggle_go_away(self): # after adding the @abstract decorator, it wanted a function directly after, so the dicts below it were throwing an error
return

all_users = {}
all_posts = {}

def __init__(self, first_name = "", last_name = "", email_address = "", license_number = ""):
self.first_name = first_name
self.last_name = last_name
self.email_address = email_address
self.license_number = license_number
self.posts = []
if self.email_address != "":
self.add_user_to_all_users()

def add_user_to_all_users(self):
"""Adds this instance's details to the class attribute, all_users."""
# Access the class attribute via the class name
Users.all_users[self.email_address] = self # add to all_users using email address

@staticmethod
def create_new_user(UserClass):
"""Create a new user and return it"""
first_name = input("Enter your first name: ")
last_name = input("Enter your last name: ")
email_address = input("Enter your email address: ")
license_number = input("Enter your driver's license number: ")

new_user = UserClass(first_name, last_name, email_address, license_number)
print(f"\nSuccessfully added user: {new_user.email_address}")
return new_user # I was missing the actual return of the obj
# if email_address not in Users.all_users:
# print(f'Successfully addes new user. ')

def add_post(self):
# which post?
user_posts = input("Enter your post here: ")
# self.post = user_posts # need to use append like the one below. else it just overwrites the list
self.posts.append(user_posts)
print(f"Post has been posted: '{user_posts}'")

def delete_post(self):
if not self.posts: # if there is nothing in self.posts
print("No posts.")
return
print("\nYour current posts are: ")

for i, post in enumerate(self.posts):
print(f"[{i}]: {post[:50]}...") # if the post is super long, shorten it to the first 50 charactersCalled truncating

try: #try, but throw error if no valid inxed
index_to_delete = int(input("FInd the post you want and enter the index here: "))

if 0 <= index_to_delete < len(self.posts): # if user chose index greater than of eq to 0 and less than the number of posts total
deleted_post = self.posts.pop(index_to_delete)
print(f"Post deleted successfully: '{deleted_post[:30]}...'")
else:
print("Invalid index") # less than 0 or greater than the length of thte dict
except ValueError:
print("Invalid input. You have to use a number.")

def __str__(self):
return (f"User: {self.first_name} {self.last_name} {self.email_address}\nNumber of posts: {len(self.posts)} total.")
# return f"You have chosen a user. That user's information is: \n First Name: {self.first_name} \n Last Name: {self.last_name} \n Email address: {self.email_address} \n Driver's License: {self.license_number}. {self.all_users}"
# return f"You have chosen a user. That user's information is: \n First Name: {self.first_name} \n Last Name: {self.last_name} \n"
# return (
# f"You have chosen {self.first_name} {self.last_name}. \n"
# )
"""Req:
- User class needs to be a base class (from abc import ABC, abstractmethod)
- Two new classes, PremiumUser and FreeUser, that inherit from Users
- Overrid the add_post() for FreeUser so that an instance of FreeUser is limited to two posts
- In the runner file, import FreeUser and PremiumUser and create at least one instance of each
- Add testing """

class PremiumUser(Users):
def __init__(self, first_name="", last_name="", email_address="", license_number=""):
super().__init__(first_name, last_name, email_address, license_number)

def make_the_squiggle_go_away(self): # after adding the @abstract decorator, it wanted a function directly after, so the dicts below it were throwing an error
return


class FreeUser(Users):
def __init__(self, first_name="", last_name="", email_address="", license_number=""):
super().__init__(first_name, last_name, email_address, license_number)

def make_the_squiggle_go_away(self): # after adding the @abstract decorator, it wanted a function directly after, so the dicts below it were throwing an error
return


def add_post(self): # This method inherits from FreeUser, which in turn inherits from Users. It then overwrites the add_post method from the User Class
# check how many posts. Free only gets 2 posts
# set number of posts to equal the length of a
number_of_posts = len(self.posts)
if number_of_posts >= 2:
print("You've reached the max number of posts for a free user.")
return
user_posts = input("Enter your post here: ")
# self.post = user_posts # need to use append like the one below. else it just overwrites the list
self.posts.append(user_posts)
print(f"Post has been posted: '{user_posts}'")


print("--- Creating User ---")
user1 = Users.create_new_user(PremiumUser)
user1 = Users.create_new_user(FreeUser)

print("\n--- Adding Posts ---")
user1.add_post()
user1.add_post()


print("\n--- Deleting a Post ---")
user1.delete_post()

print("\n--- Final Check ---")
print(user1)
34 changes: 34 additions & 0 deletions runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# import User
from User import Users, FreeUser, PremiumUser

# free_user = Users.create_new_user(FreeUser)

# premium_user = PremiumUser("Someone_Cool", "steal@thisemail.com")
# premium_user = Users.create_new_user(PremiumUser)


# --- Creating Users ---
print("\n--- Creating Premium User (user_A@example.com) ---")
# Calling create_new_user and passing the PremiumUser class as the argument
premium_user_A = Users.create_new_user(PremiumUser)

print("\n--- Creating Free User (user_B@example.com) ---")
# Calling create_new_user and passing the FreeUser class as the argument
free_user_B = Users.create_new_user(FreeUser)

# --- Testing FreeUser Post Limit ---
print("\n--- Testing FreeUser Post Limit ---")
free_user_B.add_post() # 1st Post
free_user_B.add_post() # 2nd Post
free_user_B.add_post() # 3rd Post (Should print the limit message)

# --- Testing PremiumUser Posts ---
print("\n--- Testing PremiumUser Posts ---")
premium_user_A.add_post()
premium_user_A.add_post()
premium_user_A.add_post()

# --- Final Check ---
print("\n--- Final User State ---")
print(premium_user_A)
print(free_user_B)
66 changes: 66 additions & 0 deletions test_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import pytest
from User import *
from unittest.mock import MagicMock

# free_user = Users.create_new_user(FreeUser)

# prem_user = Users.create_new_user(PremiumUser)
# def test_create_user():
# user1 = create_new_user()

@pytest.fixture
def create_input_sequence(monkeypatch):
"""Generator that yields the inputs in the correct order."""
input_seq = [
"Jane", # 1st call to input()
"Doe", # 2nd call to input()
"jane@test.com", # 3rd call to input()
"1234" # Last call for DL
]

mock_input = MagicMock(side_effect=input_seq)

monkeypatch.setattr('builtins.input', mock_input)

return mock_input

@pytest.fixture
def mock_single_post_input(monkeypatch):
"""Mocks up single post input"""
test_post_content = "My first test using pytest"
monkeypatch.setattr('builtins.input', lambda _: test_post_content)
return test_post_content

def test_create_new_user(monkeypatch):
input_gen = create_input_sequence()

monkeypatch.setattr('builtins.input', lambda _: next(input_gen)) # That lambda is a placeholder)

new_user = Users.create_new_user(FreeUser)

assert new_user.first_name == "Jane"
assert new_user.last_name == "Doe"
assert new_user.email_address == "jane@test.com"
assert new_user.license_number == "1234"


def test_free_user_add_post(mock_single_post_input, capsys):
"""Tests the add_post method using monkeypatch to mock input and capsys to capture print output."""
# 1. Arrange
account = Users()
account.add_post()

assert mock_single_post_input in account.posts
assert len(account.posts) == 1

captured = capsys.readouterr()
expected_output = f"Post has been posted: '{mock_single_post_input}'\n"
assert captured.out == expected_output

""".out: This attribute contains a string of everything that was written to standard output (stdout)—i.e., everything printed by the print() function in your code.

.err: This attribute contains a string of everything that was written to standard error (stderr).

.in_: This attribute contains a string of any content that was read from standard input (stdin)."""