forked from loafle/openapi-generator-original
[python-flask] adopt python3.5+ syntax (#16375)
* adopt python3.5+ syntax removing some residual python2 code, since it is not supported anymore, like: - no need for `six` anymore - no need for encoding utf8 in top file - remove `object` inheritance in base model - remove absolute import `__future__` * generate samples applying the new templates * update python ignore pattern ignore all the `.venv` folders
This commit is contained in:
parent
646ec8ba41
commit
00de163655
5
.gitignore
vendored
5
.gitignore
vendored
@ -173,14 +173,13 @@ samples/client/petstore/csharp-refactor/OpenAPIClient/nuget.exe
|
|||||||
# Python
|
# Python
|
||||||
*.pyc
|
*.pyc
|
||||||
__pycache__
|
__pycache__
|
||||||
|
.venv/
|
||||||
samples/client/petstore/python/dev-requirements.txt.log
|
samples/client/petstore/python/dev-requirements.txt.log
|
||||||
samples/client/petstore/python/swagger_client.egg-info/SOURCES.txt
|
samples/client/petstore/python/swagger_client.egg-info/SOURCES.txt
|
||||||
samples/client/petstore/python/.coverage
|
samples/client/petstore/python/.coverage
|
||||||
samples/client/petstore/python/.projectile
|
samples/client/petstore/python/.projectile
|
||||||
samples/client/petstore/python/.venv/
|
|
||||||
samples/client/petstore/python-asyncio/.venv/
|
|
||||||
samples/client/petstore/python-asyncio/.pytest_cache/
|
samples/client/petstore/python-asyncio/.pytest_cache/
|
||||||
samples/client/petstore/python-tornado/.venv/
|
|
||||||
|
|
||||||
# PHP
|
# PHP
|
||||||
samples/client/petstore/php/OpenAPIClient-php/composer.lock
|
samples/client/petstore/php/OpenAPIClient-php/composer.lock
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
from __future__ import absolute_import
|
|
||||||
# import models into model package
|
# import models into model package
|
||||||
{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}}
|
{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}}
|
||||||
{{/models}}
|
{{/models}}
|
@ -1,6 +1,5 @@
|
|||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
import six
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from {{packageName}} import util
|
from {{packageName}} import util
|
||||||
@ -8,7 +7,7 @@ from {{packageName}} import util
|
|||||||
T = typing.TypeVar('T')
|
T = typing.TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model:
|
||||||
# openapiTypes: The key is attribute name and the
|
# openapiTypes: The key is attribute name and the
|
||||||
# value is attribute type.
|
# value is attribute type.
|
||||||
openapi_types: typing.Dict[str, type] = {}
|
openapi_types: typing.Dict[str, type] = {}
|
||||||
@ -29,7 +28,7 @@ class Model(object):
|
|||||||
"""
|
"""
|
||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
for attr, _ in six.iteritems(self.openapi_types):
|
for attr in self.openapi_types:
|
||||||
value = getattr(self, attr)
|
value = getattr(self, attr)
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
result[attr] = list(map(
|
result[attr] = list(map(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import connexion
|
import connexion
|
||||||
import six
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
@ -97,15 +96,15 @@ def {{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{
|
|||||||
{{#items}}
|
{{#items}}
|
||||||
{{#isDate}}
|
{{#isDate}}
|
||||||
if connexion.request.is_json:
|
if connexion.request.is_json:
|
||||||
{{paramName}} = {k: util.deserialize_date(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
|
{{paramName}} = {k: util.deserialize_date(v) for k, v in connexion.request.get_json().items()} # noqa: E501
|
||||||
{{/isDate}}
|
{{/isDate}}
|
||||||
{{#isDateTime}}
|
{{#isDateTime}}
|
||||||
if connexion.request.is_json:
|
if connexion.request.is_json:
|
||||||
{{paramName}} = {k: util.deserialize_datetime(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
|
{{paramName}} = {k: util.deserialize_datetime(v) for k, v in connexion.request.get_json().items()} # noqa: E501
|
||||||
{{/isDateTime}}
|
{{/isDateTime}}
|
||||||
{{#complexType}}
|
{{#complexType}}
|
||||||
if connexion.request.is_json:
|
if connexion.request.is_json:
|
||||||
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in six.iteritems(connexion.request.get_json())} # noqa: E501
|
{{paramName}} = {k: {{baseType}}.from_dict(v) for k, v in connexion.request.get_json().items()} # noqa: E501
|
||||||
{{/complexType}}
|
{{/complexType}}
|
||||||
{{/items}}
|
{{/items}}
|
||||||
{{/isMap}}
|
{{/isMap}}
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
from six import BytesIO
|
|
||||||
|
|
||||||
{{#imports}}{{import}} # noqa: E501
|
{{#imports}}{{import}} # noqa: E501
|
||||||
{{/imports}}
|
{{/imports}}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from connexion.apps.flask_app import FlaskJSONEncoder
|
from connexion.apps.flask_app import FlaskJSONEncoder
|
||||||
import six
|
|
||||||
|
|
||||||
from {{modelPackage}}.base_model import Model
|
from {{modelPackage}}.base_model import Model
|
||||||
|
|
||||||
@ -10,7 +9,7 @@ class JSONEncoder(FlaskJSONEncoder):
|
|||||||
def default(self, o):
|
def default(self, o):
|
||||||
if isinstance(o, Model):
|
if isinstance(o, Model):
|
||||||
dikt = {}
|
dikt = {}
|
||||||
for attr, _ in six.iteritems(o.openapi_types):
|
for attr in o.openapi_types:
|
||||||
value = getattr(o, attr)
|
value = getattr(o, attr)
|
||||||
if value is None and not self.include_nulls:
|
if value is None and not self.include_nulls:
|
||||||
continue
|
continue
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info < (3, 7):
|
if sys.version_info < (3, 7):
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import six
|
|
||||||
import typing
|
import typing
|
||||||
from {{packageName}} import typing_utils
|
from {{packageName}} import typing_utils
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ def _deserialize(data, klass):
|
|||||||
if data is None:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if klass in six.integer_types or klass in (float, str, bool, bytearray):
|
if klass in (int, float, str, bool, bytearray):
|
||||||
return _deserialize_primitive(data, klass)
|
return _deserialize_primitive(data, klass)
|
||||||
elif klass == object:
|
elif klass == object:
|
||||||
return _deserialize_object(data)
|
return _deserialize_object(data)
|
||||||
@ -45,7 +44,7 @@ def _deserialize_primitive(data, klass):
|
|||||||
try:
|
try:
|
||||||
value = klass(data)
|
value = klass(data)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
value = six.u(data)
|
value = data
|
||||||
except TypeError:
|
except TypeError:
|
||||||
value = data
|
value = data
|
||||||
return value
|
return value
|
||||||
@ -110,7 +109,7 @@ def deserialize_model(data, klass):
|
|||||||
if not instance.openapi_types:
|
if not instance.openapi_types:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
for attr, attr_type in six.iteritems(instance.openapi_types):
|
for attr, attr_type in instance.openapi_types.items():
|
||||||
if data is not None \
|
if data is not None \
|
||||||
and instance.attribute_map[attr] in data \
|
and instance.attribute_map[attr] in data \
|
||||||
and isinstance(data, (list, dict)):
|
and isinstance(data, (list, dict)):
|
||||||
@ -145,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
|
|||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
return {k: _deserialize(v, boxed_type)
|
return {k: _deserialize(v, boxed_type)
|
||||||
for k, v in six.iteritems(data)}
|
for k, v in data.items() }
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import connexion
|
import connexion
|
||||||
import six
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import connexion
|
import connexion
|
||||||
import six
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import connexion
|
import connexion
|
||||||
import six
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from connexion.apps.flask_app import FlaskJSONEncoder
|
from connexion.apps.flask_app import FlaskJSONEncoder
|
||||||
import six
|
|
||||||
|
|
||||||
from openapi_server.models.base_model import Model
|
from openapi_server.models.base_model import Model
|
||||||
|
|
||||||
@ -10,7 +9,7 @@ class JSONEncoder(FlaskJSONEncoder):
|
|||||||
def default(self, o):
|
def default(self, o):
|
||||||
if isinstance(o, Model):
|
if isinstance(o, Model):
|
||||||
dikt = {}
|
dikt = {}
|
||||||
for attr, _ in six.iteritems(o.openapi_types):
|
for attr in o.openapi_types:
|
||||||
value = getattr(o, attr)
|
value = getattr(o, attr)
|
||||||
if value is None and not self.include_nulls:
|
if value is None and not self.include_nulls:
|
||||||
continue
|
continue
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
from __future__ import absolute_import
|
|
||||||
# import models into model package
|
# import models into model package
|
||||||
from openapi_server.models.api_response import ApiResponse
|
from openapi_server.models.api_response import ApiResponse
|
||||||
from openapi_server.models.category import Category
|
from openapi_server.models.category import Category
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
import six
|
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from openapi_server import util
|
from openapi_server import util
|
||||||
@ -8,7 +7,7 @@ from openapi_server import util
|
|||||||
T = typing.TypeVar('T')
|
T = typing.TypeVar('T')
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model:
|
||||||
# openapiTypes: The key is attribute name and the
|
# openapiTypes: The key is attribute name and the
|
||||||
# value is attribute type.
|
# value is attribute type.
|
||||||
openapi_types: typing.Dict[str, type] = {}
|
openapi_types: typing.Dict[str, type] = {}
|
||||||
@ -29,7 +28,7 @@ class Model(object):
|
|||||||
"""
|
"""
|
||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
for attr, _ in six.iteritems(self.openapi_types):
|
for attr in self.openapi_types:
|
||||||
value = getattr(self, attr)
|
value = getattr(self, attr)
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
result[attr] = list(map(
|
result[attr] = list(map(
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from datetime import date, datetime # noqa: F401
|
from datetime import date, datetime # noqa: F401
|
||||||
|
|
||||||
from typing import List, Dict # noqa: F401
|
from typing import List, Dict # noqa: F401
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
from six import BytesIO
|
|
||||||
|
|
||||||
from openapi_server.models.api_response import ApiResponse # noqa: E501
|
from openapi_server.models.api_response import ApiResponse # noqa: E501
|
||||||
from openapi_server.models.pet import Pet # noqa: E501
|
from openapi_server.models.pet import Pet # noqa: E501
|
||||||
@ -20,23 +16,7 @@ class TestPetController(BaseTestCase):
|
|||||||
|
|
||||||
Add a new pet to the store
|
Add a new pet to the store
|
||||||
"""
|
"""
|
||||||
body = {
|
body = {"photoUrls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"}
|
||||||
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
|
||||||
"name" : "doggie",
|
|
||||||
"id" : 0,
|
|
||||||
"category" : {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 6
|
|
||||||
},
|
|
||||||
"tags" : [ {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 1
|
|
||||||
}, {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 1
|
|
||||||
} ],
|
|
||||||
"status" : "available"
|
|
||||||
}
|
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer special-key',
|
'Authorization': 'Bearer special-key',
|
||||||
@ -71,7 +51,7 @@ class TestPetController(BaseTestCase):
|
|||||||
|
|
||||||
Finds Pets by status
|
Finds Pets by status
|
||||||
"""
|
"""
|
||||||
query_string = [('status', 'available')]
|
query_string = [('status', ['status_example'])]
|
||||||
headers = {
|
headers = {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Authorization': 'Bearer special-key',
|
'Authorization': 'Bearer special-key',
|
||||||
@ -124,23 +104,7 @@ class TestPetController(BaseTestCase):
|
|||||||
|
|
||||||
Update an existing pet
|
Update an existing pet
|
||||||
"""
|
"""
|
||||||
body = {
|
body = {"photoUrls":["photoUrls","photoUrls"],"name":"doggie","id":0,"category":{"name":"name","id":6},"tags":[{"name":"name","id":1},{"name":"name","id":1}],"status":"available"}
|
||||||
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
|
||||||
"name" : "doggie",
|
|
||||||
"id" : 0,
|
|
||||||
"category" : {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 6
|
|
||||||
},
|
|
||||||
"tags" : [ {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 1
|
|
||||||
}, {
|
|
||||||
"name" : "name",
|
|
||||||
"id" : 1
|
|
||||||
} ],
|
|
||||||
"status" : "available"
|
|
||||||
}
|
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer special-key',
|
'Authorization': 'Bearer special-key',
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
from six import BytesIO
|
|
||||||
|
|
||||||
from openapi_server.models.order import Order # noqa: E501
|
from openapi_server.models.order import Order # noqa: E501
|
||||||
from openapi_server.test import BaseTestCase
|
from openapi_server.test import BaseTestCase
|
||||||
@ -52,7 +48,7 @@ class TestStoreController(BaseTestCase):
|
|||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
}
|
}
|
||||||
response = self.client.open(
|
response = self.client.open(
|
||||||
'/v2/store/order/{order_id}'.format(order_id=1),
|
'/v2/store/order/{order_id}'.format(order_id=56),
|
||||||
method='GET',
|
method='GET',
|
||||||
headers=headers)
|
headers=headers)
|
||||||
self.assert200(response,
|
self.assert200(response,
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
from six import BytesIO
|
|
||||||
|
|
||||||
from openapi_server.models.user import User # noqa: E501
|
from openapi_server.models.user import User # noqa: E501
|
||||||
from openapi_server.test import BaseTestCase
|
from openapi_server.test import BaseTestCase
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info < (3, 7):
|
if sys.version_info < (3, 7):
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import six
|
|
||||||
import typing
|
import typing
|
||||||
from openapi_server import typing_utils
|
from openapi_server import typing_utils
|
||||||
|
|
||||||
@ -16,7 +15,7 @@ def _deserialize(data, klass):
|
|||||||
if data is None:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if klass in six.integer_types or klass in (float, str, bool, bytearray):
|
if klass in (int, float, str, bool, bytearray):
|
||||||
return _deserialize_primitive(data, klass)
|
return _deserialize_primitive(data, klass)
|
||||||
elif klass == object:
|
elif klass == object:
|
||||||
return _deserialize_object(data)
|
return _deserialize_object(data)
|
||||||
@ -45,7 +44,7 @@ def _deserialize_primitive(data, klass):
|
|||||||
try:
|
try:
|
||||||
value = klass(data)
|
value = klass(data)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
value = six.u(data)
|
value = data
|
||||||
except TypeError:
|
except TypeError:
|
||||||
value = data
|
value = data
|
||||||
return value
|
return value
|
||||||
@ -110,7 +109,7 @@ def deserialize_model(data, klass):
|
|||||||
if not instance.openapi_types:
|
if not instance.openapi_types:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
for attr, attr_type in six.iteritems(instance.openapi_types):
|
for attr, attr_type in instance.openapi_types.items():
|
||||||
if data is not None \
|
if data is not None \
|
||||||
and instance.attribute_map[attr] in data \
|
and instance.attribute_map[attr] in data \
|
||||||
and isinstance(data, (list, dict)):
|
and isinstance(data, (list, dict)):
|
||||||
@ -145,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
|
|||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
return {k: _deserialize(v, boxed_type)
|
return {k: _deserialize(v, boxed_type)
|
||||||
for k, v in six.iteritems(data)}
|
for k, v in data.items() }
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# coding: utf-8
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user