Make the connector more generic; Fixed urls and some pylint issues

Features
    * Added 'get_courrier_type' endpoint that return a 'courrier type' for a given type_dossier
    * Added url parameter 'type_dossier_detaille' to 'create_dossier' to post it in the request body
    * Replaced the way 'type fichier' is defined: now looks into 'XXX_type_raw' for file 'XXX'

Fixes
    * Url components are now encoded
    * Pylint warnings
    * Loging do not raise an error when 'files' var is empty in 'create_dossier'

Tests
    * Added 2 new errors tests to 'test_create_dossier'
    * Added 'test_get_courrier_type' to test endpoint 'get_courrier_type'
    * Fixed pylint warnings
This commit is contained in:
Michael Bideau 2019-10-24 17:24:55 +02:00
parent 6197d8ae62
commit 6809c75d33
3 changed files with 247 additions and 44 deletions

View File

@ -144,7 +144,7 @@ JSON_SCHEMA_CREATE_DOSSIER_IN = {
"terrain_code_postal",
"terrain_localite",
"reference_cadastrale",
"proprietaire",
#"proprietaire",
"qualite",
"nom",
"prenom",

View File

@ -24,11 +24,12 @@ import base64
import datetime
import json
import os
import re
import urlparse
import magic
from urllib import quote
from django.db import models
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
@ -162,6 +163,8 @@ class ForwardFile(models.Model, BaseModel): # pylint: disable=too-many-instance
# @see: https://docs.djangoproject.com/en/2.2/topics/db/models/
# The note entitled "Overridden model methods are not called on bulk operations"
def save(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Save the entity, overwritten to preprocessing data and validate model."""
# delete file content (on success)
if self.upload_status == 'success':
# pylint: disable=no-member
@ -181,6 +184,8 @@ class ForwardFile(models.Model, BaseModel): # pylint: disable=too-many-instance
# 'file_hash', 'orig_filename', 'upload_file'
# because if they are all empty we dont have any usefull information about the upload
def clean(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Check all the fields, overwritten to check grouped blank/null fields."""
ret = super(ForwardFile, self).clean(*args, **kwargs)
if (not self.file_hash
and not self.orig_filename
@ -226,7 +231,7 @@ class Collectivite(models.Model, BaseModel):
if fields:
rels = []
for rel_name in ['forward_file', 'guichet']:
if (fields[0] and hasattr(fields[0], 'name') and fields[0].name == rel_name):
if fields[0] and hasattr(fields[0], 'name') and fields[0].name == rel_name:
rels.append(fields.pop(0))
for rel in reversed(rels):
fields.append(rel)
@ -510,7 +515,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
# }
)
# pylint: disable=unused-argument,arguments-differ,keyword-arg-before-vararg
# pylint: disable=unused-argument,arguments-differ
def check_status(self, request=None, *args, **kwargs):
"""Check avaibility of the openADS.API service."""
url = urlparse.urljoin(self.openADS_API_url, '__api__')
@ -525,6 +530,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
example_pattern='{type_dossier}/',
parameters={
'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'},
'type_dossier_detaille': {'description': _("Detailled type of 'dossier'"),
'example_value': 'CUb'},
'collectivite': {
'description': _("Use this collectivite (instead of the default one)"),
'example_value': '3'
@ -537,7 +544,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
'request_body': {
'schema': {
'application/json': JSON_SCHEMA_CREATE_DOSSIER_IN
} # pylint: disable=too-many-statements,too-many-branches,too-many-locals
} # pylint: disable=too-many-statements,too-many-branches,too-many-locals,too-many-arguments
}
# 'response_body': {
# 'schema': {
@ -546,8 +553,9 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
}
)
# pylint: disable=unused-argument,keyword-arg-before-vararg
def create_dossier(self, request, type_dossier, collectivite=None, now=None, *args, **kwargs):
# pylint: disable=unused-argument
def create_dossier(self, request, type_dossier, type_dossier_detaille=None, collectivite=None,
now=None, *args, **kwargs):
"""Create an openADS 'dossier'."""
# loads the request body as JSON content
@ -571,7 +579,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
else:
# the collectivite has a guichet
if (hasattr(collectivite, 'guichet') and collectivite.guichet):
if hasattr(collectivite, 'guichet') and collectivite.guichet:
# get the datetime against which the 'guichet' is checked for opening
now_fmt = '%Y-%m-%d %H:%M:%S'
@ -592,7 +600,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
return {'message': _(u"Guichet closed for collectivite '%s'" % collectivite)}
# build the payload
payload = {"collectivite": int(collectivite_id)}
payload = {
"collectivite": int(collectivite_id),
#"type_detaille": type_dossier
}
if type_dossier_detaille:
payload["type_detaille"] = type_dossier_detaille
payload["terrain"] = {
"numero_voie": normalize(json_data['fields']['terrain_numero_voie']),
@ -620,7 +634,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# setup demandeur variable prefix
prefixes = {"demandeurs": ''}
if normalize(json_data['fields']['proprietaire']) != 'Oui':
if ('proprietaire' in json_data['fields'] and
normalize(json_data['fields']['proprietaire']) != 'Oui'):
prefixes["mandataires"] = 'mandataire_'
# for each type of demandeur with associated prefix
@ -679,7 +694,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
self.log_json_payload(payload)
# every field key that might contain a file content
file_keys = ['cerfa'] + ['plan_cadastral_%s' % i for i in range(1, 5)] + ['pouvoir_mandat']
file_keys = ['cerfa'] + ['annexe_%s' % i for i in range(1, 5)]
# prepare files that will be forwarded
files = []
@ -688,6 +703,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
and json_data['fields'][k]
and isinstance(json_data['fields'][k], dict)
and 'content' in json_data['fields'][k]):
# get the content decoded from base 64
content = base64.b64decode(json_data['fields'][k]['content'])
@ -728,8 +744,18 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
elif '.' not in filename:
filename += file_extension
# set the type fichier based on the key (less than 10 chars)
type_fichier = re.sub(r'_.*$', '', k)[:10]
# get the type fichier (less than 10 chars)
type_fichier = None
if k + '_type_raw' in json_data['fields']:
type_fichier = json_data['fields'][k + '_type_raw']
if len(type_fichier) > 10:
raise APIError(u"Type '%s' for file '%s' is too long "
"(%d chars, but max is %d)" % (
type_fichier, k, len(type_fichier), 10))
elif k.lower() == 'cerfa':
type_fichier = 'CERFA'
else:
raise APIError(u"No type field/value for file '%s'" % k)
# append the file to the list
files.append({
@ -742,11 +768,11 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# log files to be forwarded
self.logger.debug("----- files (begining) -----")
self.logger.debug("%r", files)
self.logger.debug('%s', files) if files else self.logger.debug("(no files)") # pylint: disable=expression-not-assigned
self.logger.debug("----- files (end) -----")
# make a request to openADS.API (with the payload)
url = urlparse.urljoin(self.openADS_API_url, '/dossiers/%s' % type_dossier)
url = urlparse.urljoin(self.openADS_API_url, '/dossiers/%s' % quote(type_dossier))
response = self.requests.post(
url,
json=payload,
@ -863,13 +889,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
# }
)
# pylint: disable=unused-argument,keyword-arg-before-vararg
# pylint: disable=unused-argument
def get_dossier(self, request, type_dossier, numero_dossier, *args, **kwargs):
"""Get informations about an openADS 'dossier'."""
# make a request to openADS.API
url = urlparse.urljoin(self.openADS_API_url,
'/dossier/%s/%s' % (type_dossier, numero_dossier))
url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s' % (
quote(type_dossier), quote(numero_dossier)))
response = self.requests.get(url)
# response is an error
@ -910,7 +936,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
# }
)
# pylint: disable=unused-argument,keyword-arg-before-vararg,no-self-use
# pylint: disable=unused-argument,no-self-use
def get_fwd_files(self, request, numero_dossier, fichier_id=None, *args, **kwargs):
"""Get informations about the forwarding of user files to openADS."""
payload = []
@ -973,7 +999,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
# }
)
# pylint: disable=unused-argument,keyword-arg-before-vararg
# pylint: disable=unused-argument
def get_fwd_files_status(self, request, numero_dossier, fichier_id=None, *args, **kwargs):
"""Get informations about the forwarding of a user file to openADS."""
@ -1006,7 +1032,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
@endpoint(
perm='can_access',
description=_("Get a 'courrier' from an openADS 'dossier'"),
pattern='^(?P<type_dossier>\w+)/(?P<numero_dossier>\w+)/(?P<lettre_type>\w+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string
pattern='^(?P<type_dossier>\w+)/(?P<numero_dossier>\w+)/(?P<lettre_type>[\w.,_ -]+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string
example_pattern='{type_dossier}/{numero_dossier}/{lettre_type}',
parameters={
'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'},
@ -1024,14 +1050,13 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
# }
)
# pylint: disable=unused-argument,keyword-arg-before-vararg
# pylint: disable=unused-argument
def get_courrier(self, request, type_dossier, numero_dossier, lettre_type, *args, **kwargs):
"""Get a 'courrier' from an openADS 'dossier'."""
# make a request to openADS.API
url = urlparse.urljoin(
self.openADS_API_url,
'/dossier/%s/%s/courrier/%s' % (type_dossier, numero_dossier, lettre_type))
url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s/courrier/%s' % (
quote(type_dossier), quote(numero_dossier), quote(lettre_type)))
response = self.requests.get(url)
# response is an error
@ -1115,7 +1140,7 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# }
)
# @raise ForwareFile.DoesNotExist if not found
# pylint: disable=unused-argument,keyword-arg-before-vararg
# pylint: disable=unused-argument
def upload_user_files(self, request, type_dossier, numero_dossier, file_ids=None,
*args, **kwargs):
"""A Job to forward user uploaded files to openADS."""
@ -1198,8 +1223,8 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
self.log_json_payload(payload, 'payload')
# make the request to openADS.API (with a specific timeout)
url = urlparse.urljoin(self.openADS_API_url,
'/dossier/%s/%s/files' % (type_dossier, numero_dossier))
url = urlparse.urljoin(self.openADS_API_url, '/dossier/%s/%s/files' % (
quote(type_dossier), quote(numero_dossier)))
response = self.requests.post(
url,
json=payload,
@ -1294,3 +1319,67 @@ class AtrealOpenads(BaseResource, HTTPResource, BaseModel):
# return something to please pylint
return True
@endpoint(
perm='can_access',
description=_("Get the type of 'courrier' of an openADS 'dossier'"),
pattern='^(?P<type_dossier>\w+)/?$', # noqa: W605,E501, pylint: disable=anomalous-backslash-in-string
example_pattern='{type_dossier}/',
parameters={
'type_dossier': {'description': _("Type of 'dossier'"), 'example_value': 'DIA'},
'type_dossier_detaille': {'description': _("Detailled type of 'dossier'"),
'example_value': 'CUb'},
'specific': {'description': _("Get a specific version of the 'courrier type'"),
'example_value': 'refus'},
} # pylint: disable=too-many-branches
) # pylint: disable=no-self-use
# pylint: disable=unused-argument
def get_courrier_type(self, request, type_dossier, type_dossier_detaille=None, specific=None,
*args, **kwargs):
"""Get the type of 'courrier' for an openADS 'dossier'."""
courrier_type = None
if type_dossier == 'DIA':
courrier_type = 'dia_renonciation_preempter'
if specific == 'delegation':
courrier_type = 'dia_delegation'
elif specific == 'irrecevabilite':
courrier_type = 'dia_irrecevabilite'
elif specific == 'preemption':
courrier_type = 'dia_souhait_preempter'
elif type_dossier == 'CU':
courrier_type = 'CUa'
if type_dossier_detaille == 'CUb':
courrier_type = 'CUb - ACCORD'
if specific == 'refus':
courrier_type = 'CUb - REFUS'
elif type_dossier == 'DP':
courrier_type = 'decision_non_opposition_DP'
if specific == 'annulation':
courrier_type = 'arrete_annulation_DP'
elif specific == 'prolongation':
courrier_type = 'arrete_prorogation_DP'
elif specific == 'prolongation_refus':
courrier_type = 'arrete_refus_prorogation_DP'
elif specific == 'transfert_refus':
courrier_type = 'arrete_refus_transfert_DP'
elif specific == 'transfert':
courrier_type = 'arrete_transfert_DP'
elif specific == 'attestation_tacite':
courrier_type = 'attestation_non opposition_tacite_DP'
elif specific == 'opposition':
courrier_type = 'decision_opposition_DP'
elif specific == 'certificat_tacite':
courrier_type = 'certificat_opposition_tacite_DP'
elif type_dossier == 'PC' or type_dossier == 'PI':
courrier_type = 'arrete_ss_reserves'
if specific == 'refus':
courrier_type = 'arrete_refus'
# TODO add others type and specifics variants
return {'courrier_type': courrier_type}

View File

@ -432,21 +432,24 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
"field_id": "50",
"filename": os.path.basename(fake_conf['TEST_FILE_CERFA_DIA'])
},
"plan_cadastral_1": {
"annexe_1_type_raw": "plan",
"annexe_1": {
"content": get_file_data(fake_conf['TEST_FILE_PLAN_CADASTRAL']),
"content_type": "application/pdf",
"filename": os.path.basename(fake_conf['TEST_FILE_PLAN_CADASTRAL'])
},
"plan_cadastral_2": {
"annexe_2_type_raw": "plan",
"annexe_2": {
"content": get_file_data(fake_conf['TEST_FILE_PLAN_CADASTRAL']),
"content_type": "application/pdf",
# "filename": 'plan_cad'
},
"pouvoir_mandat": {
"annexe_3_type_raw": "pouvoir",
"annexe_3": {
"content": get_file_data(fake_conf['TEST_FILE_CERFA_DIA']),
"content_type": "application/pdf",
"filename": 'mandat'
}
},
}
}
request_1.method = 'POST'
@ -469,7 +472,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp_bad
atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open)
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == "HTTP error: 502"
# TODO update the code and return message when it will be
@ -484,7 +488,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
atreal_openads.create_dossier(request_1, 'DIA', collectivite=999)
assert unicode(exception.value) == "HTTP error: 404"
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now_closed)
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_closed)
assert jresp is not None
assert len(jresp) == 1
assert 'message' in jresp
@ -492,8 +497,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
now_str_fmt = '%Y-%m-%d %H:%M:%S'
now_closed_str = now_closed.strftime(now_str_fmt)
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id,
now_closed_str)
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_closed_str)
assert jresp is not None
assert len(jresp) == 1
assert 'message' in jresp
@ -501,14 +506,42 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
now_invalid = {'invalid': 'type'}
with pytest.raises(APIError) as exception:
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id,
now_invalid)
jresp = atreal_openads.create_dossier(request_1, 'DIA',
collectivite=collectivite_1.openADS_id,
now=now_invalid)
assert unicode(exception.value) == (
u"Invalid value of type '%s' for now argument of endpoint '%s' (must be: %s)" % (
type(now_invalid),
'create_dossier',
"datetime or string formatted to '%s'" % now_str_fmt))
annexe_3_type_bak = fake_req_json['fields']['annexe_3_type_raw']
fake_req_json['fields']['annexe_3_type_raw'] = 'toooooooooooo_looonnnngggggg'
request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp_bad
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == (
u"Type '%s' for file '%s' is too long (%d chars, but max is %d)" % (
fake_req_json['fields']['annexe_3_type_raw'],
'annexe_3',
len(fake_req_json['fields']['annexe_3_type_raw']),
10))
del fake_req_json['fields']['annexe_3_type_raw']
request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp_bad
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == u"No type field/value for file '%s'" % 'annexe_3'
fake_req_json['fields']['annexe_3_type_raw'] = annexe_3_type_bak
request_1._body = json.dumps(fake_req_json) # pylint: disable=protected-access
fake_resp_json = {
'numero_dossier': fake_conf['FAKE_NUMERO_DOSSIER'],
'files': [{
@ -526,8 +559,9 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp
jresp = atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id,
now=now_open)
jresp = atreal_openads.create_dossier(request_1, 'DIA',
collectivite=collectivite_1.openADS_id,
now=now_open, type_dossier_detaille='DIA')
assert jresp['numero_dossier'] == fake_resp_json['numero_dossier']
assert jresp['recepisse']['b64_content'] == fake_resp_json['files'][0]['b64_content']
assert jresp['recepisse']['content_type'] == 'application/pdf'
@ -538,7 +572,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp
atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open)
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == (
u"Expecting '%s' value in JSON response to be a %s (not a %s)" % (
'numero_dossier', 'string', type({})))
@ -548,7 +583,8 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp
atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open)
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == u"Expecting 'numero_dossier' key in JSON response"
fake_resp_json['files'][0]['b64_content'] = 'invalid_;{[content}'
@ -556,14 +592,16 @@ def test_create_dossier(fake_conf, atreal_openads, collectivite_1, collectivite_
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp
atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open)
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
assert unicode(exception.value) == u'Failed to decode recepisse content from base 64'
fake_resp._content = 'df[{gfd;g#vfd' # pylint: disable=protected-access
with pytest.raises(APIError) as exception:
with mock.patch('passerelle.utils.Request.post') as requests_post:
requests_post.return_value = fake_resp
atreal_openads.create_dossier(request_1, 'DIA', collectivite_1.openADS_id, now=now_open)
atreal_openads.create_dossier(request_1, 'DIA', collectivite=collectivite_1.openADS_id,
now=now_open)
# pylint: disable=protected-access
assert unicode(exception.value) == u'No JSON content returned: %r' % fake_resp._content
@ -955,3 +993,79 @@ def test_upload_user_files(fake_conf, atreal_openads, request_1):
assert ffup.upload_attempt == 3
assert ffup.upload_status == 'success'
assert ffup.upload_msg == 'uploaded successfuly'
# pylint: disable=unused-argument,redefined-outer-name
# pylint: disable=too-many-statements
def test_get_courrier_type(fake_conf, atreal_openads):
"""Test the method AtrealOpenads.get_courrier_type()."""
type_mapping = {
'DIA': {
'default': 'dia_renonciation_preempter',
'detailled': [],
'specifics': [
('delegation', 'dia_delegation'),
('irrecevabilite', 'dia_irrecevabilite'),
('preemption', 'dia_souhait_preempter')]},
'CU': {
'default': 'CUa',
'detailled': ['CUa', 'CUb'],
'CUb': {
'default': 'CUb - ACCORD',
'specifics': [
('refus', 'CUb - REFUS')]}},
'DP': {
'default': 'decision_non_opposition_DP',
'detailled': [],
'specifics': [
('annulation', 'arrete_annulation_DP'),
('prolongation', 'arrete_prorogation_DP'),
('prolongation_refus', 'arrete_refus_prorogation_DP'),
('transfert_refus', 'arrete_refus_transfert_DP'),
('transfert', 'arrete_transfert_DP'),
('attestation_tacite', 'attestation_non opposition_tacite_DP'),
('opposition', 'decision_opposition_DP'),
('certificat_tacite', 'certificat_opposition_tacite_DP')]},
'PC': {
'default': 'arrete_ss_reserves',
'detailled': [],
'specifics': [
('refus', 'arrete_refus')]},
'PI': {
'default': 'arrete_ss_reserves',
'detailled': [],
'specifics': [
('refus', 'arrete_refus')]}
}
# pylint: disable=too-many-nested-blocks
for type_dossier, infos in type_mapping.items():
courrier_type = infos['default']
types_detailles = infos['detailled'] if infos['detailled'] else [None]
for type_detaille in types_detailles:
if type_detaille:
if type_detaille in infos:
if 'default' in infos[type_detaille]:
courrier_type = infos[type_detaille]['default']
res = atreal_openads.get_courrier_type(None, type_dossier,
type_dossier_detaille=type_detaille)
assert res == {'courrier_type': courrier_type}
if 'specifics' in infos[type_detaille]:
for specific_t in infos[type_detaille]['specifics']:
res = atreal_openads.get_courrier_type(
None, type_dossier, type_dossier_detaille=type_detaille,
specific=specific_t[0])
assert res == {'courrier_type': specific_t[1]}
elif 'specifics' in infos:
for specific_t in infos['specifics']:
res = atreal_openads.get_courrier_type(None, type_dossier,
type_dossier_detaille=type_detaille,
specific=specific_t[0])
assert res == {'courrier_type': specific_t[1]}
else:
res = atreal_openads.get_courrier_type(None, type_dossier)
assert res == {'courrier_type': courrier_type}