python3 function not defined even though it is - python

when I try to call the changeProfile function, I keep getting the error "getAuthCode is not defined" even though it is clearly defined. Why do I keep getting this error? What am I doing wrong? It used to work from what I remember, but now all of a sudden it doesn't. Any help would be appreciated :)
import os,re,json,socket,random,select,threading,time,sys
import urllib.request as urlreq
from urllib.request import quote,unquote
import urllib.parse
class miscellanous:
"""Main class."""
def __init__():
"""What to do on initalizing."""
pass
def getAuthCode(u, p):
"""Get authentification code from username and password specified."""
try:
data=urllib.request.urlopen('http://chatango.com/login',urllib.parse.urlencode({'user_id': u, 'password': p, 'storecookie': 'on', 'checkerrors': 'yes'}).encode()).headers
except Exception as e: print("Error: Auth request: %s" % e)
for x, y in data.items():
if x.lower() == 'set-cookie':
returned = re.compile(r"auth\.chatango\.com ?= ?([^;]*)", re.IGNORECASE).search(y)
if returned:
ret = returned.group(1)
if ret == "": raise ValueError("Error: Unable to get auth: Error in username/password.")
return ret
def createAccount(u, p):
"""Create an account with the username and password specified."""
try:
resp=urllib.request.urlopen("http://chatango.com/signupdir", urllib.parse.urlencode({"email": "accmaker"+str(random.randrange(1,1000000000000))+"#hotmail.com", "login": u, "password": p, "password_confirm": p, "storecookie": "on", "checkerrors": "yes"}).encode())
fu=str(resp.read())
resp.close()
if "screen name has been" in fu: r = "Error: User could not be created: Already exists."
else: r = "The user was created. If it didn't work, try another username."
return r
except: return "Error: Invalid or missing arguments."
def createGroup(u, p, g, d="Description.", m="Owner message."):
"""Creates a group with the username, password, group name, description and owner message specified."""
try:
g=g.replace(" ","-")
resp=urllib.request.urlopen("http://chatango.com/creategrouplogin",urllib.parse.urlencode({"User-Agent": "Mozilla/5.0", "uns": "0", "p": p, "lo": u, "d": d, "u": g, "n": m}).encode())
fu=str(resp.read())
resp.close()
if "groupexists" in fu: r = "Error: Group could not be created: Already exists."
else: r = "The group was created. If it didn't work, try another group name. Click <a href='http://%s.chatango.com/' target='_blank'>[[here]]<a> to get to the new group."
return r
except: return "Error: Invalid or missing arguments."
def changeProfile(u, p, m="Default", e="accmaker"+str(random.randrange(1,1000000000000))+"#hotmail.com", l="Norway", g="M", a="18"):
try:
resp = urlreq.urlopen('http://'+u.lower()+'.chatango.com/updateprofile?&d&pic&s='+getAuthCode(u, p), urllib.parse.urlencode({"show_friends": "checked", "dir": "checked", "checkerrors": "yes", "uns": "1", "line": m, "email": e, "location": l, "gender": g, "age": a}).encode())
return "The profile change was successful."
except Exception as e:
return "%s" % e
def checkOnlineStatus(u):
"""Check if the predefined username is online or offline."""
if "Chat with" in urlreq.urlopen("http://"+u.lower()+".chatango.com").read().decode(): return '<b><font color="#00ff00">Online</font></b>'
else: return "<b><font color='#ff0000'>Offline</font></b>"
resp.close()
def checkUserGender(u):
"""Get the gender for the predefined username."""
resp=urlreq.urlopen("http://st.chatango.com/profileimg/%s/%s/%s/mod1.xml" % (u.lower()[0], u.lower()[1], u.lower()))
try: ru=re.compile(r'<s>(.*?)</s>', re.IGNORECASE).search(resp.read().decode()).group(1)
except: ru="?"
ret=unquote(ru)
resp.close()
if ret=="M": r="Male"
elif ret=="F": r="Female"
elif ret=="?": r="Not specified"
return r
def changeBackGround(u, p, x, transparency=None):
"""Update the user's bg using the predefined username, password and bg color."""
color=quote(x.split()[0])
try: image=x.split()[1]
except: image=None
if color and len(color)==1:
color=color*6
if color and len(color)==3:
color+=color
elif color and len(color)!=6:
return False
if transparency!=None and abs(transparency)>1:
transparency = abs(transparency) / 100
data=urllib.request.urlopen("http://fp.chatango.com/profileimg/%s/%s/%s/msgbg.xml" % (u[0], u[1], u.lower())).read().decode()
data=dict([x.replace('"', '').split("=") for x in re.findall('(\w+=".*?")', data)[1:]])
data["p"]=p
data["lo"]=u
if color: data["bgc"] = color
if transparency!=None: data["bgalp"]=abs(transparency) * 100
if image!=None: data["useimg"]=1 if bool(image) else 0
data12=urllib.parse.urlencode(data)
data13=data12.encode()
der=urllib.request.urlopen("http://chatango.com/updatemsgbg", data13).read()
def checkIfGroupExists(g):
"""Check if the predefined group exists."""
i = urlreq.urlopen('http://'+g+'.chatango.com').read().decode()
if '<table id="group_table"' in i: return True#"This chat does exist!"
else: return False#"This chat doesn't exist."
i.close()

