Skip to content

Commit

Permalink
NXPY-239: Fix tests cases on Python (#277)
Browse files Browse the repository at this point in the history
NXPY-239: Fix tests cases on Python
  • Loading branch information
gitofanindya authored Oct 17, 2022
1 parent ac10600 commit 01fe8f2
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 67 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ Changelog
6.0.4
-----

Release date: ``2021-xx-xx``
Release date: ``2022-xx-xx``

- `NXPY- <https://jira.nuxeo.com/browse/NXPY->`__:
- `NXPY-241 <https://jira.nuxeo.com/browse/NXPY-241>`__: Remove Support For Python 3.6
- `NXPY-240 <https://jira.nuxeo.com/browse/NXPY-240>`__: Upgrade Nuxeo Docker Image
- `NXPY-237 <https://jira.nuxeo.com/browse/NXPY-237>`__: Update Dependencies
- `NXPY-239 <https://jira.nuxeo.com/browse/NXPY-239>`__: Fix tests cases on Python

Technical changes
-----------------
Expand Down
6 changes: 3 additions & 3 deletions nuxeo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def on_exit(self):

def enable_retry(self):
# type: () -> None
""" Set a max retry for all connection errors with an adaptative backoff. """
"""Set a max retry for all connection errors with an adaptative backoff."""
self._session.mount(
"https://", TCPKeepAliveHTTPSAdapter(max_retries=self.retries)
)
Expand Down Expand Up @@ -352,7 +352,7 @@ def request_auth_token(

def is_reachable(self):
# type: () -> bool
""" Check if the Nuxeo Platform is reachable. """
"""Check if the Nuxeo Platform is reachable."""
response = self.request("GET", "runningstatus", default=False)
if isinstance(response, requests.Response):
return response.ok
Expand All @@ -379,7 +379,7 @@ def server_info(self, force=False):
@property
def server_version(self):
# type: () -> str
""" Return the server version or "unknown". """
"""Return the server version or "unknown"."""
try:
return self.server_info()["productVersion"]
except Exception:
Expand Down
16 changes: 13 additions & 3 deletions nuxeo/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@

from .comments import API as CommentsAPI
from .endpoint import APIEndpoint
from .exceptions import BadQuery, HTTPError, UnavailableConvertor
from .exceptions import (
BadQuery,
HTTPError,
UnavailableConvertor,
NotRegisteredConvertor,
UnavailableBogusConvertor,
)
from .models import Blob, Comment, Document, Workflow
from .operations import API as OperationsAPI
from .utils import version_lt
Expand Down Expand Up @@ -154,12 +160,16 @@ def convert(self, uid, options):
)
except HTTPError as e:
if "is not registered" in e.message:
raise BadQuery(e.message)
if (
raise NotRegisteredConvertor(options)
elif (
"is not available" in e.message
or "UnsupportedOperationException" in e.message
):
raise UnavailableConvertor(options)
elif "Internal Server Error" in e.message:
raise UnavailableBogusConvertor(
e.message, options["converter"] if options["converter"] else ""
)
raise e

def fetch_acls(self, uid):
Expand Down
75 changes: 64 additions & 11 deletions nuxeo/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class NuxeoError(Exception):
""" Mother class for all exceptions. """
"""Mother class for all exceptions."""


class BadQuery(NuxeoError):
Expand All @@ -20,7 +20,7 @@ class BadQuery(NuxeoError):


class CorruptedFile(NuxeoError):
""" Exception thrown when digests of a downloaded blob are different. """
"""Exception thrown when digests of a downloaded blob are different."""

def __init__(self, filename, server_digest, local_digest):
# type: (str, str, str) -> None
Expand All @@ -41,7 +41,7 @@ def __str__(self):


class HTTPError(RetryError, NuxeoError):
""" Exception thrown when the server returns an error. """
"""Exception thrown when the server returns an error."""

_valid_properties = {"status": -1, "message": None, "stacktrace": None}

Expand Down Expand Up @@ -72,7 +72,7 @@ def __str__(self):
@classmethod
def parse(cls, json):
# type: (Dict[str, Any]) -> HTTPError
""" Parse a JSON object into a model instance. """
"""Parse a JSON object into a model instance."""
model = cls()

for key, val in json.items():
Expand All @@ -82,23 +82,23 @@ def parse(cls, json):


class Conflict(HTTPError):
""" Exception thrown when the HTTPError code is 409. """
"""Exception thrown when the HTTPError code is 409."""

status = 409


class Forbidden(HTTPError):
""" Exception thrown when the HTTPError code is 403. """
"""Exception thrown when the HTTPError code is 403."""

status = 403


class InvalidBatch(NuxeoError):
""" Exception thrown when accessing inexistant or deleted batches. """
"""Exception thrown when accessing inexistant or deleted batches."""


class InvalidUploadHandler(NuxeoError):
""" Exception thrown when trying to upload a blob using an invalid handler. """
"""Exception thrown when trying to upload a blob using an invalid handler."""

def __init__(self, handler, handlers):
# type: (str, List[str]) -> None
Expand All @@ -115,7 +115,7 @@ def __str__(self):


class OAuth2Error(HTTPError):
""" Exception thrown when an OAuth2 error happens. """
"""Exception thrown when an OAuth2 error happens."""

status = 400

Expand All @@ -126,7 +126,7 @@ def __init__(self, error):


class OngoingRequestError(Conflict):
""" Exception thrown when doing an idempotent call that is already being processed. """
"""Exception thrown when doing an idempotent call that is already being processed."""

def __init__(self, request_uid):
# type: (str) -> None
Expand All @@ -145,7 +145,7 @@ def __str__(self):


class Unauthorized(HTTPError):
""" Exception thrown when the HTTPError code is 401. """
"""Exception thrown when the HTTPError code is 401."""

status = 401

Expand All @@ -172,6 +172,59 @@ def __str__(self):
return repr(self)


class NotRegisteredConvertor(NuxeoError):
"""
Exception thrown when a converter is not registered.
:param options: options passed to the conversion request
"""

def __init__(self, options):
# type: (Dict[str, Any]) -> None
self.options = options
self.message = str(self)

def __repr__(self):
# type: () -> str
return f"ConvertorNotRegistered: conversion with options {self.options!r} can not be done"

def __str__(self):
# type: () -> str
return repr(self)


class UnavailableBogusConvertor(NuxeoError):
"""
Exception thrown when a converter is registered but not
available right now (e.g. not installed on the server)
or when a converter is not registered
and an Internal Server Error is thrown instead of actual error message.
:param error_message: actual error message
:param converter_name: name of the converter if available else empty string
"""

def __init__(self, error_message, converter_name):
# type: (str, str) -> None
self.error_message = error_message
self.converter_name = converter_name
self.message = str(self)

def __repr__(self):
# type: () -> str
msg = (
"Internal Server Error or Converter "
+ self.converter_name
+ " is not registered or "
+ "UnavailableConvertor: conversion with options or Unsupported Operation"
)
return msg

def __str__(self):
# type: () -> str
return repr(self)


class UploadError(NuxeoError):
"""
Exception thrown when an upload fails even after retries.
Expand Down
1 change: 1 addition & 0 deletions nuxeo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ def convert(self, params):
:param params: Converter permission
:return: the converter result
"""

return self.service.convert(self.uid, params)

def delete(self):
Expand Down
36 changes: 17 additions & 19 deletions nuxeo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import logging
import mimetypes
import sys
from distutils.version import StrictVersion
from packaging.version import Version
from functools import lru_cache
from typing import Any, Dict, List, Optional, Tuple, Union
from typing import Any, Dict, List, Optional, Tuple

from requests import Response

Expand Down Expand Up @@ -66,18 +66,11 @@ def chunk_partition(file_size, desired_chunk_size, handler=""):


def cmp(a, b):
# type: (Union[None, str, StrictVersion], Union[None, str, StrictVersion]) -> int
"""
cmp() does not exist anymore in Python 3.
Note: this function cannot be decorated with lru_cache() because when
*a* or *b* is a *StrictVersion* object, it is not hashable.
And callers are cached anyway.
"""
if a is None:
if b is None:
if str(a) == "0":
if str(b) == "0":
return 0
return -1
if b is None:
if str(b) == "0":
return 1
return (a > b) - (a < b)

Expand Down Expand Up @@ -136,7 +129,7 @@ def get_digester(digest):

def guess_mimetype(filename):
# type: (str) -> str
""" Guess the mimetype of a given file. """
"""Guess the mimetype of a given file."""
mime_type, _ = mimetypes.guess_type(filename)
if mime_type:
if sys.platform == "win32":
Expand Down Expand Up @@ -285,7 +278,7 @@ def version_compare(x, y):
"""

# Handle None values
if not all((x, y)):
if x == y == "0":
return cmp(x, y)

ret = (-1, 1)
Expand Down Expand Up @@ -336,29 +329,34 @@ def version_compare(x, y):
@lru_cache(maxsize=128)
def version_compare_client(x, y):
# type: (str, str) -> int
""" Try to compare SemVer and fallback to version_compare on error. """
"""Try to compare SemVer and fallback to version_compare on error."""

# Ignore date based versions, they will be treated as normal versions
if x is None:
x = "0"
if y is None:
y = "0"

if x and "-I" in x:
x = x.split("-")[0]
if y and "-I" in y:
y = y.split("-")[0]

try:
return cmp(StrictVersion(x), StrictVersion(y))
except (AttributeError, ValueError):
return cmp(Version(x), Version(y))
except Exception:
return version_compare(x, y)


@lru_cache(maxsize=128)
def version_le(x, y):
# type: (str, str) -> bool
""" x <= y """
"""x <= y"""
return version_compare_client(x, y) <= 0


@lru_cache(maxsize=128)
def version_lt(x, y):
# type: (str, str) -> bool
""" x < y """
"""x < y"""
return version_compare_client(x, y) < 0
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from nuxeo.client import Nuxeo
from nuxeo.exceptions import HTTPError
from requests.cookies import RequestsCookieJar
from .constants import NUXEO_SERVER_URL

logging.basicConfig(
format="%(module)-14s %(levelname).1s %(message)s", level=logging.DEBUG
Expand Down Expand Up @@ -59,7 +60,7 @@ def repository(server):

@pytest.fixture(scope="session")
def host():
return os.environ.get("NXDRIVE_TEST_NUXEO_URL", "http://localhost:8080/nuxeo")
return os.environ.get("NXDRIVE_TEST_NUXEO_URL", NUXEO_SERVER_URL)


@pytest.fixture(scope="module")
Expand Down
1 change: 1 addition & 0 deletions tests/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
WORKSPACE_ROOT = "/default-domain/workspaces"
WORKSPACE_NAME = "ws-python-tests"
WORKSPACE_TEST = WORKSPACE_ROOT + "/" + WORKSPACE_NAME
NUXEO_SERVER_URL = "http://localhost:8080/nuxeo"
3 changes: 2 additions & 1 deletion tests/manual/many_small_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from nuxeo.client import Nuxeo
from nuxeo.models import Document, FileBlob
from tests.constants import NUXEO_SERVER_URL


def create_random_file(file_in, i):
Expand Down Expand Up @@ -65,7 +66,7 @@ def run_test(server):

if __name__ == "__main__":
server = Nuxeo(
host=os.environ.get("NXDRIVE_TEST_NUXEO_URL", "http://localhost:8080/nuxeo"),
host=os.environ.get("NXDRIVE_TEST_NUXEO_URL", NUXEO_SERVER_URL),
auth=("Administrator", "Administrator"),
)
server.client.set(schemas=["dublincore"])
Expand Down
3 changes: 2 additions & 1 deletion tests/manual/one_big_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from nuxeo.client import Nuxeo
from nuxeo.models import Document, FileBlob
from tests.constants import NUXEO_SERVER_URL


@profile
Expand Down Expand Up @@ -51,7 +52,7 @@ def run_test(server):

if __name__ == "__main__":
server = Nuxeo(
host=os.environ.get("NXDRIVE_TEST_NUXEO_URL", "http://localhost:8080/nuxeo"),
host=os.environ.get("NXDRIVE_TEST_NUXEO_URL", NUXEO_SERVER_URL),
auth=("Administrator", "Administrator"),
)
server.client.set(schemas=["dublincore"])
Expand Down
Loading

0 comments on commit 01fe8f2

Please sign in to comment.