0

I am trying to run a test but I continue to get the following error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-43-6662b1c84945> in <module>
     25 
     26 for i in animal_data:
---> 27     a.create(i)
     28 
     29 

TypeError: create() missing 1 required positional argument: 'data'

I am thinking I am not initializing the class...but I am unsure how to do this properly. I am fairly new at this, so any help is appreciated. Here is the rest of the tester code:

from animal_shelter import AnimalShelter

a = AnimalShelter
username = "aacuser"
password = "Mulligan!23"

a.__init__(a, username, password)
animal_data = [
    {
        "name":"Finn",
        "type":"dog"
    },
    {
        "name":"Max",
        "type":"cat"
    },
    {
        "name":"Cooper",
        "type":"dog"
    },
    {
        "name":"Mulligan",
        "type":"dog"
    }
]

for i in animal_data:
    a.create(i)


    
dogs = a.read( {"type":"dog"}  )
for dog in dogs:
    print(dog)

Here is the original file I am pulling from:

from pymongo import MongoClient
from bson.objectid import ObjectId

class AnimalShelter(object):
    """ CRUD operations for Animal collection in MongoDB """

    def __init__(self, username, password):
        # Initializing the MongoClient. This helps to 
        # access the MongoDB databases and collections. 
        if username and password:
            self.client = MongoClient('mongodb://%s:%s@localhost:53937' % (username,password))
        else:
            self.client = MongoClient('mongodb://localhost:53937')
            self.database = self.client['AAC']

# Complete this create method to implement the C in CRUD.
    def create(self, data):
        if data is not None:
            insert = self.database.animals.insert(data)  # data should be dictionary 
            if insert!=0:
                return True
            else:
                return False           
        else:
            raise Exception("Nothing to save, because data parameter is empty")


    # Create method to implement the R in CRUD.
    def read(self,criteria=None):

        # If data applicable, it will return all rows which match criteria
        if criteria:
         # {'_id':False}, no ID will be placed in row(s)       
            
            data = self.database.animals.find(criteria,{"_id":False})
        else: 
            data = self.database.animals.find( {} , {"_id":False})

        return data
    
        # Create method to implement the C in CRUD
    def update(self, data, newData):
        if data is not None:
            return self.AAC.animals.update_one(data, {'$set': newData})

        else:
            print("Nothing to update, because data parameter is empty")
            return False

       
    # Create method to implement the D in CRUD
    def delete(self, data):
        if data is not None:
            return self.AAC.animals.delete_one(data)
            print("data deleted")
        else:
            return False

I also feel like my indentations are off, so this may another issue.

  • 3
    I’m thinking you want `a = AnimalShelter(username, password)` – rv.kvetch Oct 17 '21 at 23:27
  • Note that the `self` is automatically provided to instance methods, so you’d never need to pass it in yourself. The same with the `cls` parameter for class methods. – rv.kvetch Oct 17 '21 at 23:29
  • @rv.kvetch when I used a = AnimalShelter(username, password) ... it gave me an error saying I was missing 3 positional arguments. Instead of the 1 I have now. – sarahprince23 Oct 17 '21 at 23:32
  • In Python 3, I’d also suggest having it like `class AnimalShelter:` - note that subclassing from `object` is implicit is 3.x and you can omit it if desired. – rv.kvetch Oct 17 '21 at 23:32
  • 1
    @sarahprince23 Hmm.. that’s odd. Are you sure the constructor for AnimalShelter is defined like `def __init__(self, username, password)`? – rv.kvetch Oct 17 '21 at 23:37
  • 1
    As rv.kvetch already stated, you need to write the first script a bit different. If you initialize a class like this `a = AnimalShelter(username, password)` python calls `__init__` - no need to do it manually. Also you don't need to give `a` as self - python does that for you aswell / `self` is pretty much like `this` in java/c. – KH241 Oct 18 '21 at 00:05
  • Please provide a [mre]. Almost all of the `AnimalShelter` code seems to be irrelevant to the problem, like the database connection and the other methods besides `create` and `__init__`. – wjandrea Oct 18 '21 at 04:21

1 Answers1

0

The problem is that you're not creating a class instance. These lines are totally wrong:

a = AnimalShelter  # This is just an alias
a.__init__(a, username, password)  # treats the class like an instance of itself

What you want to do is this:

a = AnimalShelter(username, password)

This creates a new AnimalShelter instance and calls AnimalShelter.__init__() with the instance as the first parameter, self.


Note: As a rule of thumb, don't call __dunder__ methods manually. Most of them have entry points that add functionality, like for example, len() will validate the output of __len__(). That said, there are cases you'll need to call them directly, mostly when working with class internals, like for example, you'll often need to call super().__init__() when subclassing.

wjandrea
  • 28,235
  • 9
  • 60
  • 81