importing class and its function from another file - python

I am having little problem with importing classes in python. My work flow goes like this
index.py
class Template:
def header():
def body():
def form():
def footer():
display.py
I want to call function header(), body() and footer () in my display.py page. Will anyone make me clear about this issue in python. Thanks for your concern.
Index file--- [Index.py][1]
[1]: http://pastebin.com/qNB53KTE and display.py -- "http://pastebin.com/vRsJumzq"

What have you tried? The following would be normal way of using methods of Template class after import.
from index import Template
t = Template()
t.header()
t.body()
t.footer()
ETA: at the end of your index.py file (lines 99-105) you're calling all the functions from the above-defined Template class. That's why you're seeing duplicates.

At the bottom of your index file you create a HtmlTemplate object and call all the methods on it. Since this code is not contained in any other block, it gets executed when you import the module. You either need to remove it or check to see if the file is being run from the command line.
if __name__ == "__main__":
objx=HtmlTemplate()
objx.Header()
objx.Body()
objx.Form()
objx.Footer()
objx.CloseHtml()

Edit: Okay, I see what your problem is, given your code.
You're calling the following:
## Calling all the functions of the class template with object (objx)
objx=HtmlTemplate()
objx.Header()
objx.Body()
objx.Form()
objx.Footer()
objx.CloseHtml()
And then in your display.py:
t = HtmlTemplate()
t.Header()
t.Body()
See how Body() gets called twice?
As a footnote, you should use lowercase for method names, and Capital words for classes as you're doing now. It's a good convention. I greatly recommend it.
You should simply construct the object once in display.py and call all the methods.

I am not sure if I understand you correctly, but I believe you are asking how to import the template class in another script. The import statement is what you need:
from index import template
foo = template()
foo.header()
foo.body()
foo.footer()

You have the following code at the top and the bottom of index.py:
cgitb.enable()
print 'Content-type: text/html\n\n'
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/msa.css\" >"
# [...]
## Calling all the functions of the class template with object (objx)
objx=HtmlTemplate()
# [...]
objx.CloseHtml()
This will be called each time you import index.
To prevent this happening, put it in a block thus:
if __name__ == '__main__':
cgitb.enable()
print 'Content-type: text/html\n\n'
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/msa.css\" >"
# [...]
## Calling all the functions of the class template with object (objx)
objx=HtmlTemplate()
# [...]
objx.CloseHtml()
...or better still put this code functions that can be called from elsewhere.

The below solution worked for me:
class1(unittest.TestCase):
def method1(self)
class2(unittest.TestCase):
def method2(self):
instance_name = class1("method1")
instance_name.method1()

Related

no value for argument self in unbound method call

Thanks for reading this. I've spent the past 48 hours trying to get this code to work. First of all I must disclose that this is for a college assignment. I'm not looking for any assistance or comment on how I might 'gain' in the assignment, I just need to figure out what I'm doing wrong. I have googled the issue and I've read through tutorials on classes and I do feel like I understand them and have got the examples to work. This one issue is stumping me.
So, I have a class which will read a database as follows:
import mysql.connector
import pandas as pd
class DAOdv:
#dbConn=mysql.connector.connect()
def __init__(self):
# import the config file
config=pd.read_csv('./files/config.ini')
dbName=config.iloc[int(config[config['item']=='databaseName'].index[0])]['setting']
uname=config.iloc[int(config[config['item']=='username'].index[0])]['setting']
hst=config.iloc[int(config[config['item']=='host'].index[0])]['setting']
prt=config.iloc[int(config[config['item']=='port'].index[0])]['setting']
# create the connection
self.dbConn=mysql.connector.connect(
host=hst,
database=dbName,
port=prt,
username=uname,
password='' # no password on Server as yet
)
def allClients(self):
cursor=self.dbConn.cursor()
sSQL = 'SELECT * FROM clients'
cursor.execute(sSQL)
results=cursor.fetchall()
return results
daoDV=DAOdv()
and the 'server' code which is:
from flask import Flask
from daoDV import DAOdv
app=Flask(__name__, static_url_path='',static_folder='')
# curl "http://127.0.0.1:5000/clients"
#app.route('/clients')
def getAll():
results=DAOdv.allClients()
return results
In python, the second last line above, DAOdv is underlined in red and hovering over it produces the message "no value for argument self in unbound method call"
What am I doing wrong? I'm assuming the error is in the class?? but I can't figure out what.
Many thanks for your help with this.
Seamus
DAOdv is the class itself, not the instantiated object which you create at the end with: daoDV=DAOdv().
Change your server code to:
from daoDV import daoDV # note the capitalization - we're importing the object here
#(...)
results = daoDV.allClients()
Your method allClients() is an instance method, not a class method.
That's why you should call it like:
results=DAOdv().allClients()
Methods can be an instance or class method.
Class methods are methods which have #classmethod decorator.

