Python. Adding custom methods to existing site-packages - python

I'm using openpyxl with python 2.7 to manipulate some workbooks. I've implemented my own methods for class Worksheet except they're not being found when I try to access them. I''m on windows and I've adding the following code to site-packages/openpyxl/worksheet/worksheet.py. Source code here.
class Worksheet(_WorkbookChild):
"""
Library defined methods here.
"""
#My Method.
def hello_world(self):
print "Hello from worksheet."
When I open up a workbook and try and call my function it raises an error for 'no attribute' even though it's been defined (properly?) under the scope of the class Worksheet.
import openpyxl
wb = openpyxl.load_workbook('helloworld.xlsx')
sheet = wb.get_active_sheet()
sheet.hello_world()
AttributeError: 'Worksheet' object has no attribute 'hello_world'
Do I need to do anything differently to update the existing library? I've deleted the .pyc, recompiled and am still getting the same error.

For anyone else who runs into this problem. The library was using 4 spaces for each indent while I was using a regular tab. The variation in indents caused the method to not be defined even though it appeared to be.

Related

python win32com excel >> ws.cells(1, 1).value does not work

i have used win32com.client to to something with excel.
so far, ".cells(1, 1).value" method succesfully read the value in row1, column1.
but from now, that code doesn't work.
it occurs error >>
'<win32com.gen_py.Microsoft Excel 16.0 Object Library._Worksheet instance at 0x2284591006720>' object has no attribute 'cells'
what is a problem?
xlsApp = win32com.client.GetActiveObject("Excel.Application")
wb = xlsApp.Workbooks(wb_name)
ws = wb.Worksheets(ws_name)
test = ws.cells(1, 1).value
print(test)
The method name is Cells() with an uppercase ‘C’ is the simple answer.
It is fair to ask: “If cells() worked before, why doesn’t it work now?”. IMHO it is a failing of win32com.
win32com will, if asked, generate a wrapper for COM objects (using a package called gen_py which creates a Python file for each object). If such a wrapper exists win32com will use it by default. This wrapper is case-sensitive. This is “early binding”.
If there is not a wrapper then calls like GetActiveObject() and Dispatch() will use “late binding” where win32com will try and call whatever method you want on the object (whether the method exists or not). The package takes whatever method you ask for and tries to get the ID of that function from the COM object via IDispatch.GetIdsOfNames(). Crucially, this lookup is case-INsensitive: using cells(),Cells() or even cElLs() will all work.
And this is the problem. The generated wrappers are stored in the user’s directory. Your code might have been happily using late-binding and cells(), but another programme may have created the wrapper at a later date. Now your code will see this wrapper and switch to early-binding and now cells() no longer works: you need to use Cells().
So, when using win32com it is always worth finding out the exact function name from the reference, eg from here

VSCode Python autocompletion not working on some classes only

When using autocompletion in VSCode in my python project, it works very well except for one class and I cannot figure out why.
The class is coming from a module database which contains 3 classes total: DatabaseClient, Database, Collection
DatabaseClient has a get_database() method which returns a Database object.
Database has a get_collection() method which returns a Collection object.
Collection has several methods.
The autocompletion works as intended on the DatabaseClient & Database objects, but not at all on the Collection object.
The code below works and give the expected results (line 15 and 20 of the screenshot results match), but not the autocompletion while editing as stated above.
import lib.database as database
print( database.DatabaseClient().get_database('business').get_collection('reviews').find() )
client = database.DatabaseClient()
db = client.get_database(client.list_database_names()[0])
coll = db.get_collection(db.list_collection_names()[0])
print(coll.find())
Tried to reload VSCode, unload and reload the python extensions.
Tried to uninstall and re-install the python extensions.
Tried to change the name of my module.
Tried to change the name of the class.
Tried to change the name of the method of the Collection class.
Tried using single line command line 3 and noticed it worked this way.
Found out the solution.
The problem comes from not using typing in the method headers.
Once I added proper typing, the autocompletion worked everywhere as expected.
def get_database(self, database_name: str) -> Database:
def get_collection(self, collection_name: str) -> Collection:

access and update a python3 set defined in the module