All of the functions you've shown are part of the miscellaneous class, so to access them, you need to prefix them with the class name. To refer to the getAuthCode function, you'd use miscellaneous.getAuthCode.
But, it doesn't seem like you should really be using a class here. You never create instances of miscellaneous, nor are the functions set up to be run as methods. So, probably the right answer is to get rid of the class miscellaneous: declaration at the top of the file, and then to unindent all the functions one level.
(Note, in Python 2 you'd have an additional issue if you kept the class: Unbound methods required that their first argument be an instance of their class (or a subclass). In that situation, you'd need to use the staticmethod decorator on any functions that did not expect to get an instance at all.)

Functions within a Python class are called methods. They normally take a self parameter before their other parameters. Furthermore, methods cannot "see" each other directly; you need to call them as self.method(args) instead of just method(args).

Related

Trying to compare 3 wtforms fields with custom functions and geting recursion problem

I have 3 fields that I want to compare salary "from" field and "to" field and also there is fixed salary field. I have no idea how to do it, since there is no documentation how to do it, so i created custom function that look to each other and trying to se if they have a value.
def validate_salarylow(self, salarylow):
if self.validate_salary_fixed(self.salary_fixed) != "":
salarylow.data = int(0)
else:
try:
salarylow.data = int(salarylow.data)
except:
raise ValidationError("value is not a number")
return salarylow.data
def validate_salary_high(self, salary_high):
if self.validate_salary_fixed(self.salary_fixed) != "":
salary_high.data = int(0)
else:
try:
salary_high.data = int(salary_high.data)
except:
raise ValidationError("value is not a number")
return salary_high.data
def validate_salary_fixed(self, salary_fixed):
if self.validate_salary_high(self.salary_high) != "":
salary_fixed.data = int(0)
try:
salary_fixed.data = int(salary_fixed.data)
except:
raise ValidationError("value is not a number")
return salary_fixed.data
if I don't set if self.validate_salary_high(self.salary_high) != "": everything works fine. but when i set it I'm getting "RecursionError: maximum recursion depth exceeded" error.validate_salary_fixed function looks to validate_salary_high function and vice versa. I'm new in Python and flask and I'm sure there is easy solution, but I cant find it so I would appreciate if anyone could help.
My suggestion is to suppress the error message of the integer field by overwriting it. Thus, the types of the inputs do not have to be converted.
For validation I use two custom validators, one of which checks whether a range or a fixed value has been entered and the second checks the range for its limits. In addition, pre-built validators are used to prohibit negative values.
I'm not sure if you really need the field for the fixed salary, because it is possible to define a fixed value by narrowing the range.
from flask_wtf import FlaskForm
from wtforms import IntegerField
from wtforms.validators import (
NumberRange,
Optional,
StopValidation,
ValidationError
)
class OptionalIntegerField(IntegerField):
def process_data(self, value):
try:
super().process_data(value)
except ValueError:
pass
def process_formdata(self, valuelist):
try:
super().process_formdata(valuelist)
except ValueError:
pass
def validate_salary(form, field):
range_fields = [form.salary_low, form.salary_high]
if all(f.data is None for f in [form.salary_low, form.salary_high, form.salary_fixed]) or \
(form.salary_fixed.data is not None and any(f.data is not None for f in range_fields)) or \
(form.salary_fixed.data is None and any(f.data is None for f in range_fields)):
raise StopValidation('Either state a range from low to high or a fixed salary.')
def validate_salary_range(form, field):
if form.salary_low.data and form.salary_high.data and \
form.salary_low.data > form.salary_high.data:
raise ValidationError('The lower value should be less than or equal to the higher one.')
class SalaryForm(FlaskForm):
salary_low = OptionalIntegerField(
validators=[
validate_salary,
validate_salary_range,
Optional(),
NumberRange(min=0)
]
)
salary_high = OptionalIntegerField(
validators=[
validate_salary,
validate_salary_range,
Optional(),
NumberRange(min=0)
]
)
salary_fixed = OptionalIntegerField(
validators=[
validate_salary,
Optional(),
NumberRange(min=0)
]
)
app = Flask(__name__)
app.secret_key = 'your secret here'
#app.route('/', methods=['GET', 'POST'])
def index():
form = SalaryForm(request.form)
if form.validate_on_submit():
print(form.salary_low.data, ' - ', form.salary_high.data, '||', form.salary_fixed.data)
return render_template('index.html', **locals())
Let's take a look at your code:
Your function validate_salary_high calls validate_salary_fixed.
But when you go to your function validate_salary_fixed it calls validate_salary_high.
So you go back to your function validate_salary_high which calls validate_salary_fixed.
Now in your function validate_salary_fixed, you call validate_salary_high.
Your functions repeatedly call each other over and over again, forever, until your computer eventually throws an error - and this is exactly what is happening to you.
The way to get around this is to remove one of your recursive calls. More specifically you should either
remove your call to validate_salary_fixed in the function validate_salary_high
or remove your call to validate_salary_high in the function validate_salary_fixed
You should chose which function call to remove depending on the goal of your code (which I don't fully understand.) Good luck!

pytest mock function but verify parameters

I have a method with an external API call.
The external API call that takes two parameters (a XML string and number) and if it is successful it creates something in the external system.
def create_stuff(my_number: int,name: str):
try:
new_value = my_number + 5
stuff_xml = '''<?xml version='1.0' encoding='UTF-8'?>
<description>''' + name + '''</description>
<properties/>'''
external_api_call.create_stuff(name, new_value)
return {"status": 'success', "message": "created stuff '" + name}
except Exception as e:
return {"status": 'failure', "message": "error while creating stuff: " + str(e)}
Because I can't reach the external system from the pytest environment and really don't want to create something there just for testing purposes, I decided to mock the external call.
def test_create_stuff(mocker):
mocker.patch(
'path.to.class.external_api_call.create_stuff',
return_value=5
)
assert actual['status'] == 'success'
In the function the external call handles the verification of the parameters (i.e. is the XML structure valid), but if I mock the external call I can't validate if the rest of the function works as designed.
Is there a way to grab the parameters of the external call and validate them?
For example like this:
def test_create_folder_success(credentials_valid,status_succeded, jenkins_extension_mocked):
my_mocker = mocker.patch(
'path.to.class.external_api_call.create_stuff',
return_value=5
)
actual = my_class.create_stuff(my_number=5,name="foo")
xml = xml.etree.ElementTree.parse(my_mocker.name)
value = my_mocker.new_value
assert actual['status'] == 'success'
assert value == 10
assert validate_xml(xml) == True
thank you jonrsharpe and sry for the late response!
with your help I was able to get it woking:
def test_create_folder_success(credentials_valid,status_succeded):
with mock.patch('path.to.class.external_api_call.create_stuff') as my_mocker:
actual = my_class.create_stuff(my_number=5,name="foo")
my_args = my_mocker.call_args
xml = xml.etree.ElementTree.parse(my_args[1])
assert validate_xml(xml) == True
value = my_mocker.new_value
assert actual['status'] == 'success'
assert value == 10

Is it possible to use __init__ values from a class calling another class?

So I have two class that are called:
a.py
import requests
class A:
def __init__(self, parent):
self.parent = parent
self.accessToken = "VeryImportant" <---
def productFeed(self, Country, UserInput):
while True:
try:
else:
params = {
'country': UserInput,
'locale': 'en-{}_{}'.format(UserInput, UserInput)
}
headers = {
'importante': 'Yessir {}'.format(self.accessToken),
}
r = requests.get("URL", params=params, headers=headers, timeout=5)
# -------------------------------------------------------------------------
if r.status_code == 200:
return r.json()
b.py
import lib.vendors.testing.a as testing
class B:
def __init__(self):
self.getClassA = testing.A
def main(self):
country = "GB"
UserInput = "Hello"
print(self.getClassA.productFeed(country, UserInput))
However it seems like I am getting issue on class A: saying TypeError: ProductFeed() missing 1 required positional argument: 'UserInput'
The issue I believe is related to the self - I assume I need to add it into the params inside the self.getClassA.productFeed(country, UserInput) however the issue will be that if I send over the self, it doesn't want to use the self.accessToken from class A in that case and then I am not able to the the correct request.
What I want to do is that if I call self.getClassA.productFeed(country, UserInput)- I want to use the self.accessToken that is in class A instead of needing to send it over
What should I do to be able to do that?
You can choose to use something as static.
If "accessToken" isn't different for every instance of the class A you can define it before the init function. In that way you can read it by using A.accessToken and your program wont crash anymore.
However if accessToken is static, this means that different instances of the class A cannot have different values for accessToken.
You can make the productFeed function static and change the self with anything else. When you call it you have to pass an instance of A as argument
In A class
#staticmethod
def productFeed(instance, Country, UserInput):
while True:
try:
else:
params = {
'country': UserInput,
'locale': 'en-{}_{}'.format(UserInput, UserInput)
}
headers = {
'importante': 'Yessir {}'.format(instance.accessToken),
}
r = requests.get("URL", params=params, headers=headers, timeout=5)
# -------------------------------------------------------------------------
if r.status_code == 200:
return r.json()
in main
def main(self):
country = "GB"
UserInput = "Hello"
print(self.getClassA.productFeed(A(None),country, UserInput))
You are not creating an instance of the A class. You use a direct reference:
testing.A
where you should use
testing.A( ... )
Your code is interpreting the country variable as the self argument because self is not a keyword

Require an option only if a choice is made when using click

When using click I know how to define a multiple choice option. I also know how to set an option as a required one. But, how can I indicate that an option B is required only if the value of option A is foo?
Here's an example:
import click
#click.command()
#click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
#click.option('--filename', type=click.STRING)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
if __name__ == "__main__":
main()
If the output option is stdout, then filename is not needed. However, if the user chooses output to be file, then the other option filename must be provided. Is this pattern supported by click?
At the beginning of the function I can add something like:
if output == 'file' and filename is None:
raise ValueError('When output is "file", a filename must be provided')
But I am interested whether there's a nicer/cleaner solution.
In the particular case of this example, I think an easier method would be to get rid of --output, and simply assume stdout if --filename is not specified and if --filename is specified, then use it instead of stdout.
But assuming this is a contrived example, you can inherit from click.Option to allow hooking into the click processing:
Custom Class:
class OptionRequiredIf(click.Option):
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params['output'] == 'file':
msg = 'Required if --output=file'
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
Using Custom Class:
To use the custom class, pass it as the cls argument to the option decorator like:
#click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
Test Code:
import click
#click.command()
#click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
#click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
main('--output=file'.split())
Results:
Usage: test.py [OPTIONS]
Error: Missing option "--filename". Required if --output=file
You can do the same thing with a custom validation callback:
import click
def required_with_output(ctx, param, value):
if ctx.params.get("output") != "stdout" and value is None:
raise click.BadParameter("--output requires --filename")
return value
#click.command()
#click.option(
"--output",
type=click.Choice(["stdout", "file"]),
default="stdout",
)
#click.option("--filename", callback=required_with_output)
def main(output, filename):
print("output: " + output)
if output == "file":
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
if __name__ == "__main__":
main()
I think this is a little simpler.
I extended the answer by Stephen, and made it more generic:
class OptionRequiredIf(click.Option):
"""
Option is required if the context has `option` set to `value`
"""
def __init__(self, *a, **k):
try:
option = k.pop('option')
value = k.pop('value')
except KeyError:
raise(KeyError("OptionRequiredIf needs the option and value "
"keywords arguments"))
click.Option.__init__(self, *a, **k)
self._option = option
self._value = value
def process_value(self, ctx, value):
value = super(OptionRequiredIf, self).process_value(ctx, value)
if value is None and ctx.params[self._option] == self._value:
msg = 'Required if --{}={}'.format(self._option, self._value)
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
Usage example:
#click.option('--email', type=click.STRING,
help='Settings for sending emails.',
option='output', value='email', cls=OptionRequiredIf)
I was inspired by this answer