Mock flask.request in python nosetests

I'm writing test cases for code that is called via a route under Flask. I don't want to test the code by setting up a test app and calling a URL that hits the route, I want to call the function directly. To make this work I need to mock flask.request and I can't seem to manage it. Google / stackoverflow searches lead to a lot of answers that show how to set up a test application which again is not what I want to do.
The code would look something like this.
somefile.py
-----------
from flask import request
def method_called_from_route():
data = request.values
# do something with data here
test_somefile.py
----------------
import unittest
import somefile
class SomefileTestCase(unittest.TestCase):
#patch('somefile.request')
def test_method_called_from_route(self, mock_request):
# want to mock the request.values here
I'm having two issues.
(1) Patching the request as I've sketched out above does not work. I get an error similar to "AttributeError: 'Blueprint' object has no attribute 'somefile'"
(2) I don't know how to exactly mock the request object if I could patch it. It doesn't really have a return_value since it isn't a function.
Again I can't find any examples on how to do this so I felt a new question was acceptable.
Try this
test_somefile.py
import unittest
import somefile
import mock
class SomefileTestCase(unittest.TestCase):
def test_method_called_from_route(self):
m = mock.MagicMock()
m.values = "MyData"
with mock.patch("somefile.request", m):
somefile.method_called_from_route()
unittest.main()
somefile.py
from flask import request
def method_called_from_route():
data = request.values
assert(data == "MyData")
This is going to mock the entire request object.
If you want to mock only request.values while keeping all others intact, this would not work.
A few years after the question was asked, but this is how I solved this with python 3.9 (other proposed solutions stopped working with python 3.8 see here). I'm using pytest and pytest-mock, but the idea should be the same across testing frameworks, as long as you are using the native unittest.mock.patch in some capacity (pytest-mock essentially just wraps these methods in an easier to use api). Unfortunately, it does require that you set up a test app, however, you do not need to go through the process of using test_client, and can just invoke the function directly.
This can be easily handled by using the Application Factory Design Pattern, and injecting application config. Then, just use the created app's .test_request_context as a context manager to mock out the request object. using .test_request_context as a context manager, gives everything called within the context access to the request object. Here's an example below.
import pytest
from app import create_app
#pytest.fixture
def request_context():
"""create the app and return the request context as a fixture
so that this process does not need to be repeated in each test
"""
app = create_app('module.with.TestingConfig')
return app.test_request_context
def test_something_that_requires_global_request_object(mocker, request_context):
"""do the test thing"""
with request_context():
# mocker.patch is just pytest-mock's way of using unittest.mock.patch
mock_request = mocker.patch('path.to.where.request.is.used')
# make your mocks and stubs
mock_request.headers = {'content-type': 'application/json'}
mock_request.get_json.return_value = {'some': 'json'}
# now you can do whatever you need, using mock_request, and you do not
# need to remain within the request_context context manager
run_the_function()
mock_request.get_json.assert_called_once()
assert 1 == 1
# etc.
pytest is great because it allows you to easily setup fixtures for your tests as described above, but you could do essentially the same thing with UnitTest's setUp instance methods. Happy to provide an example for the Application Factory design pattern, or more context, if necessary!
with help of Gabrielbertouinataa on this article: https://medium.com/#vladbezden/how-to-mock-flask-request-object-in-python-fdbc249de504:
code:
def print_request_data():
print(flask.request.data)
test:
flask_app = flask.Flask('test_flask_app')
with flask_app.test_request_context() as mock_context:
mock_context.request.data = "request_data"
mock_context.request.path = "request_path"
print_request_data()
Here is an example of how I dealt with it:
test_common.py module
import pytest
import flask
def test_user_name(mocker):
# GIVEN: user is provided in the request.headers
given_user_name = "Some_User"
request_mock = mocker.patch.object(flask, "request")
request_mock.headers.get.return_value = given_user_name
# WHEN: request.header.get method is called
result = common.user_name()
# THEN: user name should be returned
request_mock.headers.get.assert_called_once_with("USERNAME", "Invalid User")
assert result == given_user_name
common.py module
import flask
def user_name():
return flask.request.headers.get("USERNAME", "Invalid User")
What you're trying to do is counterproductive. Following the RFC 2616 a request is:
A request message from a client to a server includes, within the first line of that message, the method to be applied to the resource, the identifier of the resource, and the protocol version in use.
Mocking the Flask request you need to rebuild its structure, what certainly, you will not to want to do!
The best approach should be use something like Flask-Testing or use some recipes like this, and then, test your method.