I am using https://github.com/sciunto/python-bibtexparser as a library module for my code(installed with pip3). So, I don't have writing access to the module.
But, the set it is using is rather limited, as defined in standard_types in https://github.com/sciunto/python-bibtexparser/blob/master/bibtexparser/bibdatabase.py.
Is it possible, that, I redefine/append the set from the calling code? e.g.
#foo.py
import bibtexparser
#redefine standard_types
bibtexparser.STANDARD_TYPES = set([the complete set I need])
#or append the standard_types
bibtexparser.STANDARD_TYPES.update = set([append to the set])
?
Update: Actually I cant access the variable STANDARD_TYPES. I am trying to do:
from bibtexparser import bibdatabase as bd
class Window(Gtk.ApplicationWindow):
def __init__(self, application, giofile=None):
Gtk.ApplicationWindow.__init__(self,
application=application,
default_width=1000,
default_height=200,
border_width=5)
print(bd)
print(bd.STANDARD_TYPES)
Which is yielding:
<module 'bibtexparser.bibdatabase' from '/usr/lib/python3.5/site-packages/bibtexparser/bibdatabase.py'>
......
print(bd.STANDARD_TYPES)
AttributeError: module 'bibtexparser.bibdatabase' has no attribute 'STANDARD_TYPES'
It looks like other parts of the package perform from bibtextparser import STANDARD_TYPES, so you can't just replace it; the modules that have already imported it will keep the old version. Using update would work fine though you need to fix your syntax:
bibtexparser.STANDARD_TYPES.update({append to the set})
That said, it looks like BibTexParser can be initialized passing it ignore_nonstandard_types=True and it won't even check STANDARD_TYPES, which is probably what you really want; it doesn't involve hacky monkey-patching at all.

unpickle instance after refactoring module name

Previously I defined an ElectrodePositionsModel class in the module gselu.py in the package gselu, and pickled the ElectrodePositionsModel objects into some files.
Some time later it was decided to refactor the project and the package name gselu was changed to ielu
When I attempt to unpickle the old pickle files with pickle.load(), the process fails with the error, 'module' object has no attribute 'ElectrodePositionsModel'. What I understand of the Unpicklers behavior is that this is because the pickle thinks it has stored an instance of gselu.gselu.ElectrodePositionsModel, and tries to therefore import this class from this module. When it doesn't exist, it gives up.
I think that I am supposed to add something to the module's init.py to tell it where the gselu.gselu.ElectrodePositionsModel is, but I can't get the pickle.load() function to give me any error message other than 'module' has no attribute 'ElectrodePositionsModel' and I can't figure out where I am supposed to provide the correct path to find it. The code that does the unpickling is in the same module file (gselu.py) as the ElectrodePositionsModel class.
When I load the pickle file in an ipython session and manually import ElectrodePositionsModel, it loads correctly.
How do I tell the pickler where to load this module?
I realise this questions is old, but I just ran into a similar problem.
What I did to solve it was to take the old code and unpickle the data using that.
Then instead of pickling directly the custom classes, I pickled CustomClass.__dict__ which only contained raw python.
This data could then easily be imported in the new module by doing
a = NewNameOfCustomClass()
a.__dict__ = pickle.load('olddata.p', 'rb')
This method works if your custom class only has standard variables (such as builtins or numpy arrays, etc).

gdata AttributeError: 'ContactEntry' object has no attribute 'name'

Using GData Python libraries, version 2.0.18
Attempting to retrieve contact list using the Service approach (not Client like the sample app). It appears that the return is mapped to a ContactEntry (good), but it gives error when I try to access the name attribute:
AttributeError: 'ContactEntry' object has no attribute 'name'
from gdata.contacts.service import ContactsService
(...)
self.client = ContactsService(source='appname', additional_headers=additional_headers )
feed = self.client.GetContactsFeed(uri=query.ToUri())
self.client is a gdata.contacts.service
GetContactsFeed uses
def GetContactsFeed(self, uri=None):
uri = uri or self.GetFeedUri()
return self.Get(uri, converter=gdata.contacts.ContactsFeedFromString)
The sample code uses desired_class=gdata.contacts.data.ContactsFeed
Seems like there should be a name attribute.
Is my syntax wrong?
Ok, here is the issue for the python contacts sample vs my implementation:
in gdata/sample/contacts/contacts_example.py it uses gdata.contacts.Client which (long chain to it) calls for the atom classes to use desired_class=gdata.contacts.data.ContactsFeed.
The service, as pointed out in the question, uses converter=gdata.contacts.ContactsFeedFromString.
This converter comes from the init file, src/gdata/contacts/init.py, as do the class definitions. Obviously at this point, you know what's coming -- the classes for the xml in the initializer do not match the ones in the data file.
I added these missing, incorrect ones in to initializer and things worked as expected. Alternatively, changing to use desired_class would do it too (at some point you'd have to map to converter...isn't supported directly in service.py), or adding converter to data.ContactsFeed, etc.
Hope this helps someone.

Categories

Resources