From dda8aacbb16e9f6e49c434acac018d88305ba15c Mon Sep 17 00:00:00 2001 From: "Abraham O. OLAGUNJU" <36889745+OluwaninsolaAO@users.noreply.github.com> Date: Wed, 22 Mar 2023 09:23:52 +0100 Subject: [PATCH] Task 06: still in development --- console.py | 1 - models/__init__.py | 11 ++++-- models/base_model.py | 15 ++++--- models/city.py | 11 ++++-- models/engine/db_storage.py | 79 +++++++++++++++++++++++++++++++++++++ models/state.py | 15 +++++-- 6 files changed, 115 insertions(+), 17 deletions(-) create mode 100755 models/engine/db_storage.py diff --git a/console.py b/console.py index 3f891299ed4e..997b50939934 100755 --- a/console.py +++ b/console.py @@ -12,7 +12,6 @@ from models.place import Place from models.review import Review from models import storage -from models.engine.file_storage import FileStorage class HBNBCommand(cmd.Cmd): diff --git a/models/__init__.py b/models/__init__.py index d3765c2bc603..ef3b02270ffd 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,7 +1,12 @@ #!/usr/bin/python3 -"""This module instantiates an object of class FileStorage""" -from models.engine.file_storage import FileStorage +"""This module instantiates the storage medium""" +import os +if os.environ.get('HBNB_TYPE_STORAGE') == 'db': + from models.engine.db_storage import DBStorage + storage = DBStorage() +else: + from models.engine.file_storage import FileStorage + storage = FileStorage() -storage = FileStorage() storage.reload() diff --git a/models/base_model.py b/models/base_model.py index 39b9ec27e1b8..ef498dd25d22 100644 --- a/models/base_model.py +++ b/models/base_model.py @@ -14,17 +14,16 @@ class BaseModel: id = Column(String(60), nullable=False, primary_key=True) created_at = Column(DateTime, nullable=False, default=datetime.utcnow()) updated_at = Column(DateTime, nullable=False, default=datetime.utcnow()) + def __init__(self, *args, **kwargs): """Instatntiates a new model""" if not kwargs: self.id = str(uuid.uuid4()) self.created_at = datetime.now() - self.updated_at = datetime.now() + self.updated_at = self.created_at else: - kwargs['updated_at'] = datetime.strptime(kwargs['updated_at'], - '%Y-%m-%dT%H:%M:%S.%f') - kwargs['created_at'] = datetime.strptime(kwargs['created_at'], - '%Y-%m-%dT%H:%M:%S.%f') + for at in ['created_at', 'updated_at']: + kwargs[at] = datetime.fromisoformat(kwargs[at]) del kwargs['__class__'] self.__dict__.update(kwargs) @@ -48,10 +47,14 @@ def to_dict(self): (str(type(self)).split('.')[-1]).split('\'')[0]}) dictionary['created_at'] = self.created_at.isoformat() dictionary['updated_at'] = self.updated_at.isoformat() + try: + del dictionary['_sa_instance_state'] + except KeyError: + pass return dictionary def delete(self): """Delete the class instance""" from models import storage - del storage.all()[self.to_dict()['__class__'] + '.' + self.id] + storage.delete(self) diff --git a/models/city.py b/models/city.py index b9b4fe221502..eb55bd4b1326 100644 --- a/models/city.py +++ b/models/city.py @@ -1,9 +1,12 @@ #!/usr/bin/python3 """ City Module for HBNB project """ -from models.base_model import BaseModel +from models.base_model import BaseModel, Base +from sqlalchemy import Column, String, ForeignKey +from sqlalchemy.orm import relationship -class City(BaseModel): +class City(BaseModel, Base): """ The city class, contains state ID and name """ - state_id = "" - name = "" + __tablename__ = 'cities' + name = Column(String(128), nullable=False) + state_id = Column(String(60), ForeignKey('states.id'), nullable=False) diff --git a/models/engine/db_storage.py b/models/engine/db_storage.py new file mode 100755 index 000000000000..d961939ffec8 --- /dev/null +++ b/models/engine/db_storage.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Defines a new engine that uses SQLAlchemy""" +import os +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, scoped_session + + +class DBStorage: + """DBStorage Engine running on SQLAlchemy""" + + __engine = None + __session = None + + def __init__(self): + """class constructor for DBStorage""" + + credentials = ['HBNB_MYSQL_USER', 'HBNB_MYSQL_PWD', + 'HBNB_MYSQL_HOST', 'HBNB_MYSQL_DB'] + env = [os.environ.get(c) for c in credentials] + e = 'mysql+mysqldb://{}:{}@{}/{}'.format(*env[:]) + self.__engine = create_engine(e, pool_pre_ping=True) + Session = sessionmaker(bind=self.__engine) + self.__session = Session() + + # drop all tables if the environment variable + # HBNB_ENV is equal to test + if os.environ.get('HBNB_ENV') == 'test': + from models.base_model import Base + Base.metadata.drop_all(self.__engine) + + + def all(self, cls=None): + """Queries the current database session (self.__session) + for all objects depending of the class name (argument cls)""" + from models.user import User + from models.state import State + from models.city import City + from models.amenity import Amenity + from models.place import Place + from models.review import Review + + class_list = [User, State, City, Amenity, Place, Review] + objs = {} + if cls is not None: + for obj in self.__session.query(cls).all(): + objs.update({obj.to_dict()['__class__'] + '.' + obj.id: obj}) + else: + for class_item in class_list: + for obj in self.__session.query(class_item).all(): + objs.update({obj.to_dict()['__class__'] + '.' + obj.id: obj}) + return objs + + def new(self, obj): + """Add obj to the current database session""" + self.__session.add(obj) + + def save(self): + """Commit all changes of the current database session""" + self.__session.commit() + + def delete(self, obj=None): + """Delete from the current database session obj if not None""" + if obj is not None: + self.__session.delete(obj) + + def reload(self): + """Create all tables in the database + """ + from models.user import User + from models.state import State + from models.city import City + from models.amenity import Amenity + from models.place import Place + from models.review import Review + from models.base_model import Base + + Base.metadata.create_all(self.__engine) + Session = sessionmaker(bind=self.__engine, expire_on_commit=False) + self.__session = scoped_session(Session) diff --git a/models/state.py b/models/state.py index 583f041f07e4..d6fa322ec283 100644 --- a/models/state.py +++ b/models/state.py @@ -1,8 +1,17 @@ #!/usr/bin/python3 """ State Module for HBNB project """ -from models.base_model import BaseModel +from models.base_model import BaseModel, Base +from sqlalchemy import Column, String +from sqlalchemy.orm import relationship -class State(BaseModel): +class State(BaseModel, Base): """ State class """ - name = "" + __tablename__ = 'states' + name = Column(String(128), nullable=False) + cities = relationship('City', cascade='all, delete', backref='state') + + @property + def cities(self): + """A getter for the attribute cities""" + return [city for city in self.cities if city.state_id == self.id]