Python mock patch doesn't work as expected for public method

I'm trying to patch a public method for my flask application but it doesn't seem to work.
Here's my code in mrss.feed_burner
def get_feed(env=os.environ):
return 'something'
And this is how I use it
#app.route("/feed")
def feed():
mrss_feed = get_feed(env=os.environ)
response = make_response(mrss_feed)
response.headers["Content-Type"] = "application/xml"
return response
And this is my test which it's not parsing.
def test_feed(self):
with patch('mrss.feed_burner.get_feed', new=lambda: '<xml></xml>'):
response = self.app.get('/feed')
self.assertEquals('<xml></xml>', response.data)
I believe your problem is that you're not patching in the right namespace. See where_to_patch documentation for unittest.mock.patch.
Essentially, you're patching the definition of get_feed() in mrss.feed_burner but your view handler feed() already has a reference to the original mrss.feed_burner.get_feed(). To solve this problem, you need to patch the reference in your view file.
Based on your usage of get_feed in your view function, I assume you're importing get_feed like so
view_file.py
from mrss.feed_burner import get_feed
If so, you should be patching view_file.get_feed like so:
def test_feed(self):
with patch('view_file.get_feed', new=lambda: '<xml></xml>'):
...

redirect while passing arguments

In flask, I can do this:
render_template("foo.html", messages={'main':'hello'})
And if foo.html contains {{ messages['main'] }}, the page will show hello. But what if there's a route that leads to foo:
#app.route("/foo")
def do_foo():
# do some logic here
return render_template("foo.html")
In this case, the only way to get to foo.html, if I want that logic to happen anyway, is through a redirect:
#app.route("/baz")
def do_baz():
if some_condition:
return render_template("baz.html")
else:
return redirect("/foo", messages={"main":"Condition failed on page baz"})
# above produces TypeError: redirect() got an unexpected keyword argument 'messages'
So, how can I get that messages variable to be passed to the foo route, so that I don't have to just rewrite the same logic code that that route computes before loading it up?
You could pass the messages as explicit URL parameter (appropriately encoded), or store the messages into session (cookie) variable before redirecting and then get the variable before rendering the template. For example:
from flask import session, url_for
def do_baz():
messages = json.dumps({"main":"Condition failed on page baz"})
session['messages'] = messages
return redirect(url_for('.do_foo', messages=messages))
#app.route('/foo')
def do_foo():
messages = request.args['messages'] # counterpart for url_for()
messages = session['messages'] # counterpart for session
return render_template("foo.html", messages=json.loads(messages))
(encoding the session variable might not be necessary, flask may be handling it for you, but can't recall the details)
Or you could probably just use Flask Message Flashing if you just need to show simple messages.
I found that none of the answers here applied to my specific use case, so I thought I would share my solution.
I was looking to redirect an unauthentciated user to public version of an app page with any possible URL params. Example:
/app/4903294/my-great-car?email=coolguy%40gmail.com to
/public/4903294/my-great-car?email=coolguy%40gmail.com
Here's the solution that worked for me.
return redirect(url_for('app.vehicle', vid=vid, year_make_model=year_make_model, **request.args))
Hope this helps someone!
I'm a little confused. "foo.html" is just the name of your template. There's no inherent relationship between the route name "foo" and the template name "foo.html".
To achieve the goal of not rewriting logic code for two different routes, I would just define a function and call that for both routes. I wouldn't use redirect because that actually redirects the client/browser which requires them to load two pages instead of one just to save you some coding time - which seems mean :-P
So maybe:
def super_cool_logic():
# execute common code here
#app.route("/foo")
def do_foo():
# do some logic here
super_cool_logic()
return render_template("foo.html")
#app.route("/baz")
def do_baz():
if some_condition:
return render_template("baz.html")
else:
super_cool_logic()
return render_template("foo.html", messages={"main":"Condition failed on page baz"})
I feel like I'm missing something though and there's a better way to achieve what you're trying to do (I'm not really sure what you're trying to do)
You can however maintain your code and simply pass the variables in it separated by a comma: if you're passing arguments, you should rather use render_template:
#app.route("/baz")
def do_baz():
if some_condition:
return render_template("baz.html")
else:
return render_template("/foo", messages={"main":"Condition failed on page baz"})

Why do I get TypeError: get() takes exactly 2 arguments (1 given)? Google App Engine

I have been trying and trying for several hours now and there must be an easy way to retreive the url. I thought this was the way:
#from data.models import Program
import basehandler
class ProgramViewHandler(basehandler.BaseHandler):
def get(self,slug):
# query = Program.all()
# query.filter('slug =', fslug)
self.render_template('../presentation/program.html',{})
Whenever this code gets executed I get this error on the stacktrace:
appengine\ext\webapp__init__.py", line 511, in call
handler.get(*groups)
TypeError: get() takes exactly 2 arguments (1 given)
I have done some debugging, but this kind of debugging exceeds my level of debugging. When I remove the slug from def get(self,slug) everything runs fine.
This is the basehandler:
import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
class BaseHandler(webapp.RequestHandler):
def __init__(self,**kw):
webapp.RequestHandler.__init__(BaseHandler, **kw)
def render_template(self, template_file, data=None, **kw):
path = os.path.join(os.path.dirname(__file__), template_file)
self.response.out.write(template.render(path, data))
If somebody could point me in the right direction it would be great! Thank you! It's the first time for me to use stackoverflow to post a question, normally I only read it to fix the problems I have.
You are getting this error because ProgramViewHandler.get() is being called without the slug parameter.
Most likely, you need to fix the URL mappings in your main.py file. Your URL mapping should probably look something like this:
application = webapp.WSGIApplication([(r'/(.*)', ProgramViewHandler)])
The parenthesis indicate a regular expression grouping. These matched groups are passed to your handler as arguments. So in the above example, everything in the URL following the initial "/" will be passed to ProgramViewHandler.get()'s slug parameter.
Learn more about URL mappings in webapp here.
If you do this:
obj = MyClass()
obj.foo(3)
The foo method on MyClass is called with two arguments:
def foo(self, number)
The object on which it is called is passed as the first parameter.
Maybe you are calling get() statically (i.e. doing ProgramViewHandler.get() instead of myViewHandlerVariable.get()), or you are missing a parameter.

Categories

Resources