Remove support for Python 2.7
issue7497 review53261002
This commit is contained in:
@@ -25,12 +25,6 @@ services:
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- IMAGE: python:2.7
|
||||
TOXENV: py27
|
||||
DATABASE: sqlite
|
||||
- IMAGE: python:2.7
|
||||
TOXENV: py27
|
||||
DATABASE: postgresql
|
||||
- IMAGE: python:3.4
|
||||
TOXENV: py34
|
||||
DATABASE: sqlite
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Remove support for Python 2.7
|
||||
* Use today as fallback for invoice date report
|
||||
|
||||
Version 4.8.0 - 2018-04-23
|
||||
|
||||
@@ -4,7 +4,7 @@ Installing trytond_account_invoice
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
* Python 2.7 or later (http://www.python.org/)
|
||||
* Python 3.4 or later (http://www.python.org/)
|
||||
* python-dateutil (http://labix.org/python-dateutil)
|
||||
* python-sql (http://code.google.com/p/python-sql/)
|
||||
* trytond (http://www.tryton.org/)
|
||||
|
||||
+8
-14
@@ -18,8 +18,7 @@ __all__ = ['FiscalYear',
|
||||
'RenewFiscalYear']
|
||||
|
||||
|
||||
class FiscalYear:
|
||||
__metaclass__ = PoolMeta
|
||||
class FiscalYear(metaclass=PoolMeta):
|
||||
__name__ = 'account.fiscalyear'
|
||||
invoice_sequences = fields.One2Many(
|
||||
'account.fiscalyear.invoice_sequence', 'fiscalyear',
|
||||
@@ -72,8 +71,7 @@ class FiscalYear:
|
||||
return [{}]
|
||||
|
||||
|
||||
class Period:
|
||||
__metaclass__ = PoolMeta
|
||||
class Period(metaclass=PoolMeta):
|
||||
__name__ = 'account.period'
|
||||
|
||||
@classmethod
|
||||
@@ -188,8 +186,7 @@ class InvoiceSequence(sequence_ordered(), ModelSQL, ModelView, MatchMixin):
|
||||
return Transaction().context.get('company')
|
||||
|
||||
|
||||
class Move:
|
||||
__metaclass__ = PoolMeta
|
||||
class Move(metaclass=PoolMeta):
|
||||
__name__ = 'account.move'
|
||||
|
||||
@classmethod
|
||||
@@ -197,8 +194,7 @@ class Move:
|
||||
return super(Move, cls)._get_origin() + ['account.invoice']
|
||||
|
||||
|
||||
class MoveLine:
|
||||
__metaclass__ = PoolMeta
|
||||
class MoveLine(metaclass=PoolMeta):
|
||||
__name__ = 'account.move.line'
|
||||
|
||||
invoice_payment = fields.Function(fields.Many2One(
|
||||
@@ -231,7 +227,7 @@ class MoveLine:
|
||||
pool = Pool()
|
||||
InvoicePaymentLine = pool.get('account.invoice-account.move.line')
|
||||
|
||||
ids = map(int, lines)
|
||||
ids = list(map(int, lines))
|
||||
result = dict.fromkeys(ids, None)
|
||||
for sub_ids in grouped_slice(ids):
|
||||
payment_lines = InvoicePaymentLine.search([
|
||||
@@ -253,8 +249,7 @@ class MoveLine:
|
||||
return [('invoice_payments',) + tuple(domain[1:])]
|
||||
|
||||
|
||||
class Reconciliation:
|
||||
__metaclass__ = PoolMeta
|
||||
class Reconciliation(metaclass=PoolMeta):
|
||||
__name__ = 'account.move.reconciliation'
|
||||
|
||||
@classmethod
|
||||
@@ -285,9 +280,8 @@ class Reconciliation:
|
||||
Invoice.process(invoices)
|
||||
|
||||
|
||||
class RenewFiscalYear:
|
||||
class RenewFiscalYear(metaclass=PoolMeta):
|
||||
__name__ = 'account.fiscalyear.renew'
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
@property
|
||||
def invoice_sequence_fields(self):
|
||||
@@ -306,7 +300,7 @@ class RenewFiscalYear:
|
||||
for field in self.invoice_sequence_fields:
|
||||
sequence = getattr(invoice_sequence, field, None)
|
||||
sequences[sequence.id] = sequence
|
||||
copies = Sequence.copy(sequences.values(), default={
|
||||
copies = Sequence.copy(list(sequences.values()), default={
|
||||
'next_number': 1,
|
||||
})
|
||||
|
||||
|
||||
+11
-11
@@ -576,7 +576,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
for key in computed_taxes:
|
||||
if key not in tax_keys:
|
||||
self.tax_amount += computed_taxes[key]['amount']
|
||||
value = InvoiceTax.default_get(InvoiceTax._fields.keys())
|
||||
value = InvoiceTax.default_get(list(InvoiceTax._fields.keys()))
|
||||
value.update(computed_taxes[key])
|
||||
invoice_tax = InvoiceTax(**value)
|
||||
if invoice_tax.tax:
|
||||
@@ -680,7 +680,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
'tax_amount': tax_amount,
|
||||
'total_amount': total_amount,
|
||||
}
|
||||
for key in result.keys():
|
||||
for key in list(result.keys()):
|
||||
if key not in names:
|
||||
del result[key]
|
||||
return result
|
||||
@@ -880,7 +880,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
|
||||
def _compute_taxes(self):
|
||||
taxes = self._get_taxes()
|
||||
for tax in taxes.itervalues():
|
||||
for tax in taxes.values():
|
||||
tax['invoice'] = self.id
|
||||
return taxes
|
||||
|
||||
@@ -895,7 +895,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
continue
|
||||
computed_taxes = invoice._compute_taxes()
|
||||
if not invoice.taxes:
|
||||
to_create.extend([tax for tax in computed_taxes.values()])
|
||||
to_create.extend(computed_taxes.values())
|
||||
else:
|
||||
tax_keys = []
|
||||
for tax in invoice.taxes:
|
||||
@@ -1119,7 +1119,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
]
|
||||
|
||||
def get_origins(self, name):
|
||||
return ', '.join(set(itertools.ifilter(None,
|
||||
return ', '.join(set(filter(None,
|
||||
(l.origin_name for l in self.lines))))
|
||||
|
||||
@classmethod
|
||||
@@ -1209,7 +1209,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
if not l.reconciliation]
|
||||
|
||||
best = Result([], self.total_amount)
|
||||
for n in xrange(len(lines), 0, -1):
|
||||
for n in range(len(lines), 0, -1):
|
||||
for comb_lines in combinations(lines, n):
|
||||
remainder = sum((l.debit - l.credit) for l in comb_lines)
|
||||
remainder -= amount
|
||||
@@ -1287,7 +1287,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
def add_payment_lines(cls, payments):
|
||||
"Add value lines to the key invoice from the payment dictionary."
|
||||
to_write = []
|
||||
for invoice, lines in payments.iteritems():
|
||||
for invoice, lines in payments.items():
|
||||
if invoice.state == 'paid':
|
||||
cls.raise_user_error('modify_payment_lines_invoice_paid', {
|
||||
'invoice': invoice.rec_name,
|
||||
@@ -1304,7 +1304,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
PaymentLine = pool.get('account.invoice-account.move.line')
|
||||
|
||||
payments = defaultdict(list)
|
||||
ids = map(int, lines)
|
||||
ids = list(map(int, lines))
|
||||
for sub_ids in grouped_slice(ids):
|
||||
payment_lines = PaymentLine.search([
|
||||
('line', 'in', list(sub_ids)),
|
||||
@@ -1313,7 +1313,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
payments[payment_line.invoice].append(payment_line.line)
|
||||
|
||||
to_write = []
|
||||
for invoice, lines in payments.iteritems():
|
||||
for invoice, lines in payments.items():
|
||||
if invoice.state == 'paid':
|
||||
cls.raise_user_error('modify_payment_lines_invoice_paid', {
|
||||
'invoice': invoice.rec_name,
|
||||
@@ -1360,7 +1360,7 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin):
|
||||
cls.update_taxes(new_invoices)
|
||||
if refund:
|
||||
cls.post(new_invoices)
|
||||
for invoice, new_invoice in itertools.izip(invoices, new_invoices):
|
||||
for invoice, new_invoice in zip(invoices, new_invoices):
|
||||
if new_invoice.state == 'posted':
|
||||
MoveLine.reconcile([l for l in invoice.lines_to_pay
|
||||
if not l.reconciliation] +
|
||||
@@ -1887,7 +1887,7 @@ class InvoiceLine(sequence_ordered(), ModelSQL, ModelView, TaxableMixin):
|
||||
def get_invoice_taxes(self, name):
|
||||
if not self.invoice:
|
||||
return
|
||||
taxes_keys = self._get_taxes().keys()
|
||||
taxes_keys = list(self._get_taxes().keys())
|
||||
taxes = []
|
||||
for tax in self.invoice.taxes:
|
||||
if tax.manual:
|
||||
|
||||
@@ -13,14 +13,12 @@ supplier_payment_term = fields.Many2One(
|
||||
'account.invoice.payment_term', "Supplier Payment Term")
|
||||
|
||||
|
||||
class Address:
|
||||
__metaclass__ = PoolMeta
|
||||
class Address(metaclass=PoolMeta):
|
||||
__name__ = 'party.address'
|
||||
invoice = fields.Boolean('Invoice')
|
||||
|
||||
|
||||
class ContactMechanism:
|
||||
__metaclass__ = PoolMeta
|
||||
class ContactMechanism(metaclass=PoolMeta):
|
||||
__name__ = 'party.contact_mechanism'
|
||||
invoice = fields.Boolean('Invoice')
|
||||
|
||||
@@ -91,8 +89,7 @@ class PartyPaymentTerm(ModelSQL, ValueMixin):
|
||||
parent='party', fields=fields)
|
||||
|
||||
|
||||
class PartyReplace:
|
||||
__metaclass__ = PoolMeta
|
||||
class PartyReplace(metaclass=PoolMeta):
|
||||
__name__ = 'party.replace'
|
||||
|
||||
@classmethod
|
||||
@@ -103,8 +100,7 @@ class PartyReplace:
|
||||
]
|
||||
|
||||
|
||||
class PartyErase:
|
||||
__metaclass__ = PoolMeta
|
||||
class PartyErase(metaclass=PoolMeta):
|
||||
__name__ = 'party.erase'
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from setuptools import setup
|
||||
import re
|
||||
import os
|
||||
import io
|
||||
try:
|
||||
from configparser import ConfigParser
|
||||
except ImportError:
|
||||
from ConfigParser import ConfigParser
|
||||
import os
|
||||
import re
|
||||
from configparser import ConfigParser
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
def read(fname):
|
||||
@@ -27,6 +24,7 @@ def get_require_version(name):
|
||||
major_version, minor_version + 1)
|
||||
return require
|
||||
|
||||
|
||||
config = ConfigParser()
|
||||
config.readfp(open('tryton.cfg'))
|
||||
info = dict(config.items('tryton'))
|
||||
@@ -102,7 +100,6 @@ setup(name=name,
|
||||
'Natural Language :: Slovenian',
|
||||
'Natural Language :: Spanish',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
@@ -112,6 +109,7 @@ setup(name=name,
|
||||
'Topic :: Office/Business :: Financial :: Accounting',
|
||||
],
|
||||
license='GPL-3',
|
||||
python_requires='>=3.4',
|
||||
install_requires=requires,
|
||||
dependency_links=dependency_links,
|
||||
zip_safe=False,
|
||||
@@ -122,10 +120,4 @@ setup(name=name,
|
||||
test_suite='tests',
|
||||
test_loader='trytond.test_loader:Loader',
|
||||
tests_require=tests_require,
|
||||
use_2to3=True,
|
||||
convert_2to3_doctests=[
|
||||
'tests/scenario_invoice.rst',
|
||||
'tests/scenario_invoice_alternate_currency.rst',
|
||||
'tests/scenario_invoice_supplier.rst',
|
||||
],
|
||||
)
|
||||
|
||||
@@ -158,9 +158,9 @@ Post invoice::
|
||||
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> invoice.tax_identifier.code
|
||||
u'BE0897290877'
|
||||
'BE0897290877'
|
||||
>>> invoice.untaxed_amount
|
||||
Decimal('220.00')
|
||||
>>> invoice.tax_amount
|
||||
@@ -206,7 +206,7 @@ Credit invoice with refund::
|
||||
>>> credit.execute('credit')
|
||||
>>> invoice.reload()
|
||||
>>> invoice.state
|
||||
u'paid'
|
||||
'paid'
|
||||
>>> invoice.reconciled == today
|
||||
True
|
||||
>>> receivable.reload()
|
||||
@@ -295,7 +295,7 @@ Pay invoice::
|
||||
>>> pay.execute('pay')
|
||||
|
||||
>>> invoice.state
|
||||
u'paid'
|
||||
'paid'
|
||||
|
||||
Create empty invoice::
|
||||
|
||||
@@ -304,7 +304,7 @@ Create empty invoice::
|
||||
>>> invoice.payment_term = payment_term
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
u'paid'
|
||||
'paid'
|
||||
|
||||
Create some complex invoice and test its taxes base rounding::
|
||||
|
||||
@@ -355,14 +355,14 @@ Create a paid invoice::
|
||||
'end'
|
||||
>>> invoice.tax_identifier
|
||||
>>> invoice.state
|
||||
u'paid'
|
||||
'paid'
|
||||
|
||||
The invoice is posted when the reconciliation is deleted::
|
||||
|
||||
>>> invoice.payment_lines[0].reconciliation.delete()
|
||||
>>> invoice.reload()
|
||||
>>> invoice.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> invoice.tax_identifier
|
||||
|
||||
Credit invoice with non line lines::
|
||||
|
||||
@@ -135,7 +135,7 @@ Create invoice with alternate currency::
|
||||
Decimal('460.00')
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> invoice.untaxed_amount
|
||||
Decimal('420.00')
|
||||
>>> invoice.tax_amount
|
||||
@@ -163,7 +163,7 @@ Pay the invoice with rate change::
|
||||
True
|
||||
>>> pay.execute('pay')
|
||||
>>> invoice.state
|
||||
u'paid'
|
||||
'paid'
|
||||
|
||||
Create negative tax::
|
||||
|
||||
@@ -191,7 +191,7 @@ Create invoice with alternate currency and negative taxes::
|
||||
Decimal('360.00')
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> invoice.untaxed_amount
|
||||
Decimal('400.00')
|
||||
>>> invoice.tax_amount
|
||||
|
||||
@@ -121,23 +121,23 @@ Create invoice::
|
||||
Decimal('120.00')
|
||||
>>> invoice.save()
|
||||
>>> invoice.state
|
||||
u'draft'
|
||||
'draft'
|
||||
>>> bool(invoice.move)
|
||||
False
|
||||
>>> invoice.click('validate_invoice')
|
||||
>>> invoice.state
|
||||
u'validated'
|
||||
'validated'
|
||||
>>> bool(invoice.move)
|
||||
True
|
||||
>>> invoice.move.state
|
||||
u'draft'
|
||||
'draft'
|
||||
>>> invoice.click('post')
|
||||
>>> invoice.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> bool(invoice.move)
|
||||
True
|
||||
>>> invoice.move.state
|
||||
u'posted'
|
||||
'posted'
|
||||
>>> invoice.untaxed_amount
|
||||
Decimal('110.00')
|
||||
>>> invoice.tax_amount
|
||||
@@ -184,7 +184,7 @@ Credit invoice::
|
||||
>>> credit_note, = Invoice.find(
|
||||
... [('type', '=', 'in'), ('id', '!=', invoice.id)])
|
||||
>>> credit_note.state
|
||||
u'draft'
|
||||
'draft'
|
||||
>>> credit_note.untaxed_amount == -invoice.untaxed_amount
|
||||
True
|
||||
>>> credit_note.tax_amount == -invoice.tax_amount
|
||||
@@ -210,7 +210,7 @@ Cancel draft invoice::
|
||||
|
||||
>>> invoice_draft.click('cancel')
|
||||
>>> invoice_draft.state
|
||||
u'cancel'
|
||||
'cancel'
|
||||
>>> invoice_draft.move
|
||||
>>> invoice_draft.reconciled
|
||||
|
||||
@@ -218,7 +218,7 @@ Cancel posted invoice::
|
||||
|
||||
>>> invoice.click('cancel')
|
||||
>>> invoice.state
|
||||
u'cancel'
|
||||
'cancel'
|
||||
>>> invoice.cancel_move is not None
|
||||
True
|
||||
>>> invoice.reconciled == today
|
||||
|
||||
@@ -135,14 +135,14 @@ class AccountInvoiceTestCase(ModuleTestCase):
|
||||
}])]
|
||||
}])
|
||||
terms = remainder_term.compute(Decimal('0.0'), cu1,
|
||||
date=datetime.date(2016, 05, 17))
|
||||
date=datetime.date(2016, 5, 17))
|
||||
self.assertEqual(terms, [
|
||||
(datetime.date(2016, 05, 17), Decimal('0.0')),
|
||||
(datetime.date(2016, 5, 17), Decimal('0.0')),
|
||||
])
|
||||
terms = percent_term.compute(Decimal('0.0'), cu1,
|
||||
date=datetime.date(2016, 05, 17))
|
||||
date=datetime.date(2016, 5, 17))
|
||||
self.assertEqual(terms, [
|
||||
(datetime.date(2016, 05, 17), Decimal('0.0')),
|
||||
(datetime.date(2016, 5, 17), Decimal('0.0')),
|
||||
])
|
||||
|
||||
@with_transaction()
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[tox]
|
||||
envlist = {py27,py34,py35,py36}-{sqlite,postgresql},pypy-{sqlite,postgresql}
|
||||
envlist = {py34,py35,py36}-{sqlite,postgresql},pypy3-{sqlite,postgresql}
|
||||
|
||||
[testenv]
|
||||
commands = {envpython} setup.py test
|
||||
deps =
|
||||
{py27,py34,py35,py36}-postgresql: psycopg2 >= 2.5
|
||||
pypy-postgresql: psycopg2cffi >= 2.5
|
||||
{py34,py35,py36}-postgresql: psycopg2 >= 2.5
|
||||
pypy3-postgresql: psycopg2cffi >= 2.5
|
||||
sqlite: sqlitebck
|
||||
setenv =
|
||||
sqlite: TRYTOND_DATABASE_URI={env:SQLITE_URI:sqlite://}
|
||||
|
||||
Reference in New Issue
Block a user