Checking to see if multiple ENV variables exist

Is there a more optimal way I can check to see if multiple ENV variables exist with customized exceptions? Perhaps a way to match a group of EVN variables, and then have the exception self-reference the variable name in its output?
if os.environ.get('USERNAME') is not None:
self.username = os.environ.get('USERNAME')
else:
raise CustomException('Environment variable USERNAME not set')
if os.environ.get('PASSWORD') is not None:
self.password = os.environ.get('PASSWORD')
else:
raise CustomException('Environment variable PASSWORD not set')
I am using Python 2.7. Thanks!
You can do something like this:
#
# ENV vars you want to go over
#
env_vars = 'HOME,PATH,NONEXISTS'.split(',')
for evar in env_vars:
# Loop will create it as: self.$evar = os.environ.get(evar)
if evar not in os.environ:
# Will skip: NONEXISTS
continue
# or if you want to raise exception
raise ValueError('Environment variable "%s" was not set' % evar)
# setattr: will create a dynamic attribute for "self"
# self.home = ...
# self.path = ...
# evar.lower() => so we'll have self.home vs self.HOME
setattr(self, evar.lower(), os.environ.get(evar))
In general, just note that you don't need to verify if it's "None" in Python, so
# Replace this
if os.environ.get('USERNAME') is not None:
# With this, the default of get => is None, and None won't pass "if"
if os.environ.get('USERNAME'):
# Will create an exception if USERNAME doesn't exists
if os.environ['USERNAME']
Hope it helps ...
You could always use a loop with a three items list:
for data in [
["USERNAME", "username", CustomException],
["PASSWORD", "password", CustomException]
]:
env_var = os.environ.get(data[0])
if env_var:
setattr(self, data[1], env_var)
else:
# Should work, cannot check due to not having actually Python installed.
raise data[2]("Environment variable %s not set" % data[0])
If you don't like using indexes, you could replace the items by dicts like this to have a more consistent access if you change order:
{"env_var_name": "USERNAME", "attr": "username", "exception_cls": CustomException}
Just put all the environment lookups in a try: block:
try:
self.username= os.environ['USERNAME']
self.password= os.environ['PASSWORD']
except KeyError as e:
raise CustomException('Environment variable {} not set'.format(e.args[0]))

Categories