pythonc9.iocodeanywhere

Codeanywhere error on script vs C9.io working fine


I migrated my workspace from C9.io to Codeanywhere, and on C9.io my scripts worked fine; my scripts being a python terminal game/app that I've been working on. I have a test script to run the functions I've created so far, and the player.py file for creating different classes and player objects, with saving, loading, etc. On C9.io, this is the output.

Strength: 15
Agility: 10
Critical Chance: 25
Spell Power: 15
Intellect: 5
Speed: 5
---
Health: 100/100
Stamina: 10
Armor: 20
Resilience: 2
---
Strength: 20.25
Agility: 10
Critical Chance: 43.75
Spell Power: 15
Intellect: 5
Speed: 4.0
---
Health: 100/100
Stamina: 7.5
Armor: 16.0
Resilience: 1.4
---
# more test info regarding other scripts

But when I run the test script on Codeanywhere, this is what happens.

Strength: 15
Strength: 15
Agility: 10
Critical Chance: 25
Spell Power: 15
Intellect: 5
Speed: 5
---
Health: 100/100
Stamina: 10
Armor: 20
Resilience: 2
---
Traceback (most recent call last):
  File "test.py", line 7, in <module>
    player2 = BerserkerCharacter('Jon', 'Snow')
  File "/home/cabox/workspace/grimside/assets/player.py", line 93, in __init__
    super().__init__()
TypeError: super() takes at least 1 argument (0 given)

I've tried putting self infront of the super().__init__(), as well as throwing self in the argument, and I'm not that skilled in Python so I don't know what to fix. Here's my scripts.

test.py

from assets import *
player = BaseCharacter()
player.show_player_stats("offensive")
print('---')
player.show_player_stats("defensive")
print('---')
player2 = BerserkerCharacter('Jon', 'Snow')
player2.show_player_stats("offensive")
print('---')
player2.show_player_stats("defensive")
print('---')
#more test info regarding other scripts

player.py

#import functions used by script
#random is a math function used for creating random integers
import random
#pickle is for saving/loading/writing/reading files
import pickle
#sys is for system-related functions, such as quitting the program
import sys
#create a class called BaseCharacter, aka an Object()
class BaseCharacter:
    #define what to do when the object is created, or when you call player = BaseCharacter()
    def __init__(self):
        #generate all the stats. these are the default stats, not necessarily used by the final class when player starts to play.
        #round(random.randint(25,215) * 2.5) creates a random number between 25 and 215, multiplies it by 2.5, then roudns it to the nearest whole number
        self.gold = round(random.randint(25, 215) * 2.5)
        self.currentHealth = 100
        self.maxHealth = 100
        self.stamina = 10
        self.resil = 2
        self.armor = 20
        self.strength = 15
        self.agility = 10
        self.criticalChance = 25
        self.spellPower = 15
        self.intellect = 5
        self.speed = 5
        self.first_name = 'New'
        self.last_name = 'Player'
        self.desc = "Base Description"
        self.class_ = None
        self.equipment = [None] * 6
    #define the function to update stats when the class is set
    def updateStats(self, attrs, factors):
        #try to do a function
        try:
            #iterate, or go through data
            for attr, fac in zip(attrs, factors):
                val = getattr(self, attr)
                setattr(self, attr, val * fac)
        #except an error with a value given or not existing values
        except:
            raise("Error updating stats.")
    #print out the stats when called
    #adding the category line in between the ( ) makes it require a parameter when called
    def show_player_stats(self, category):
        #if the input for category is put into all upper case and it says "OFFENSIVE", do this
        if category.upper() == "OFFENSIVE":
            #print the stats. {} means a filler, and the .format makes it print the value based off the variables, in order; strength: {} will print strength: 15 if strength = 15
            print("Strength: {}\nAgility: {}\nCritical Chance: {}\nSpell Power: {}\nIntellect: {}\nSpeed: {}".format(self.strength, self.agility, self.criticalChance, self.spellPower, self.intellect, self.speed))
        #or, if the input for category is put into all upper case and it says "DEFENSIVE", do this
        elif category.upper() == "DEFENSIVE":
            #same as before
            print("Health: {}/{}\nStamina: {}\nArmor: {}\nResilience: {}".format(self.currentHealth, self.maxHealth, self.stamina, self.armor, self.resil))
        elif category.upper() == "INFO":
            print("Name: {} {}\nGold: {}\nClass: {}\nClass Description: {}".format(self.first_name, self.last_name, self.gold, self.class_, self.desc))
        #if its anything else
        else:
            #raise an error, formating the Category {} with the category input given
            raise KeyError("Category {} is not a valid category! Please choose Offensive or Defensive.".format(category))
    #save progress to a local file using this function
    def save(self):
        #opening a new file with the filename being put as FirstName_LastName (example New_Player.txt) with read and write permissions as variable f
        with open(self.first_name+'_'+self.last_name, 'wb') as f:
            #use pickle script to dump the information in stats/equipment/etc to a local save file
            pickle.dump(self, f)
    #declare as a static method
    @staticmethod
    #load save file with given name when called
    def load(filename):
        #open the save file with name given as a read only file as variable f
        with open(filename, 'rb') as f:
            #return the stats and update them as needed
            return pickle.load(f)
#classes
#create the warrior class, based off of the base character which automatically uses all the variables, functions, and data from BaseCharacter
class WarriorCharacter(BaseCharacter):
    #define data when initialized, or the Object is created
    def __init__(self, first_name, last_name):
        super().__init__()
        #update the class value since its a copy of BaseCharacter
        self.class_ = 'Warrior'
        #update the first name
        self.first_name = first_name
        #update the last name
        self.last_name = last_name
        #update description value
        self.desc = 'You were  born a protector. You grew up to bear a one-handed weapon and shield, born to prevent harm to others. A warrior is great with health, armor, and defense.'
        #update the values Stamina, Resil, And Armor by multipling current value by 1.25, 1.25, and 1.35.
        self.updateStats(['stamina', 'resil', 'armor', 'strength', 'speed'], [1.25, 1.25, 1.35, 0.75, 0.40])

class BerserkerCharacter(BaseCharacter):
    def __init__(self, first_name, last_name):
        super().__init__()
        self.class_ = 'Berserker'
        self.first_name = first_name
        self.last_name = last_name
        self.desc = 'A natural viking at heart, you are vicious and short-tempered. Your brute strength and anger allows you to dual wield two-handed weapons. Anyone in your way is an obstacle begging to be obliterated. While suffering defensively, you are enhanced offensively.'
        self.updateStats(['stamina', 'armor', 'resil', 'strength', 'criticalChance', 'speed'], [0.75, 0.80, 0.70, 1.35, 1.75, 0.80])

Solution

  • Based on the discussion in the comments:

    It turns out that the container (incorrectly) runs Python 2.7 by default, instead of 3.4 as stated in the description.

    The simplest fix is to make the calls to super valid for both versions by specifying the parameters, e.g.:

    class WarriorCharacter(BaseCharacter):
        #define data when initialized, or the Object is created
        def __init__(self, first_name, last_name):
            super(WarriorCharacter, self).__init__()
    

    And

    class BerserkerCharacter(BaseCharacter):
        def __init__(self, first_name, last_name):
            super(BerserkerCharacter, self).__init__()