formatting, code optimized
This commit is contained in:
parent
dc6412cb4f
commit
ed04075bdb
5 changed files with 83 additions and 71 deletions
|
@ -6,6 +6,7 @@
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from .line import Line
|
from .line import Line
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
Line,
|
Line,
|
||||||
|
|
53
line.py
53
line.py
|
@ -3,13 +3,13 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains the
|
# The COPYRIGHT file at the top level of this repository contains the
|
||||||
# full copyright notices and license terms.
|
# full copyright notices and license terms.
|
||||||
|
|
||||||
import mimetypes, magic
|
import mimetypes
|
||||||
|
import magic
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from PIL import Image, UnidentifiedImageError
|
from PIL import Image, UnidentifiedImageError
|
||||||
from trytond.model import fields
|
from trytond.model import fields
|
||||||
from trytond.pool import Pool, PoolMeta
|
from trytond.pool import PoolMeta
|
||||||
from trytond.config import config
|
from trytond.config import config
|
||||||
from trytond.transaction import Transaction
|
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
from trytond.pyson import Eval, Bool
|
from trytond.pyson import Eval, Bool
|
||||||
|
@ -18,13 +18,13 @@ from trytond.modules.cashbook.line import STATES, DEPENDS
|
||||||
|
|
||||||
store_prefix = config.get('cashbook', 'store_prefix', default='cashbook')
|
store_prefix = config.get('cashbook', 'store_prefix', default='cashbook')
|
||||||
image_limit = config.get('cashbook', 'image_max_pixel', default='2000')
|
image_limit = config.get('cashbook', 'image_max_pixel', default='2000')
|
||||||
try :
|
try:
|
||||||
image_limit = int(image_limit)
|
image_limit = int(image_limit)
|
||||||
if image_limit < 100:
|
if image_limit < 100:
|
||||||
image_limit = 100
|
image_limit = 100
|
||||||
if image_limit > 10000:
|
if image_limit > 10000:
|
||||||
image_limit = 10000
|
image_limit = 10000
|
||||||
except :
|
except Exception:
|
||||||
image_limit = 2000
|
image_limit = 2000
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,10 +37,11 @@ DEPENDS2.extend(DEPENDS)
|
||||||
class Line(metaclass=PoolMeta):
|
class Line(metaclass=PoolMeta):
|
||||||
__name__ = 'cashbook.line'
|
__name__ = 'cashbook.line'
|
||||||
|
|
||||||
media = fields.Binary(string='Image of PDF', filename='media_name',
|
media = fields.Binary(
|
||||||
file_id='media_id', store_prefix=store_prefix,
|
string='Image of PDF', filename='media_name', file_id='media_id',
|
||||||
states=STATES2, depends=DEPENDS2)
|
store_prefix=store_prefix, states=STATES2, depends=DEPENDS2)
|
||||||
media_name = fields.Char(string='File name',
|
media_name = fields.Char(
|
||||||
|
string='File name',
|
||||||
states={
|
states={
|
||||||
'required': Bool(Eval('media')),
|
'required': Bool(Eval('media')),
|
||||||
'readonly': STATES2['readonly'],
|
'readonly': STATES2['readonly'],
|
||||||
|
@ -48,11 +49,12 @@ class Line(metaclass=PoolMeta):
|
||||||
media_id = fields.Char(string='File ID', readonly=True)
|
media_id = fields.Char(string='File ID', readonly=True)
|
||||||
media_mime = fields.Char(string='MIME', readonly=True)
|
media_mime = fields.Char(string='MIME', readonly=True)
|
||||||
media_size = fields.Integer(string='File size', readonly=True)
|
media_size = fields.Integer(string='File size', readonly=True)
|
||||||
media_image = fields.Function(fields.Binary(string='Image', readonly=True,
|
media_image = fields.Function(fields.Binary(
|
||||||
|
string='Image', readonly=True,
|
||||||
states={
|
states={
|
||||||
'invisible': ~Eval('media_mime', '').in_(['image/png', 'image/jpg', 'image/jpeg']),
|
'invisible': ~Eval('media_mime', '').in_([
|
||||||
}, depends=['media_mime']),
|
'image/png', 'image/jpg', 'image/jpeg']),
|
||||||
'on_change_with_media_image')
|
}, depends=['media_mime']), 'on_change_with_media_image')
|
||||||
|
|
||||||
@fields.depends('media', 'media_mime')
|
@fields.depends('media', 'media_mime')
|
||||||
def on_change_with_media_image(self, name=True):
|
def on_change_with_media_image(self, name=True):
|
||||||
|
@ -83,7 +85,7 @@ class Line(metaclass=PoolMeta):
|
||||||
"""
|
"""
|
||||||
image_data2 = None
|
image_data2 = None
|
||||||
with BytesIO(image_data) as fhdl:
|
with BytesIO(image_data) as fhdl:
|
||||||
try :
|
try:
|
||||||
image = Image.open(fhdl, 'r')
|
image = Image.open(fhdl, 'r')
|
||||||
except UnidentifiedImageError:
|
except UnidentifiedImageError:
|
||||||
raise UserError(gettext('cashbook_media.msg_file_unknown_type'))
|
raise UserError(gettext('cashbook_media.msg_file_unknown_type'))
|
||||||
|
@ -93,7 +95,7 @@ class Line(metaclass=PoolMeta):
|
||||||
|
|
||||||
if width > height:
|
if width > height:
|
||||||
new_size = (image_limit, int(height * image_limit / width))
|
new_size = (image_limit, int(height * image_limit / width))
|
||||||
else :
|
else:
|
||||||
new_size = (int(width * image_limit / height), image_limit)
|
new_size = (int(width * image_limit / height), image_limit)
|
||||||
|
|
||||||
# resize - fit in (image_limit x image_limit)
|
# resize - fit in (image_limit x image_limit)
|
||||||
|
@ -116,15 +118,17 @@ class Line(metaclass=PoolMeta):
|
||||||
values['media_mime'] = None
|
values['media_mime'] = None
|
||||||
values['media_size'] = None
|
values['media_size'] = None
|
||||||
values['media_name'] = None
|
values['media_name'] = None
|
||||||
else :
|
else:
|
||||||
values['media_mime'] = cls._identify_file(values['media'][:1024])
|
values['media_mime'] = cls._identify_file(values['media'][:1024])
|
||||||
|
|
||||||
# if its a image, resize it to fit in (image_limit x image_limit) pixel
|
# if its a image, resize it to fit
|
||||||
|
# in (image_limit x image_limit) pixel
|
||||||
if values['media_mime'].startswith('image'):
|
if values['media_mime'].startswith('image'):
|
||||||
new_image = cls.resize_image_file(values['media'])
|
new_image = cls.resize_image_file(values['media'])
|
||||||
if new_image is not None:
|
if new_image is not None:
|
||||||
values['media'] = new_image
|
values['media'] = new_image
|
||||||
values['media_mime'] = cls._identify_file(values['media'][:1024])
|
values['media_mime'] = cls._identify_file(
|
||||||
|
values['media'][:1024])
|
||||||
|
|
||||||
values['media_size'] = len(values['media'])
|
values['media_size'] = len(values['media'])
|
||||||
file_ext = mimetypes.guess_extension(values['media_mime'])
|
file_ext = mimetypes.guess_extension(values['media_mime'])
|
||||||
|
@ -147,15 +151,14 @@ class Line(metaclass=PoolMeta):
|
||||||
if line.media_size > 1024*1024*5:
|
if line.media_size > 1024*1024*5:
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
'cashbook_media.msg_file_too_big',
|
'cashbook_media.msg_file_too_big',
|
||||||
recname = line.rec_name,
|
recname=line.rec_name))
|
||||||
))
|
if line.media_mime not in [
|
||||||
if not line.media_mime in ['application/pdf',
|
'application/pdf',
|
||||||
'image/png', 'image/jpg', 'image/jpeg']:
|
'image/png', 'image/jpg', 'image/jpeg']:
|
||||||
raise UserError(gettext(
|
raise UserError(gettext(
|
||||||
'cashbook_media.msg_file_invalid_mime',
|
'cashbook_media.msg_file_invalid_mime',
|
||||||
recname = line.rec_name,
|
recname=line.rec_name,
|
||||||
fmime = line.media_mime,
|
fmime=line.media_mime))
|
||||||
))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(cls, vlist):
|
def create(cls, vlist):
|
||||||
|
|
66
setup.py
66
setup.py
|
@ -2,7 +2,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Always prefer setuptools over distutils
|
# Always prefer setuptools over distutils
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup
|
||||||
# To use a consistent encoding
|
# To use a consistent encoding
|
||||||
from codecs import open
|
from codecs import open
|
||||||
from os import path
|
from os import path
|
||||||
|
@ -36,7 +36,7 @@ with open(path.join(here, 'versiondep.txt'), encoding='utf-8') as f:
|
||||||
l2 = i.strip().split(';')
|
l2 = i.strip().split(';')
|
||||||
if len(l2) < 4:
|
if len(l2) < 4:
|
||||||
continue
|
continue
|
||||||
modversion[l2[0]] = {'min':l2[1], 'max':l2[2], 'prefix':l2[3]}
|
modversion[l2[0]] = {'min': l2[1], 'max': l2[2], 'prefix': l2[3]}
|
||||||
|
|
||||||
# tryton-version
|
# tryton-version
|
||||||
major_version = 6
|
major_version = 6
|
||||||
|
@ -51,19 +51,26 @@ for dep in info.get('depends', []):
|
||||||
prefix = modversion[dep]['prefix']
|
prefix = modversion[dep]['prefix']
|
||||||
|
|
||||||
if len(modversion[dep]['max']) > 0:
|
if len(modversion[dep]['max']) > 0:
|
||||||
requires.append('%s_%s >= %s, <= %s' %
|
requires.append(
|
||||||
(prefix, dep, modversion[dep]['min'], modversion[dep]['max']))
|
'%s_%s >= %s, <= %s' %
|
||||||
else :
|
(prefix, dep,
|
||||||
requires.append('%s_%s >= %s' %
|
modversion[dep]['min'],
|
||||||
|
modversion[dep]['max']))
|
||||||
|
else:
|
||||||
|
requires.append(
|
||||||
|
'%s_%s >= %s' %
|
||||||
(prefix, dep, modversion[dep]['min']))
|
(prefix, dep, modversion[dep]['min']))
|
||||||
else :
|
else:
|
||||||
requires.append('%s_%s >= %s.%s, < %s.%s' %
|
requires.append(
|
||||||
('trytond', dep, major_version, minor_version,
|
'%s_%s >= %s.%s, < %s.%s' % (
|
||||||
major_version, minor_version + 1))
|
'trytond', dep, major_version, minor_version,
|
||||||
requires.append('trytond >= %s.%s, < %s.%s' %
|
major_version, minor_version + 1))
|
||||||
(major_version, minor_version, major_version, minor_version + 1))
|
requires.append(
|
||||||
|
'trytond >= %s.%s, < %s.%s' % (
|
||||||
|
major_version, minor_version, major_version, minor_version + 1))
|
||||||
|
|
||||||
setup(name='%s_%s' % (PREFIX, MODULE),
|
setup(
|
||||||
|
name='%s_%s' % (PREFIX, MODULE),
|
||||||
version=info.get('version', '0.0.1'),
|
version=info.get('version', '0.0.1'),
|
||||||
description='Tryton module to add a file-field to cashbook.',
|
description='Tryton module to add a file-field to cashbook.',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
|
@ -74,21 +81,21 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
author_email='service@m-ds.de',
|
author_email='service@m-ds.de',
|
||||||
license='GPL-3',
|
license='GPL-3',
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Environment :: Plugins',
|
'Environment :: Plugins',
|
||||||
'Framework :: Tryton',
|
'Framework :: Tryton',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Intended Audience :: Customer Service',
|
'Intended Audience :: Customer Service',
|
||||||
'Intended Audience :: Information Technology',
|
'Intended Audience :: Information Technology',
|
||||||
'Intended Audience :: Financial and Insurance Industry',
|
'Intended Audience :: Financial and Insurance Industry',
|
||||||
'Topic :: Office/Business',
|
'Topic :: Office/Business',
|
||||||
'Topic :: Office/Business :: Financial :: Accounting',
|
'Topic :: Office/Business :: Financial :: Accounting',
|
||||||
'Natural Language :: German',
|
'Natural Language :: German',
|
||||||
'Natural Language :: English',
|
'Natural Language :: English',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
],
|
],
|
||||||
|
|
||||||
keywords='tryton cashbook pdf png image file',
|
keywords='tryton cashbook pdf png image file',
|
||||||
|
@ -97,7 +104,8 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
'trytond.modules.%s' % MODULE,
|
'trytond.modules.%s' % MODULE,
|
||||||
],
|
],
|
||||||
package_data={
|
package_data={
|
||||||
'trytond.modules.%s' % MODULE: (info.get('xml', [])
|
'trytond.modules.%s' % MODULE: (
|
||||||
|
info.get('xml', [])
|
||||||
+ ['tryton.cfg', 'locale/*.po', 'tests/*.py',
|
+ ['tryton.cfg', 'locale/*.po', 'tests/*.py',
|
||||||
'view/*.xml', 'versiondep.txt', 'README.rst']),
|
'view/*.xml', 'versiondep.txt', 'README.rst']),
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,21 +4,14 @@
|
||||||
import trytond.tests.test_tryton
|
import trytond.tests.test_tryton
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from trytond.modules.cashbook_media.tests.test_line import LineTestCase
|
from .test_line import LineTestCase
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['suite']
|
__all__ = ['suite']
|
||||||
|
|
||||||
|
|
||||||
class CashbookTestCase(\
|
|
||||||
LineTestCase,
|
|
||||||
):
|
|
||||||
'Test cashbook module'
|
|
||||||
module = 'cashbook_media'
|
|
||||||
|
|
||||||
# end CashbookTestCase
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = trytond.tests.test_tryton.suite()
|
suite = trytond.tests.test_tryton.suite()
|
||||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CashbookTestCase))
|
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
|
||||||
|
LineTestCase))
|
||||||
return suite
|
return suite
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
from trytond.tests.test_tryton import with_transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from trytond.transaction import Transaction
|
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.modules.cashbook.tests import CashbookTestCase
|
from trytond.modules.cashbook.tests import CashbookTestCase
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
@ -126,8 +125,11 @@ class LineTestCase(CashbookTestCase):
|
||||||
self.assertEqual(book.state, 'open')
|
self.assertEqual(book.state, 'open')
|
||||||
|
|
||||||
# add invalid file
|
# add invalid file
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(
|
||||||
"The file type 'text/plain' of the record '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. (allowed: PNG, JPG, PDF)",
|
UserError,
|
||||||
|
"The file type 'text/plain' of the record " +
|
||||||
|
"'05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. " +
|
||||||
|
"(allowed: PNG, JPG, PDF)",
|
||||||
Book.write,
|
Book.write,
|
||||||
*[
|
*[
|
||||||
[book],
|
[book],
|
||||||
|
@ -146,8 +148,11 @@ class LineTestCase(CashbookTestCase):
|
||||||
])
|
])
|
||||||
|
|
||||||
# replace image at line-1 by invalid file
|
# replace image at line-1 by invalid file
|
||||||
self.assertRaisesRegex(UserError,
|
self.assertRaisesRegex(
|
||||||
"The file type 'text/plain' of the record '05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. (allowed: PNG, JPG, PDF)",
|
UserError,
|
||||||
|
"The file type 'text/plain' of the record " +
|
||||||
|
"'05/02/2022|Rev|1.00 usd|Text 2 [Cat1]' is not allowed. " +
|
||||||
|
"(allowed: PNG, JPG, PDF)",
|
||||||
Lines.write,
|
Lines.write,
|
||||||
*[
|
*[
|
||||||
[book.lines[0]],
|
[book.lines[0]],
|
||||||
|
@ -163,7 +168,6 @@ class LineTestCase(CashbookTestCase):
|
||||||
"""
|
"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Book = pool.get('cashbook.book')
|
Book = pool.get('cashbook.book')
|
||||||
Lines = pool.get('cashbook.line')
|
|
||||||
|
|
||||||
types = self.prep_type()
|
types = self.prep_type()
|
||||||
category = self.prep_category(cattype='in')
|
category = self.prep_category(cattype='in')
|
||||||
|
@ -226,3 +230,6 @@ class LineTestCase(CashbookTestCase):
|
||||||
self.assertEqual(img2.size, (2000, 837))
|
self.assertEqual(img2.size, (2000, 837))
|
||||||
|
|
||||||
# end LineTestCase
|
# end LineTestCase
|
||||||
|
|
||||||
|
|
||||||
|
del CashbookTestCase
|
||||||
|
|
Loading…
Reference in a new issue