>>> import module1
>>> dir(module1)
['__builtins__', '__doc__', '__file__', '__name__', '__package__']
I try putting some functions like this to module1 code:
def __dir__(self):
return 'ok'
def __dir__():
return 'ok'
def __dir__(self):
print 'ok'
def __dir__():
print 'ok'
... but nothing of those works. How good writen overwriting dir function should look?
I want something like this:
>>> import module1
>>> dir(module1)
'ok' [or ok]
Your question is asking how to modify the behavior of dir() on module objects, but in your comments you clarified that your ultimate goal is to modify the behavior of help(module). dir works differently on different objects, and I don't believe there is a direct way to change that for a module. It will simply always want to list the attributes of the module being everything in the scope.
What you can do though, is define an __all__ attribute in your module, and specify which attributes should be made public in the help doc:
mymodule
__all__ = ['foo']
foo = 'bar'
class Klass(object):
pass
>>> import mymodule
>>> help(mymodule)
You will see that because Klass was excluded from __all__ it will not be visible in the help.
Also, if you do from mymodule import *, only the foo attribute will be imported:
>>> from mymodule import *
>>> dir()
# ['__builtins__', '__doc__', '__name__', '__package__', 'foo']
Related
Given a uri like /home/ I want to find the view function that this corresponds to, preferably in a form like app.views.home or just <app_label>.<view_func>. Is there a function that will give me this?
You can use the resolve method provided by django to get the function. You can use the __module__ attribute of the function returned to get the app label. This will return a string like project.app.views. So something like this:
from django.urls import resolve
myfunc, myargs, mykwargs = resolve("/hello_world/")
mymodule = myfunc.__module__
In case one needs the class of the view since a class based view is being used one can access the view_class of the returned function:
view_class = myfunc.view_class
From Django 2.0 onward django.core.urlresolvers module has been moved to django.urls.
You will need to do this:
from django.urls import resolve
myfunc, myargs, mykwargs = resolve("/hello_world/")
mymodule = myfunc.__module__
Since Django 1.3 (March 2011) the resolve function in the urlresolvers module returns a ResolverMatch object. Which provides access to all attributes of the resolved URL match, including the view callable path.
>>> from django.core.urlresolvers import resolve
>>> match = resolve('/')
>>> match.func
<function apps.core.views.HomeView>
>>> match._func_path
'apps.core.views.HomeView'
1. Generate a text file with all URLs with corresponding view functions
./manage.py show_urls --format pretty-json --settings=<path-to-settings> > urls.txt
example
./manage.py show_urls --format pretty-json --settings=settings2.testing > urls.txt
2. Look for your URL in the output file urls.txt
{
"url": "/v3/affiliate/commission/",
"module": "api.views.affiliate.CommissionView",
"name": "affiliate-commission",
},
All the others focus on just the module or string representation of the view. However, if you want to directly access the view object for some reason, this could be handy
resolve('the_path/').func.cls
This gives the view object itself, this works on class based view, I haven't tested it on a function based view though.
Based on KillianDS's answer, here's my solution:
from django.core.urlresolvers import resolve
def response(request, template=None, vars={}):
if template is None:
view_func = resolve(request.META['REQUEST_URI'])[0]
app_label = view_func.__module__.rsplit('.', 1)[1]
view_name = view_func.__name__
template = '%s.html' % os.path.join(app_label, view_name)
return render_to_response(template, vars, context_instance=RequestContext(request))
Now you can just call return response(request) at the end of your view funcs and it will automatically load up app/view.html as the template and pass in the request context.
import yaml
class Import_Yaml_Setting():
def __init__(self, path):
self.read_yaml(path)
def read_yaml(self, path):
stream = open(path, 'r')
self.settings = yaml.load(stream)
stream.close()
class MasterDef(Import_Yaml_Setting):
def __init__(self, path):
Import_Yaml_Setting.__init__(self, path)
def function_1():
path = 'path_to_settings\\yaml_file.yaml'
MasterDef(path)
def function_2():
MasterDef.settings
if __name__ == '__main__':
function_1()
function_2()
My plan is it to have a class Import_Yaml_Setting which imports settings from a yaml file. The class MasterDef inherits the class Import_Yaml_Setting.
After 'function_1' calls MasterDef in order to import the settings. I want to do this once in my program. After, I just want to get access to the imported settings
without import them again. This should do function_2.
My problem
I don't know how I have to call MasterDef at the first place. If I would create an instance of MasterDef them I wouldn't have access to this instance in function_2.
Also, I get an error that says MasterDef has no attribute settings.
What would be the right way to do this.
There are a few things incorrect, so lets start with the most obvious.
If you have a class MasterDef, calling MasterDef() creates an instance
of that class. If you don't assign that to a variable, that instance will
immediately disappear.
Doing MasterDef.settings later on could work if the class had a
class attribute or method called settings, but in that case you are not accessing
the settings attribute on an instance.
Typical such global settings are passed around, or implemented as a function object that
does the loading only once, or are made into a global variable (as
shown in the following example). Simplified you would do:
from __future__ import print_function, absolute_import, division, unicode_literals
class MasterDef(object):
def __init__(self):
self.settings = dict(some='setting')
master_def = None
def function_1():
global master_def
if master_def is None:
master_def = MasterDef()
def function_2():
print('master_def:', master_def.settings)
if __name__ == '__main__':
function_1()
function_2()
which gives:
master_def: {'some': 'setting'}
A few notes to the above:
If, for whatever reason, you are doing anything new on Python 2.7
make things more Python3 compatible by including the from
__future__ import as indicated. Even if you are just using the
print function (instead of the outdated print statement). It
will make transitioning easier (2.7 goes EOL in 2020)
Again in 2.7 make your base classes a subclass of object, that
makes it e.g. possible to have properties.
By testing that master_def is None you can invoke function_1 multiple
times
You should also be aware that PyYAML load, as is written in its
documentation, can be unsafe when you don't have full control over
your input. There is seldom need to use load() so use safe_load()
or upgrade to my ruamel.yaml package which implements the newer YAML
1.2 standard (released 2009, so there is no excuse for using PyYAML
that still doesn't support that).
As you also seem to be on Windows (assumed from you using \\), consider using raw strings
where you don't need to escape the backslash, using os.path.join(). I am leaving out
your path part in my full example as I am not on Windows:
from __future__ import print_function, absolute_import, division, unicode_literals
import ruamel.yaml
class Import_Yaml_Setting(object):
def __init__(self, path):
self._path = path # stored in case you want to write out the configuration
self.settings = self.read_yaml(path)
def read_yaml(self, path):
yaml = ruamel.yaml.YAML(typ='safe')
with open(path, 'r') as stream:
return yaml.load(stream)
class MasterDef(Import_Yaml_Setting):
def __init__(self, path):
Import_Yaml_Setting.__init__(self, path)
master_def = None
def function_1():
global master_def
path = 'yaml_file.yaml'
if master_def is None:
master_def = MasterDef(path)
def function_2():
print('master_def:', master_def.settings)
if __name__ == '__main__':
function_1()
function_2()
If your YAML file looks like:
example: file
very: simple
the output of the above program will be:
master_def: {'example': 'file', 'very': 'simple'}
I have tried to import like this:
sample_wave is another python file onlistener is the classname and onpartialTranscript is function in it
from sample_wave import onPartialTranscript
how can i invoke the function inside the class from another file?
def create_username():
username, pwd
try:
engine.say("Enter the user name and password for New user")
engine.runAndWait()
username = add_user(raw_input(onPartialTranscript(username), pwd=getpass.getpass()))
engine.say("User Credentials added! %s" % username)
engine.runAndWait()
except Exception as e:
engine.say("recheck credentials")
engine.runAndWait()
you cannot import function from class you should import class and then create object of that class and call that method
from sample_wave import onlistener
x = onlistener();
username = ...
x.onPartialTranscript(username)
You can't import the function directly. However, you could:
Import the class and instantiate the object, as stated in earlier answer
Rewrite the function
Import the class and create your own as its child, overriding __init__ method
I would vote for 3., it seems to be the cleanest to me.
Besides you can try following experiment. Nevertheless, it can introduce unexpected results, usage of eval is not a good practice for example, etc.
test.py - the module which you want to import from:
class onlistener:
def __init__(self):
pass
def testfunction(self):
print "Imported"
In the following, use inspect module to find the function called testfunction:
import inspect
from test import onlistener
def main():
classfunc = inspect.getsourcelines(onlistener.testfunction)
# the first field contains the code (list of lines), convert it to string
my_str = ''
first = True
for line in myfunc[0]:
if first:
# First line contains 'self' argument, remove it
line = line.replace('self', '')
first = False
# we need to remove the indentation, here it's 4 spaces
my_str += line[4:]
# append the call to the function
# newline is needed due to specification of compile function
my_str += 'testfunction()\n'
# create code object
my_func = compile(my_str, '<string>', 'exec')
# The last line will call the function and print "Imported"
eval(my_func)
Hi I have a GUI written using Tkinter and the code template is as follows. My question is PyCharm gives me warnings on my functions (def func1, def func2) that they are static. To get rid of the warnings I placed #staticmethod above the functions. What does this do and is it necessary?
# Use TKinter for python 2, tkinter for python 3
import Tkinter as Tk
import ctypes
import numpy as np
import os, fnmatch
import tkFont
class MainWindow(Tk.Frame):
def __init__(self, parent):
Tk.Frame.__init__(self,parent)
self.parent = parent
self.parent.title('BandCad')
self.initialize()
#staticmethod
def si_units(self, string):
if string.endswith('M'):
num = float(string.replace('M', 'e6'))
elif string.endswith('K'):
num = float(string.replace('K', 'e3'))
elif string.endswith('k'):
num = float(string.replace('k', 'e3'))
else:
num = float(string)
return num
if __name__ == "__main__":
# main()
root = Tk.Tk()
app = MainWindow(root)
app.mainloop()
You can also turn off that inspection so that PyCharm doesn't warn you. Preferences -> Editor -> Inspections. Note that the inspection appears in the JavaScript section as well as the Python section.
You are right about #staticmethod being confusing. It is not really needed in Python code and in my opinion should almost never by used. Instead, since si_units is not a method, move it out of the class and remove the unused self parameter. (Actually, you should have done that when adding #staticmethod; the posted code will not work right with 'self' left in.)
Unless one has forgotten to use 'self' when it needs to be used, this is (or at least should be) the intent of the PyCharm warning. No confusion, no fiddling with PyCharm settings.
While you are at it, you could condense the function and make it easily extensible to other suffixes by using a dict.
def si_units(string):
d = {'k':'e3', 'K':'e3', 'M':'e6'}
end = string[-1]
if end in d:
string = string[:-1] + d[end]
return float(string)
for f in ('1.5', '1.5k', '1.5K', '1.5M'): print(si_units(f))
The goal is to update the content of an existent file identified by 'filename'.
The first save call (aStorage.save(filename, ContentFile(content1)) creates the file 'test1'.
The second save call (aStorage.save(filename, ContentFile(content2))) creates a new file (done by Storage.get_available_name) instead of updating the current one.
>>> from django.core.files.storage import FileSystemStorage
>>> from django.core.files.base import ContentFile
>>> import sys
>>> sys.path.append('/home/project1')
>>> import os
>>> os.environ['DJANGO_SETTINGS_MODULE']='project1.settings'
>>> from django.conf import settings
>>> aStorage = FileSystemStorage(location=settings.BASE_DIR)
>>> content1 = "1514 – Mary Tudor (pictured), sister of Henry VIII of England"
>>> content2 = "1874 – The Universal Postal Union, then known as the General Postal"
>>> filename = os.path.join(settings.BASE_DIR, 'tests', 'test1')
>>> aStorage.save(filename, ContentFile(content1))
'./tests/test1'
>>> aStorage.save(filename, ContentFile(content2))
'./tests/test1_ESZ5jdM'
One solution might be this one here:
>>>>if (aStorage.exists(filename)):
>>>> aStorage.delete(filename)
>>> aStorage.save(filename,ContentFile(content2))
`'./tests/test1'`
Is there any other mechanism/workaround to achieve the same functionality ? Thank you.
IF you want to "overwrite" the file, you can go with your own custom Filestorage like this:
class MyFileSystemStorage(FileSystemStorage):
def get_available_name(self, name):
if os.path.exists(self.path(name)):
os.remove(self.path(name))
return name
In this case the file will be deleted so that a file with the same name can be created. This feels like it would be overwritten. Hope this is what you are looking for.
Update:
MyFileSystemStorage is a small custom class which inherits from FileSystemStorage and overwrites the "default" get_available_name function from Djangos FileSystemStorage. You do not need to use this function directly. Its transparently handled if you save a FileObject.
You can use it like this:
aStorage = MyFileSystemStorage(location=settings.BASE_DIR)
If you use MyFileSystemStorage instead of Django FileSystemStorage and save a file with a certain name, an already existing file with that name will be deleted and a new one will be created with the given name. Be careful to use the code like this because any existing file will be "overwritten" if it already exists. If I follow your example correctly you want this behaviour, so I think that it wouldnt not have an impact on your existing code.
It's not clear to me in which situation I can use save method. Therefore, for the moment, I prefer not to change/overwrite the Django Storage.save/get_available_name method behavior. This sounds like another solution to my problem : to use the Storage.open method instead of Storage.save:
>>> content1 = "11111111"
>>> content2 = "22222222"
>>> aStorage
<django.core.files.storage.FileSystemStorage object at 0x7f94ffccc6d0>
>>> fd = aStorage.open("test1.txt","w+")
>>> fd.write(content1)
8
>>> fd.seek(0)
0
>>> fd.read()
'11111111'
>>> fd.close()
>>>
>>> fd = aStorage.open("test1.txt","w+")
>>> fd.read()
''
>>> fd.write(content2)
8
>>> fd.seek(0)
0
>>> fd.read()
'22222222'
>>> fd.close()
>>> aStorage.exists("test1.txt")
>>> True
I will appreciate if you could share with me a situation for the usage of Django's Storage.save method. I am looking here a real case situation. Thanks.