diff --git a/.copier-answers.yml b/.copier-answers.yml index f23d2e3a..f8bcd1f4 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -11,7 +11,7 @@ github_enable_makepot: false github_enable_stale_action: true github_enforce_dev_status_compatibility: false include_wkhtmltopdf: false -odoo_version: 16.0 +odoo_version: 17.0 org_name: Camptocamp org_slug: camptocamp rebel_module_groups: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f4f16d33..781b64af 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -3,11 +3,11 @@ name: pre-commit on: pull_request: branches: - - "16.0*" + - "17.0*" push: branches: - - "16.0" - - "16.0-ocabot-*" + - "17.0" + - "17.0-ocabot-*" jobs: pre-commit: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2e29c9d..dbe89204 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,11 +3,11 @@ name: tests on: pull_request: branches: - - "16.0*" + - "17.0*" push: branches: - - "16.0" - - "16.0-ocabot-*" + - "17.0" + - "17.0-ocabot-*" jobs: unreleased-deps: @@ -35,18 +35,18 @@ jobs: fail-fast: false matrix: include: - - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest + - container: ghcr.io/oca/oca-ci/py3.10-odoo17.0:latest include: "attachment_azure,cloud_platform_azure" makepot: "false" name: test azure with Odoo - - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest + - container: ghcr.io/oca/oca-ci/py3.10-ocb17.0:latest include: "attachment_azure,cloud_platform_azure" name: test azure with OCA - - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest + - container: ghcr.io/oca/oca-ci/py3.10-odoo17.0:latest exclude: "attachment_s3,cloud_platform_exoscale,attachment_swift,cloud_platform_ovh,attachment_azure,cloud_platform_azure" makepot: "false" name: test others with Odoo - - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest + - container: ghcr.io/oca/oca-ci/py3.10-ocb17.0:latest exclude: "attachment_s3,cloud_platform_exoscale,attachment_swift,cloud_platform_ovh,attachment_azure,cloud_platform_azure" name: test others with OCB services: diff --git a/.pylintrc b/.pylintrc index 54a5e915..b6a56d34 100644 --- a/.pylintrc +++ b/.pylintrc @@ -10,7 +10,7 @@ manifest_required_authors=Camptocamp manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=16.0 +valid_odoo_versions=17.0 [MESSAGES CONTROL] disable=all diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory index fedc3ea6..6fdf08b7 100644 --- a/.pylintrc-mandatory +++ b/.pylintrc-mandatory @@ -9,7 +9,7 @@ manifest_required_authors=Camptocamp manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=16.0 +valid_odoo_versions=17.0 [MESSAGES CONTROL] disable=all diff --git a/attachment_azure/pyproject.toml b/attachment_azure/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/attachment_azure/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/attachment_s3/README.rst b/attachment_s3/README.rst deleted file mode 100644 index 0d036993..00000000 --- a/attachment_s3/README.rst +++ /dev/null @@ -1,58 +0,0 @@ -Attachments on S3 storage -========================= - -This addon allows to store the attachments (documents and assets) on S3 or any -other S3-compatible Object Storage. - -Configuration -------------- - -Activate S3 storage: - -* Create or set the system parameter with the key ``ir_attachment.location`` - and the value in the form ``s3``. - -Configure accesses with environment variables: - -* ``AWS_HOST`` (not required if using AWS services) -* ``AWS_REGION`` (required if using AWS services) -* ``AWS_ACCESS_KEY_ID`` -* ``AWS_SECRET_ACCESS_KEY`` -* ``AWS_BUCKETNAME`` (optional {db} placeholder) - -Read-only mode: - -The bucket and the file key are stored in the attachment. So if you change the -``AWS_BUCKETNAME`` or the ``ir_attachment.location``, the existing attachments -will still be read on their former bucket. But as soon as they are written over -or new attachments are created, they will be created on the new bucket or on -the other location (db or filesystem). This is a convenient way to be able to -read the production attachments on a replication (since you have the -credentials) without any risk to alter the production data. - -This addon must be added in the server wide addons with (``--load`` option): - -``--load=web,attachment_s3`` - -The System Parameter ``ir_attachment.storage.force.database`` can be customized to -force storage of files in the database. See the documentation of the module -``base_attachment_object_storage``. - -Multi-tenancy -------------- - -Use the `{db}` placeholder to handle multi-tenancy. - -On instances that hold multiple databases, it's preferable to have one bucket per database. - -To handle this, you can insert the `{db}` placeholder in your bucket name variable ``AWS_BUCKETNAME``. -It will be replaced by the database name. -This will give you a unique bucketname per database. - - -Limitations ------------ - -* You need to call ``env['ir.attachment'].force_storage()`` after - having changed the ``ir_attachment.location`` configuration in order to - migrate the existing attachments to S3. diff --git a/attachment_s3/__init__.py b/attachment_s3/__init__.py deleted file mode 100644 index 0650744f..00000000 --- a/attachment_s3/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import models diff --git a/attachment_s3/__manifest__.py b/attachment_s3/__manifest__.py deleted file mode 100644 index 7958e620..00000000 --- a/attachment_s3/__manifest__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2016-2021 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -{ - "name": "Attachments on S3 storage", - "summary": "Store assets and attachments on a S3 compatible object storage", - "version": "15.0.1.0.0", - "author": "Camptocamp,Odoo Community Association (OCA)", - "license": "AGPL-3", - "category": "Knowledge Management", - "depends": ["base", "base_attachment_object_storage"], - "external_dependencies": { - "python": ["boto3"], - }, - "website": "https://github.com/camptocamp/odoo-cloud-platform", - "data": [], - "installable": False, -} diff --git a/attachment_s3/models/__init__.py b/attachment_s3/models/__init__.py deleted file mode 100644 index aaf38a16..00000000 --- a/attachment_s3/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import ir_attachment diff --git a/attachment_s3/models/ir_attachment.py b/attachment_s3/models/ir_attachment.py deleted file mode 100644 index d18c0e23..00000000 --- a/attachment_s3/models/ir_attachment.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright 2016-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -import io -import logging -import os -from urllib.parse import urlsplit - -from odoo import _, api, exceptions, models - -from ..s3uri import S3Uri - -_logger = logging.getLogger(__name__) - -try: - import boto3 - from botocore.exceptions import ClientError, EndpointConnectionError -except ImportError: - boto3 = None # noqa - ClientError = None # noqa - EndpointConnectionError = None # noqa - _logger.debug("Cannot 'import boto3'.") - - -class IrAttachment(models.Model): - _inherit = "ir.attachment" - - def _get_stores(self): - return ["s3"] + super()._get_stores() - - @api.model - def _get_s3_bucket(self, name=None): - """Connect to S3 and return the bucket - - The following environment variables can be set: - * ``AWS_HOST`` - * ``AWS_REGION`` - * ``AWS_ACCESS_KEY_ID`` - * ``AWS_SECRET_ACCESS_KEY`` - * ``AWS_BUCKETNAME`` - - If a name is provided, we'll read this bucket, otherwise, the bucket - from the environment variable ``AWS_BUCKETNAME`` will be read. - - """ - host = os.environ.get("AWS_HOST") - - # Ensure host is prefixed with a scheme (use https as default) - if host and not urlsplit(host).scheme: - host = "https://%s" % host - - region_name = os.environ.get("AWS_REGION") - access_key = os.environ.get("AWS_ACCESS_KEY_ID") - secret_key = os.environ.get("AWS_SECRET_ACCESS_KEY") - bucket_name = name or os.environ.get("AWS_BUCKETNAME") - # replaces {db} by the database name to handle multi-tenancy - bucket_name = bucket_name.format(db=self.env.cr.dbname) - - params = { - "aws_access_key_id": access_key, - "aws_secret_access_key": secret_key, - } - if host: - params["endpoint_url"] = host - if region_name: - params["region_name"] = region_name - if not (access_key and secret_key and bucket_name): - msg = _( - "If you want to read from the %(bucket_name)s S3 bucket, the following " - "environment variables must be set:\n" - "* AWS_ACCESS_KEY_ID\n" - "* AWS_SECRET_ACCESS_KEY\n" - "If you want to write in the %(bucket_name)s S3 bucket, this variable " - "must be set as well:\n" - "* AWS_BUCKETNAME\n" - "Optionally, the S3 host can be changed with:\n" - "* AWS_HOST\n" - ).format(bucket_name=bucket_name) - - raise exceptions.UserError(msg) - # try: - s3 = boto3.resource("s3", **params) - bucket = s3.Bucket(bucket_name) - exists = True - try: - s3.meta.client.head_bucket(Bucket=bucket_name) - except ClientError as e: - # If a client error is thrown, then check that it was a 404 error. - # If it was a 404 error, then the bucket does not exist. - error_code = e.response["Error"]["Code"] - if error_code == "404": - exists = False - except EndpointConnectionError as error: - # log verbose error from s3, return short message for user - msg = _logger.exception("Error during connection on S3") - raise exceptions.UserError(str(error)) from None - - if not exists: - if not region_name: - bucket = s3.create_bucket(Bucket=bucket_name) - else: - bucket = s3.create_bucket( - Bucket=bucket_name, - CreateBucketConfiguration={"LocationConstraint": region_name}, - ) - return bucket - - @api.model - def _store_file_read(self, fname): - if fname.startswith("s3://"): - s3uri = S3Uri(fname) - try: - bucket = self._get_s3_bucket(name=s3uri.bucket()) - except exceptions.UserError: - _logger.exception( - "error reading attachment '%s' from object storage", fname - ) - return "" - try: - key = s3uri.item() - bucket.meta.client.head_object(Bucket=bucket.name, Key=key) - with io.BytesIO() as res: - bucket.download_fileobj(key, res) - res.seek(0) - read = res.read() - except ClientError: - read = "" - _logger.info("attachment '%s' missing on object storage", fname) - return read - else: - return super()._store_file_read(fname) - - @api.model - def _store_file_write(self, key, bin_data): - location = self.env.context.get("storage_location") or self._storage() - if location == "s3": - bucket = self._get_s3_bucket() - obj = bucket.Object(key=key) - with io.BytesIO() as file: - file.write(bin_data) - file.seek(0) - filename = "s3://%s/%s" % (bucket.name, key) - try: - obj.upload_fileobj(file) - except ClientError as error: - # log verbose error from s3, return short message for user - _logger.exception("Error during storage of the file %s" % filename) - raise exceptions.UserError( - _("The file could not be stored: %s") % str(error) - ) from None - else: - _super = super() - filename = _super._store_file_write(key, bin_data) - return filename - - @api.model - def _store_file_delete(self, fname): - if fname.startswith("s3://"): - s3uri = S3Uri(fname) - bucket_name = s3uri.bucket() - item_name = s3uri.item() - # delete the file only if it is on the current configured bucket - # otherwise, we might delete files used on a different environment - if bucket_name == os.environ.get("AWS_BUCKETNAME"): - bucket = self._get_s3_bucket() - obj = bucket.Object(key=item_name) - try: - bucket.meta.client.head_object(Bucket=bucket.name, Key=item_name) - obj.delete() - _logger.info("file %s deleted on the object storage" % (fname,)) - except ClientError: - # log verbose error from s3, return short message for - # user - _logger.exception("Error during deletion of the file %s" % fname) - else: - return super()._store_file_delete(fname) diff --git a/attachment_s3/s3uri.py b/attachment_s3/s3uri.py deleted file mode 100644 index a7054ebd..00000000 --- a/attachment_s3/s3uri.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -import re - - -class S3Uri(object): - - _url_re = re.compile("^s3:///*([^/]*)/?(.*)", re.IGNORECASE | re.UNICODE) - - def __init__(self, uri): - match = self._url_re.match(uri) - if not match: - raise ValueError("%s: is not a valid S3 URI" % (uri,)) - self._bucket, self._item = match.groups() - - def bucket(self): - return self._bucket - - def item(self): - return self._item diff --git a/attachment_swift/README.rst b/attachment_swift/README.rst deleted file mode 100644 index 619f58e0..00000000 --- a/attachment_swift/README.rst +++ /dev/null @@ -1,60 +0,0 @@ -Attachments on Swift storage -============================ - -This addon enable storing attachments (documents and assets) on OpenStack Object Storage (Swift) - -Configuration -------------- - -Activate Swift storage: - -* Create or set the system parameter with the key ``ir_attachment.location`` with the following value ``swift``. - -Configure accesses with environment variables: - -* ``SWIFT_AUTH_URL`` : URL of the Swift server -* ``SWIFT_TENANT_NAME`` : **!** DEPRECATED **!** Use ``SWIFT_PROJECT_NAME`` instead -* ``SWIFT_PROJECT_NAME`` -* ``SWIFT_ACCOUNT`` -* ``SWIFT_PASSWORD`` -* ``SWIFT_REGION_NAME`` : optional region -* ``SWIFT_WRITE_CONTAINER`` : Name of the container to use in the store (created if not existing) - -Read-only mode: - -The container name and the key are stored in the attachment. So if you change the -``SWIFT_WRITE_CONTAINER`` or the ``ir_attachment.location``, the existing attachments -will still be read on their former container. But as soon as they are written over -or new attachments are created, they will be created on the new container or on -the other location (db or filesystem). This is a convenient way to be able to -read the production attachments on a replication (since you have the -credentials) without any risk to alter the production data. - -This addon must be added in the server wide addons with (``--load`` option): - -``--load=web,attachment_swift`` - -The System Parameter ``ir_attachment.storage.force.database`` can be customized to -force storage of files in the database. See the documentation of the module -``base_attachment_object_storage``. - -Python Dependencies -------------------- - -This module needs the python-swiftclient and the python-keystoneclient (For auth v3.0) to work. -The python-keystoneclient needs the linux package build-essential and python-dev to install properly. - -The python-swiftclient can be used from the command line, useful to test: - -.. code-block:: sh - - export AUTH_VERSION=3.0 - export OS_USERNAME={SWIFT_ACCOUNT} - export OS_PASSWORD={SWIFT_PASSWORD} - export OS_PROJECT_NAME={SWIFT_PROJECT_NAME} - export OS_REGION_NAME={SWIFT_REGION_NAME} - export OS_AUTH_URL=https://auth.cloud.ovh.net/v3 - swift stat - -More information at -https://docs.openstack.org/python-swiftclient/latest/cli/index.html#swift-usage diff --git a/attachment_swift/__init__.py b/attachment_swift/__init__.py deleted file mode 100644 index 0650744f..00000000 --- a/attachment_swift/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import models diff --git a/attachment_swift/__manifest__.py b/attachment_swift/__manifest__.py deleted file mode 100644 index d0c2ed9c..00000000 --- a/attachment_swift/__manifest__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2017-2021 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -{ - "name": "Attachments on Swift storage", - "summary": "Store assets and attachments on a Swift compatible object store", - "version": "15.0.1.0.0", - "author": "Camptocamp,Odoo Community Association (OCA)", - "license": "AGPL-3", - "category": "Knowledge Management", - "depends": ["base_attachment_object_storage"], - "external_dependencies": { - "python": [ - "swiftclient", - "keystoneclient", - "keystoneauth1", - ], - }, - "website": "https://github.com/camptocamp/odoo-cloud-platform", - "data": [], - "installable": False, -} diff --git a/attachment_swift/models/__init__.py b/attachment_swift/models/__init__.py deleted file mode 100644 index aaf38a16..00000000 --- a/attachment_swift/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import ir_attachment diff --git a/attachment_swift/models/ir_attachment.py b/attachment_swift/models/ir_attachment.py deleted file mode 100644 index 6a8b088a..00000000 --- a/attachment_swift/models/ir_attachment.py +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2017-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -import logging -import os - -from odoo import _, api, exceptions, models - -from ..swift_uri import SwiftUri - -_logger = logging.getLogger(__name__) - -try: - import keystoneauth1 - import keystoneauth1.identity - import keystoneauth1.session - import swiftclient - from swiftclient.exceptions import ClientException -except ImportError: - swiftclient = None - ClientException = None - _logger.debug("Cannot 'import swiftclient'.") - - -SWIFT_TIMEOUT = 15 - - -class SwiftSessionStore(object): - """Keep in memory the current Swift Auth session - - The auth endpoint has a rate limit on swift, if every operation - on the filestore authenticate, the limit is exhausted and - operations rejected with an HTTP error code 429. - - Swift connections can reuse the same session by asking a session - matching their connection parameters with ``get_session``. - - The keystoneauth1's session automatically creates a new token - if the previous one is expired. - - The best documentation I found about sessions is - https://docs.openstack.org/keystoneauth/latest/using-sessions.html - """ - - def __init__(self): - self._sessions = {} - - def _get_key(self, auth_url, username, password, project_name): - return (auth_url, username, password, project_name) - - def get_session( - self, auth_url=None, username=None, password=None, project_name=None - ): - key = self._get_key(auth_url, username, password, project_name) - session = self._sessions.get(key) - if not session: - auth = keystoneauth1.identity.v3.Password( - username=username, - password=password, - project_name=project_name, - auth_url=auth_url, - project_domain_id="default", - user_domain_id="default", - ) - session = keystoneauth1.session.Session( - auth=auth, - timeout=SWIFT_TIMEOUT, - ) - self._sessions[key] = session - return session - - -swift_session_store = SwiftSessionStore() - - -class IrAttachment(models.Model): - _inherit = "ir.attachment" - - def _get_stores(self): - return ["swift"] + super()._get_stores() - - @api.model - def _get_swift_connection(self): - """Returns a connection object for the Swift object store""" - host = os.environ.get("SWIFT_AUTH_URL") - account = os.environ.get("SWIFT_ACCOUNT") - password = os.environ.get("SWIFT_PASSWORD") - project_name = os.environ.get("SWIFT_PROJECT_NAME") - if not project_name and os.environ.get("SWIFT_TENANT_NAME"): - project_name = os.environ["SWIFT_TENANT_NAME"] - _logger.warning( - "SWIFT_TENANT_NAME is deprecated and " - "must be replaced by SWIFT_PROJECT_NAME" - ) - region = os.environ.get("SWIFT_REGION_NAME") - os_options = {} - if region: - os_options["region_name"] = region - if not (host and account and password and project_name): - raise exceptions.UserError( - _( - "Problem connecting to Swift store, are the env variables " - "(SWIFT_AUTH_URL, SWIFT_ACCOUNT, SWIFT_PASSWORD, " - "SWIFT_TENANT_NAME) properly set?" - ) - ) - try: - session = swift_session_store.get_session( - username=account, - password=password, - project_name=project_name, - auth_url=host, - ) - conn = swiftclient.client.Connection( - session=session, - os_options=os_options, - ) - except ClientException: - _logger.exception("Error connecting to Swift object store") - raise exceptions.UserError(_("Error on Swift connection")) from None - return conn - - @api.model - def _store_file_read(self, fname): - if fname.startswith("swift://"): - swifturi = SwiftUri(fname) - try: - conn = self._get_swift_connection() - except exceptions.UserError: - _logger.exception( - "error reading attachment '%s' from object storage", fname - ) - return "" - try: - resp, read = conn.get_object(swifturi.container(), swifturi.item()) - except ClientException: - read = "" - _logger.exception("Error reading object from Swift object store") - return read - else: - return super()._store_file_read(fname) - - def _store_file_write(self, key, bin_data): - if self._storage() == "swift": - container = os.environ.get("SWIFT_WRITE_CONTAINER") - conn = self._get_swift_connection() - conn.put_container(container) - filename = "swift://{}/{}".format(container, key) - try: - conn.put_object(container, key, bin_data) - except ClientException: - _logger.exception("Error writing to Swift object store") - raise exceptions.UserError(_("Error writing to Swift")) from None - else: - _super = super() - filename = _super._store_file_write(key, bin_data) - return filename - - @api.model - def _store_file_delete(self, fname): - if fname.startswith("swift://"): - swifturi = SwiftUri(fname) - container = swifturi.container() - # delete the file only if it is on the current configured bucket - # otherwise, we might delete files used on a different environment - if container == os.environ.get("SWIFT_WRITE_CONTAINER"): - conn = self._get_swift_connection() - try: - conn.delete_object(container, swifturi.item()) - except ClientException: - _logger.exception(_("Error deleting an object on the Swift store")) - # we ignore the error, file will stay on the object - # storage but won't disrupt the process - else: - return super()._file_delete_from_store(fname) diff --git a/attachment_swift/swift_uri.py b/attachment_swift/swift_uri.py deleted file mode 100644 index f12c841f..00000000 --- a/attachment_swift/swift_uri.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2017-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -import re - - -class SwiftUri(object): - - _url_re = re.compile("^swift:///*([^/]*)/?(.*)", re.IGNORECASE | re.UNICODE) - - def __init__(self, uri): - match = self._url_re.match(uri) - if not match: - raise ValueError("%s: is not a valid Swift URI" % (uri,)) - self._container, self._item = match.groups() - - def container(self): - return self._container - - def item(self): - return self._item diff --git a/attachment_swift/tests/__init__.py b/attachment_swift/tests/__init__.py deleted file mode 100644 index 8a60b377..00000000 --- a/attachment_swift/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import test_mock_swift_api diff --git a/attachment_swift/tests/test_mock_swift_api.py b/attachment_swift/tests/test_mock_swift_api.py deleted file mode 100644 index a13a80f5..00000000 --- a/attachment_swift/tests/test_mock_swift_api.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright 2017-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -import base64 -import os - -import keystoneauth1 -import mock -from mock import patch - -from odoo.addons.attachment_swift.models.ir_attachment import SwiftSessionStore -from odoo.addons.attachment_swift.swift_uri import SwiftUri -from odoo.addons.base.tests.test_ir_attachment import TestIrAttachment - - -class TestAttachmentSwift(TestIrAttachment): - def setup(self): - res = super().setUp() - self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift") - return res - - def test_session_store_get_session(self): - auth_url = "auth_url" - username = "username" - password = "password" - project_name = "project_name" - store = SwiftSessionStore() - session = store.get_session( - auth_url=auth_url, - username=username, - password=password, - project_name=project_name, - ) - self.assertEqual(session.auth.auth_url, auth_url) - self.assertEqual( - session.auth.get_cache_id_elements().get("password_username"), username - ) - self.assertEqual( - session.auth.get_cache_id_elements().get("password_password"), password - ) - self.assertEqual(session.auth.project_name, project_name) - - # get the same session on a second call - self.assertEqual( - store.get_session( - auth_url=auth_url, - username=username, - password=password, - project_name=project_name, - ), - session, - ) - - @patch("swiftclient.client") - def test_connection(self, mock_swift_client): - """Test the connection to the store""" - os.environ["SWIFT_AUTH_URL"] = "auth_url" - os.environ["SWIFT_ACCOUNT"] = "account" - os.environ["SWIFT_PASSWORD"] = "password" - os.environ["SWIFT_PROJECT_NAME"] = "project_name" - os.environ["SWIFT_REGION_NAME"] = "NOWHERE" - attachment = self.Attachment - attachment._get_swift_connection() - mock_swift_client.Connection.assert_called_once_with( - session=mock.ANY, - os_options={"region_name": os.environ.get("SWIFT_REGION_NAME")}, - ) - __, kwargs = mock_swift_client.Connection.call_args - session = kwargs["session"] - self.assertTrue(isinstance(session, keystoneauth1.session.Session)) - self.assertEqual(session.auth.auth_url, os.environ["SWIFT_AUTH_URL"]) - self.assertEqual( - session.auth.get_cache_id_elements().get("password_username"), - os.environ["SWIFT_ACCOUNT"], - ) - self.assertEqual( - session.auth.get_cache_id_elements().get("password_password"), - os.environ["SWIFT_PASSWORD"], - ) - self.assertEqual(session.auth.project_name, os.environ["SWIFT_PROJECT_NAME"]) - - def test_store_file_on_swift(self): - """ - Test writing a file - """ - (self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift")) - os.environ["SWIFT_AUTH_URL"] = "auth_url" - os.environ["SWIFT_ACCOUNT"] = "account" - os.environ["SWIFT_PASSWORD"] = "password" - os.environ["SWIFT_PROJECT_NAME"] = "project_name" - os.environ["SWIFT_WRITE_CONTAINER"] = "my_container" - container = os.environ.get("SWIFT_WRITE_CONTAINER") - attachment = self.Attachment - bin_data = base64.b64decode(self.blob1_b64) - with patch("swiftclient.client.Connection") as MockConnection: - conn = MockConnection.return_value - attachment.create({"name": "a5", "datas": self.blob1_b64}) - conn.put_object.assert_called_with( - container, attachment._compute_checksum(bin_data), bin_data - ) - - def test_delete_file_on_swift(self): - """ - Test deleting a file - """ - (self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift")) - os.environ["SWIFT_AUTH_URL"] = "auth_url" - os.environ["SWIFT_ACCOUNT"] = "account" - os.environ["SWIFT_PASSWORD"] = "password" - os.environ["SWIFT_PROJECT_NAME"] = "project_name" - os.environ["SWIFT_WRITE_CONTAINER"] = "my_container" - - attachment = self.Attachment - container = os.environ.get("SWIFT_WRITE_CONTAINER") - with patch("swiftclient.client.Connection") as MockConnection: - conn = MockConnection.return_value - a5 = attachment.create({"name": "a5", "datas": self.blob1_b64}) - uri = SwiftUri(a5.store_fname) - a5.unlink() - conn.delete_object.assert_called_with(container, uri.item()) diff --git a/attachment_swift/tests/test_with_swift_store.py b/attachment_swift/tests/test_with_swift_store.py deleted file mode 100644 index 83823b6b..00000000 --- a/attachment_swift/tests/test_with_swift_store.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2017-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -from swiftclient.exceptions import ClientException - -from odoo.addons.base.tests.test_ir_attachment import TestIrAttachment - -from ..swift_uri import SwiftUri - - -class TestAttachmentSwift(TestIrAttachment): - """ - Those tests are made to be run against a real Swift store (local or remote) - """ - - def setup(self): - res = super().setUp() - self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift") - return res - - def test_connection(self): - """Test the connection to the Swift object store""" - conn = self.Attachment._get_swift_connection() - self.assertNotEqual(conn, False) - - def test_store_file_on_swift(self): - """Test writing a file and then reading it""" - (self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift")) - a5 = self.Attachment.create({"name": "a5", "datas": self.blob1_b64}) - a5bis = self.Attachment.browse(a5.id)[0] - self.assertEqual(a5.datas, a5bis.datas) - - def test_delete_file_on_swift(self): - """Create a file and then test the deletion""" - (self.env["ir.config_parameter"].set_param("ir_attachment.location", "swift")) - a5 = self.Attachment.create({"name": "a5", "datas": self.blob1_b64}) - uri = SwiftUri(a5.store_fname) - con = self.Attachment._get_swift_connection() - con.get_object(uri.container(), uri.item()) - a5.unlink() - with self.assertRaises(ClientException): - con.get_object(uri.container(), uri.item()) diff --git a/base_attachment_object_storage/pyproject.toml b/base_attachment_object_storage/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/base_attachment_object_storage/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/base_fileurl_field/pyproject.toml b/base_fileurl_field/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/base_fileurl_field/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/cloud_platform/pyproject.toml b/cloud_platform/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/cloud_platform/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/cloud_platform_azure/pyproject.toml b/cloud_platform_azure/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/cloud_platform_azure/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/cloud_platform_exoscale/README.md b/cloud_platform_exoscale/README.md deleted file mode 100644 index 3c815ed0..00000000 --- a/cloud_platform_exoscale/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Cloud Platform Exoscale - -Install addons specific to the Exoscale setup. - - * The object storage is S3 diff --git a/cloud_platform_exoscale/__init__.py b/cloud_platform_exoscale/__init__.py deleted file mode 100644 index 0650744f..00000000 --- a/cloud_platform_exoscale/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import models diff --git a/cloud_platform_exoscale/__manifest__.py b/cloud_platform_exoscale/__manifest__.py deleted file mode 100644 index 45ead050..00000000 --- a/cloud_platform_exoscale/__manifest__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2017-2021 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -{ - "name": "Cloud Platform Exoscale", - "summary": "Addons required for the Camptocamp Cloud Platform on Exoscale", - "version": "15.0.1.0.0", - "author": "Camptocamp,Odoo Community Association (OCA)", - "license": "AGPL-3", - "category": "Extra Tools", - "depends": [ - "cloud_platform", - "attachment_s3", - "monitoring_statsd", - ], - "excludes": [ - "cloud_platform_ovh", - ], - "website": "https://github.com/camptocamp/odoo-cloud-platform", - "data": [], - "installable": False, -} diff --git a/cloud_platform_exoscale/models/__init__.py b/cloud_platform_exoscale/models/__init__.py deleted file mode 100644 index 5d08f36c..00000000 --- a/cloud_platform_exoscale/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import cloud_platform diff --git a/cloud_platform_exoscale/models/cloud_platform.py b/cloud_platform_exoscale/models/cloud_platform.py deleted file mode 100644 index 66702fdb..00000000 --- a/cloud_platform_exoscale/models/cloud_platform.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright 2016-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -import os -import re - -from odoo import api, models - -from odoo.addons.cloud_platform.models.cloud_platform import ( - FilestoreKind, - PlatformConfig, -) - -S3_STORE_KIND = FilestoreKind("s3", "remote") - - -class CloudPlatform(models.AbstractModel): - _inherit = "cloud.platform" - - @api.model - def _filestore_kinds(self): - kinds = super(CloudPlatform, self)._filestore_kinds() - kinds["s3"] = S3_STORE_KIND - return kinds - - @api.model - def _platform_kinds(self): - kinds = super(CloudPlatform, self)._platform_kinds() - kinds.append("exoscale") - return kinds - - @api.model - def _config_by_server_env_for_exoscale(self): - fs_kinds = self._filestore_kinds() - configs = { - "prod": PlatformConfig(filestore=fs_kinds["s3"]), - "integration": PlatformConfig(filestore=fs_kinds["s3"]), - "labs": PlatformConfig(filestore=fs_kinds["s3"]), - "test": PlatformConfig(filestore=fs_kinds["db"]), - "dev": PlatformConfig(filestore=fs_kinds["db"]), - } - return configs - - @api.model - def _check_filestore(self, environment_name): - params = self.env["ir.config_parameter"].sudo() - use_s3 = params.get_param("ir_attachment.location") == S3_STORE_KIND.name - if environment_name in ("prod", "integration"): - # Labs instances use s3 by default, but we don't want - # to enforce it in case we want to test something with a different - # storage. At your own risks! - assert use_s3, ( - "S3 must be used on production and integration instances. " - "It is activated by setting 'ir_attachment.location.' to 's3'." - " The 'install()' function sets this option " - "automatically." - ) - if use_s3: - assert os.environ.get("AWS_ACCESS_KEY_ID"), ( - "AWS_ACCESS_KEY_ID environment variable is required when " - "ir_attachment.location is 's3'." - ) - assert os.environ.get("AWS_SECRET_ACCESS_KEY"), ( - "AWS_SECRET_ACCESS_KEY environment variable is required when " - "ir_attachment.location is 's3'." - ) - bucket_name = os.environ.get("AWS_BUCKETNAME", "") - if environment_name in ("prod", "integration", "labs"): - assert bucket_name, ( - "AWS_BUCKETNAME environment variable is required when " - "ir_attachment.location is 's3'.\n" - "Normally, 's3' is activated on labs, integration " - "and production, but should not be used in dev environment" - " (or using a dedicated dev bucket, never using the " - "integration/prod bucket).\n" - "If you don't actually need a bucket, change the" - " 'ir_attachment.location' parameter." - ) - # A bucket name is defined under the following format - # -odoo- - # - # Use AWS_BUCKETNAME_UNSTRUCTURED to by-pass check on bucket name - # structure - if os.environ.get("AWS_BUCKETNAME_UNSTRUCTURED"): - return - prod_bucket = bool(re.match(r"[a-z-0-9]+-odoo-prod", bucket_name)) - if environment_name == "prod": - assert prod_bucket, ( - "AWS_BUCKETNAME should match '-odoo-prod', " - "we got: '%s'" % (bucket_name,) - ) - else: - # if we are using the prod bucket on another instance - # such as an integration, we must be sure to be in read only! - assert not prod_bucket, ( - "AWS_BUCKETNAME should not match '-odoo-prod', " - "we got: '%s'" % (bucket_name,) - ) - - elif environment_name == "test": - # store in DB so we don't have files local to the host - assert params.get_param("ir_attachment.location") == "db", ( - "In test instances, files must be stored in the database with " - "'ir_attachment.location' set to 'db'. This is " - "automatically set by the function 'install()'." - ) - - @api.model - def install(self): - self._install("exoscale") diff --git a/cloud_platform_ovh/README.md b/cloud_platform_ovh/README.md deleted file mode 100644 index f82fe48d..00000000 --- a/cloud_platform_ovh/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Cloud Platform OVH - -Install addons specific to the OVH setup. - - * The object storage is Swift diff --git a/cloud_platform_ovh/__init__.py b/cloud_platform_ovh/__init__.py deleted file mode 100644 index 0650744f..00000000 --- a/cloud_platform_ovh/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import models diff --git a/cloud_platform_ovh/__manifest__.py b/cloud_platform_ovh/__manifest__.py deleted file mode 100644 index 8f22580e..00000000 --- a/cloud_platform_ovh/__manifest__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2017-2021 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - - -{ - "name": "Cloud Platform OVH", - "summary": "Addons required for the Camptocamp Cloud Platform on OVH", - "version": "15.0.1.0.0", - "author": "Camptocamp,Odoo Community Association (OCA)", - "license": "AGPL-3", - "category": "Extra Tools", - "depends": [ - "cloud_platform", - "attachment_swift", - "monitoring_statsd", - ], - "excludes": [ - "cloud_platform_exoscale", - ], - "website": "https://github.com/camptocamp/odoo-cloud-platform", - "data": [], - "installable": False, -} diff --git a/cloud_platform_ovh/models/__init__.py b/cloud_platform_ovh/models/__init__.py deleted file mode 100644 index 5d08f36c..00000000 --- a/cloud_platform_ovh/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import cloud_platform diff --git a/cloud_platform_ovh/models/cloud_platform.py b/cloud_platform_ovh/models/cloud_platform.py deleted file mode 100644 index bed4db9a..00000000 --- a/cloud_platform_ovh/models/cloud_platform.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2017-2019 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -import os -import re - -from odoo import api, models - -from odoo.addons.cloud_platform.models.cloud_platform import ( - FilestoreKind, - PlatformConfig, -) - -SWIFT_STORE_KIND = FilestoreKind("swift", "remote") - - -class CloudPlatform(models.AbstractModel): - _inherit = "cloud.platform" - - @api.model - def _filestore_kinds(self): - kinds = super(CloudPlatform, self)._filestore_kinds() - kinds["swift"] = SWIFT_STORE_KIND - return kinds - - @api.model - def _platform_kinds(self): - kinds = super()._platform_kinds() - kinds.append("ovh") - return kinds - - @api.model - def _config_by_server_env_for_ovh(self): - fs_kinds = self._filestore_kinds() - configs = { - "prod": PlatformConfig(filestore=fs_kinds["swift"]), - "integration": PlatformConfig(filestore=fs_kinds["swift"]), - "labs": PlatformConfig(filestore=fs_kinds["swift"]), - "test": PlatformConfig(filestore=fs_kinds["db"]), - "dev": PlatformConfig(filestore=fs_kinds["db"]), - } - return configs - - @api.model - def _check_filestore(self, environment_name): - params = self.env["ir.config_parameter"].sudo() - use_swift = params.get_param("ir_attachment.location") == SWIFT_STORE_KIND.name - if environment_name in ("prod", "integration"): - # Labs instances use swift by default, but we don't want - # to enforce it in case we want to test something with a different - # storage. At your own risks! - assert use_swift, ( - "Swift must be used on production and integration instances. " - "It is activated, setting 'ir_attachment.location.' to 'swift'" - " The 'install()' function sets this option " - "automatically." - ) - if use_swift: - assert os.environ.get("SWIFT_AUTH_URL"), ( - "SWIFT_AUTH_URL environment variable is required when " - "ir_attachment.location is 'swift'." - ) - assert os.environ.get("SWIFT_ACCOUNT"), ( - "SWIFT_ACCOUNT environment variable is required when " - "ir_attachment.location is 'swift'." - ) - assert os.environ.get("SWIFT_PASSWORD"), ( - "SWIFT_PASSWORD environment variable is required when " - "ir_attachment.location is 'swift'." - ) - container_name = os.environ.get("SWIFT_WRITE_CONTAINER", "") - if environment_name in ("prod", "integration", "labs"): - assert container_name, ( - "SWIFT_WRITE_CONTAINER environment variable is required when " - "ir_attachment.location is 'swift'.\n" - "Normally, 'swift' is activated on labs, integration " - "and production, but should not be used in dev environment" - " (or using a dedicated dev bucket, never using the " - "integration/prod bucket).\n" - "If you don't actually need a bucket, change the" - " 'ir_attachment.location' parameter." - ) - prod_container = bool(re.match(r"[a-z0-9-]+-odoo-prod", container_name)) - # A bucket name is defined under the following format - # -odoo- - # - # Use SWIFT_WRITE_CONTAINER_UNSTRUCTURED to by-pass check on bucket name - # structure - if os.environ.get("SWIFT_WRITE_CONTAINER_UNSTRUCTURED"): - return - if environment_name == "prod": - assert prod_container, ( - "SWIFT_WRITE_CONTAINER should match '-odoo-prod', " - "we got: '%s'" % (container_name,) - ) - else: - # if we are using the prod bucket on another instance - # such as an integration, we must be sure to be in read only! - assert not prod_container, ( - "SWIFT_WRITE_CONTAINER should not match " - "'-odoo-prod', we got: '%s'" % (container_name,) - ) - elif environment_name == "test": - # store in DB so we don't have files local to the host - assert params.get_param("ir_attachment.location") == "db", ( - "In test instances, files must be stored in the database with " - "'ir_attachment.location' set to 'db'. This is " - "automatically set by the function 'install()'." - ) - - @api.model - def install(self): - self._install("ovh") diff --git a/logging_json/pyproject.toml b/logging_json/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/logging_json/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/monitoring_log_requests/pyproject.toml b/monitoring_log_requests/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/monitoring_log_requests/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/monitoring_prometheus/pyproject.toml b/monitoring_prometheus/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/monitoring_prometheus/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/monitoring_statsd/pyproject.toml b/monitoring_statsd/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/monitoring_statsd/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/monitoring_status/pyproject.toml b/monitoring_status/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/monitoring_status/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/session_redis/pyproject.toml b/session_redis/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/session_redis/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/setup/.setuptools-odoo-make-default-ignore b/setup/.setuptools-odoo-make-default-ignore deleted file mode 100644 index 207e6153..00000000 --- a/setup/.setuptools-odoo-make-default-ignore +++ /dev/null @@ -1,2 +0,0 @@ -# addons listed in this file are ignored by -# setuptools-odoo-make-default (one addon per line) diff --git a/setup/README b/setup/README deleted file mode 100644 index a63d633e..00000000 --- a/setup/README +++ /dev/null @@ -1,2 +0,0 @@ -To learn more about this directory, please visit -https://pypi.python.org/pypi/setuptools-odoo diff --git a/setup/attachment_azure/odoo/addons/attachment_azure b/setup/attachment_azure/odoo/addons/attachment_azure deleted file mode 120000 index b6be12c0..00000000 --- a/setup/attachment_azure/odoo/addons/attachment_azure +++ /dev/null @@ -1 +0,0 @@ -../../../../attachment_azure \ No newline at end of file diff --git a/setup/attachment_azure/setup.py b/setup/attachment_azure/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/attachment_azure/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/base_attachment_object_storage/odoo/addons/base_attachment_object_storage b/setup/base_attachment_object_storage/odoo/addons/base_attachment_object_storage deleted file mode 120000 index 2e30a179..00000000 --- a/setup/base_attachment_object_storage/odoo/addons/base_attachment_object_storage +++ /dev/null @@ -1 +0,0 @@ -../../../../base_attachment_object_storage \ No newline at end of file diff --git a/setup/base_attachment_object_storage/setup.py b/setup/base_attachment_object_storage/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/base_attachment_object_storage/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/cloud_platform/odoo/addons/cloud_platform b/setup/cloud_platform/odoo/addons/cloud_platform deleted file mode 120000 index c065b916..00000000 --- a/setup/cloud_platform/odoo/addons/cloud_platform +++ /dev/null @@ -1 +0,0 @@ -../../../../cloud_platform \ No newline at end of file diff --git a/setup/cloud_platform/setup.py b/setup/cloud_platform/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/cloud_platform/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/cloud_platform_azure/odoo/addons/cloud_platform_azure b/setup/cloud_platform_azure/odoo/addons/cloud_platform_azure deleted file mode 120000 index 5d297223..00000000 --- a/setup/cloud_platform_azure/odoo/addons/cloud_platform_azure +++ /dev/null @@ -1 +0,0 @@ -../../../../cloud_platform_azure \ No newline at end of file diff --git a/setup/cloud_platform_azure/setup.py b/setup/cloud_platform_azure/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/cloud_platform_azure/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/kwkhtmltopdf_assets/odoo/addons/kwkhtmltopdf_assets b/setup/kwkhtmltopdf_assets/odoo/addons/kwkhtmltopdf_assets deleted file mode 120000 index 9d3daa29..00000000 --- a/setup/kwkhtmltopdf_assets/odoo/addons/kwkhtmltopdf_assets +++ /dev/null @@ -1 +0,0 @@ -../../../../kwkhtmltopdf_assets \ No newline at end of file diff --git a/setup/kwkhtmltopdf_assets/setup.py b/setup/kwkhtmltopdf_assets/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/kwkhtmltopdf_assets/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/logging_json/odoo/addons/logging_json b/setup/logging_json/odoo/addons/logging_json deleted file mode 120000 index 7e261fb7..00000000 --- a/setup/logging_json/odoo/addons/logging_json +++ /dev/null @@ -1 +0,0 @@ -../../../../logging_json \ No newline at end of file diff --git a/setup/logging_json/setup.py b/setup/logging_json/setup.py deleted file mode 100644 index ebf59b81..00000000 --- a/setup/logging_json/setup.py +++ /dev/null @@ -1,10 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon={ - 'external_dependencies_override': { - 'python': {'pythonjsonlogger': 'python-json-logger',}, - }, - }, -) diff --git a/setup/monitoring_prometheus/odoo/addons/monitoring_prometheus b/setup/monitoring_prometheus/odoo/addons/monitoring_prometheus deleted file mode 120000 index 34b5ef7f..00000000 --- a/setup/monitoring_prometheus/odoo/addons/monitoring_prometheus +++ /dev/null @@ -1 +0,0 @@ -../../../../monitoring_prometheus \ No newline at end of file diff --git a/setup/monitoring_prometheus/setup.py b/setup/monitoring_prometheus/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/monitoring_prometheus/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/monitoring_status/odoo/addons/monitoring_status b/setup/monitoring_status/odoo/addons/monitoring_status deleted file mode 120000 index b5a85e74..00000000 --- a/setup/monitoring_status/odoo/addons/monitoring_status +++ /dev/null @@ -1 +0,0 @@ -../../../../monitoring_status \ No newline at end of file diff --git a/setup/monitoring_status/setup.py b/setup/monitoring_status/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/monitoring_status/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/setup/session_redis/odoo/addons/session_redis b/setup/session_redis/odoo/addons/session_redis deleted file mode 120000 index c8732c21..00000000 --- a/setup/session_redis/odoo/addons/session_redis +++ /dev/null @@ -1 +0,0 @@ -../../../../session_redis \ No newline at end of file diff --git a/setup/session_redis/setup.py b/setup/session_redis/setup.py deleted file mode 100644 index 28c57bb6..00000000 --- a/setup/session_redis/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -import setuptools - -setuptools.setup( - setup_requires=['setuptools-odoo'], - odoo_addon=True, -) diff --git a/test_base_fileurl_field/pyproject.toml b/test_base_fileurl_field/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/test_base_fileurl_field/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi"