I am unable to declare a constructor in Python 3.8. I am not able to declare a constructor. The system is showing the error message:
"Undefined Variable" and "illegal target for annotations.
class Employee:
def__init__(self,name,id):
self.name = name
self.id = id
def dispaly(self):
print("ID: %d\nName: %s"%(self.id,self.name))
emp1 = Employee("Robert",101)
emp1.dispaly()
You are missing a space between def and __init__ keywords.
Correct way:
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def display(self):
print("Employee Name is {} and ID is {}.".format(self.name, self.id))
emp1 = Employee("Robert", "E001")
emp1.display()
Related
I extend the RethinkDb API by providing some extra functions.
For example I simplify the expression
site_ids = r.table('periods')\
['regions']\
.concat_map(lambda row: row['sites'])\
['id']
to
site_ids = f['periods']\
.unwind('regions.sites.id')
using a custom unwind method that is able to resolve a path of nested document elements. If an item in the given path is a list, its entries are concatenated with concat_map. Otherwise the item is accessed with bracket notation:
def unwind(self, path):
items = path.split('.')
cursor = self._cursor
for item in items:
is_list = isinstance(cursor[item].run().next(), list)
if is_list:
cursor = cursor.concat_map(lambda row: row[item])
else:
cursor = cursor[item]
return self.wrap(self._f, cursor)
=> How can I improve the type check to find out if an element is a list? The check should not require an extra .run() and it should work in main queries as well as in sub queries.
My current implementation with the expression
is_list = isinstance(cursor[item].run().next(), list)
works fine in "main queries" like
result = f['periods'] \
.unwind('regions.sites.plants.product.process.technologies')\
.populate_with('periods', 'technologies')\
.sum('specific_cost_per_year') \
.run()
It does not work in sub queries, e.g. inside a mapping function:
def period_mapper(period):
return {
'year': period['start'],
'site_ids': f.wrap(period).unwind('regions.sites.id')
}
f.table('periods')\
.map(period_mapper)\
.run()
I get the error
rethinkdb.errors.ReqlServerCompileError: Variable name not found in:
var_1['regions']
^^^^^
because I am not able to .run() a query on the passed variable argument "period".
I tried to replace the if-then-else condition with r.branch but that did not help.
=> How can I choose an operator based on the type of the current cursor content in a better way?
Code of my selection class that wraps a RethinkDb cursor:
from rethinkdb.ast import RqlQuery
# needs to inherit from RqlQuery for the json serialization to work
class AbstractSelection(RqlQuery):
def __init__(self, f, cursor):
self._f = f
self._cursor = cursor
def __getitem__(self, identifier):
cursor = self._cursor[identifier]
return self.wrap(self._f, cursor)
def __repr__(self):
return self._cursor.__repr__()
def __str__(self):
return self._cursor.__str__()
def build(self):
return self._cursor.build()
#property
def _args(self): # required for json serialization
return self._cursor._args
#property
def optargs(self): # required for json serialization
return self._cursor.optargs
def wrap(self, r, cursor):
raise NotImplemented('Needs to be implemented by inheriting class')
def unwind(self, path):
items = path.split('.')
cursor = self._cursor
for item in items:
is_list = isinstance(cursor[item].run().next(), list)
if is_list:
cursor = cursor.concat_map(lambda row: row[item])
else:
cursor = cursor[item]
return self.wrap(self._f, cursor)
def pick(self, path, query):
return self.unwind(path).get(query)
def populate(self, collection_name, path):
return self.map(lambda identifier:
self._f[collection_name]
.pick(path, {'id': identifier})
)
def get(self, query):
cursor = self._cursor.filter(query)[0]
return self.wrap(self._f, cursor)
def to_array(self):
return [item for item in self._cursor]
I managed to use type_of in combination with branch. Accessing the item with bracket notation returns a STREAM and I had to get the first item with [0] before using type_of to check for the 'ARRAY' type. This also works if the property is not an array:
def unwind(self, path):
items = path.split('.')
cursor = self._cursor
r = self._f._r
for item in items:
cursor = r.branch(
cursor[item][0].type_of() == 'ARRAY',
cursor.concat_map(lambda row: row[item]),
cursor[item]
)
return self.wrap(self._f, cursor)
class SunOrder(models.Model):
_name = 'sun.order'
manufacture_id = fields.Many2one(
'product.product',
#api.model
def create(self, vals):
Sequence = self.env['ir.sequence']
vals['name'] = Sequence.next_by_code('sun.order')
return super(SunOrder, self).create(vals)
here is simple create method that i use when creating data in my module.
the goal is to create quotation with same CREATE method with same name and samemanufacture_id.I mean when i creat sun.order i need that the same time quotation would be created. So maybe some 1 can give me example or general idea how it can be done. because i have no clue.
class pos_quotation(models.Model):
_name = "pos.quotation"
name = fields.Char('Name')
manufacture_id = fields.Many2one(
'product.product',
You can rewrite your create method as follows:
#api.model
def create(self, vals):
Sequence = self.env['ir.sequence']
vals['name'] = Sequence.next_by_code('sun.order')
#set your pos_quotation dictionary
vals_quot = {'manufacture_id': vals['manufacture_id'],
#... other fields for pos.quotation model
}
self.env['pos.quotation'].create(vals_quot)
return super(SunOrder, self).create(vals)
I hope this help you.
I have added this fields under account.invoice in order to get an autoincrement number but it doesn't work.
Help me please to figure out my error
Example Code
class invoice(osv.osv):
_inherit = 'account.invoice'
def _get_increment(self, cr, uid, ids, fields, arg, context=None):
if context is None: context = {}
res = {}
if type == 'out_invoice':
ids = self.search(cr,uid,[('id','!=',False),('type','in',('out_invoice','out_refund'))])
if ids:
last_id = ids and max(ids)
print 'last_id',last_id
for invoice in self.browse(cr, uid, last_id, context):
print 'invoice', invoice
if invoice.name1:
res[invoice.id] = invoice.name1
else :
res[invoice.id] = invoice.name1 + 1
return res
_columns={
'name1':fields.function(_get_increment, type='integer', string='Name1'),
}
First of all. Your function never returns a value since type is never set.
Which means the if condition is never triggered.
At second. I'd suggest that you'd use the new Odoo API.
function fields are replaced by the compute attribute on fields and the declaration no longer takes place in the _columns dictionary.
New API
instead of importing from openerp.osv you should import the following:
from openerp import fields, models, api
The code would look like this:
from openerp import fields, models, api
class invoice(models.Model):
_inherit = 'account.invoice'
name1 = fields.Integer('Name1', compute='_get_increment')
#api.one
def _get_increment(self):
self.name1 = 1 + 1 #This value should be the value that you've calculated
the only thing you need to do in the method _get_increment is set self.name1.
In the new API self is a record. So self.id would get you the id of the record and so on.
I have a model, where I want to access a field, given by a string. Example:
def test(self):
field = 'name'
name = getattr(self, field)
This works fine - name is set to self.name. But then I want to access a related field:
def test2(self):
field = 'partner_id.name'
name = getattr(self, field)
That doesn't work (because 'partner_id.name' does not exist on self). Any idea how to do it right?
getattr doesn't support the dot notation, only simple attribute names. You can however create a simple function that does:
def getfield(model, field_name):
value = model
for part in field_name.split('.'):
value = getattr(value, part)
return value
You would use it like this:
def test2(self):
field = 'partner_id.name'
name = getfield(self, field)
You need to use the object that contain partner_id.name
def test2(self):
field = 'name'
object = self.pool.get('res.partner').browse(cr, uid, self.partner_id.id)#v7
#object = self.env['res.partner'].browse(self.partner_id.id)#v8
name = getattr(object, field)
I also came across another solution, inspired by the mail template system:
from openerp.tools.safe_eval import safe_eval as eval
def test2(self):
field = 'partner_id.name'
field = 'object.' + field
name = eval(field, {'object': self})
I want to access an attribute of a model from within a function. Take a look at the line if(len(self.order_line) > 0):
How do I do this correctly? Because the code above doesn't work.
The purpose of this function field is to read and modify another attribute of the same model which is the order_line. So it acts as a bridge to simplify the ui, the user only need to specify a property unit to represent the order_line. So I need to access the said order_line from within the function.
And I also want to SET the order_line value based on the property_unit_rel value BEFORE the creation of sale.order. How do I do that within the _property_unit_inv function?
Overall code:
from osv import osv,fields
class custom_sale_order(osv.osv):
_name = "sale.order"
_inherit = 'sale.order'
def _property_unit_read(self, cr, uid, ids, property_unit_rel, arg, context):
if(len(self.order_line) > 0):
pass
else:
return None
def _property_unit_inv(self, cr, uid, ids, property_unit_rel, arg, context):
pass
#this will simplify the need of defining a sale_order_line
_columns = {
'property_unit_rel' : fields.function(
_property_unit_read,
fnct_inv = _property_unit_inv,
type='many2one',
obj="property.unit",
method=True,
string='Property'
),
}
_defaults = {
}
_sql_constraints = [
]
def init(self, cr):
pass
custom_sale_order()
Most methods you call in OpenERP have parameters self, cr, uid, ids, ....
self is pool (see object pool pattern), cr is database cursor, uid is user id and ids is id or list of ids of objects you call method for. If you want to get number of order lines you must get order object at first. You can do it with a=self.browse(cr, uid, ids, context=context) to get object (or objects) specified by ids.
If ids is int or long you'll get browse_record but if it's list you'll get iterable browse_record_list (list of browse records). To get lines of some order you can call a.order_line (or a[0].order_line if ids was a list).
So if you can get an attribute of object you have to call it for browse_record.