Skip to content

Commit

Permalink
Merge branch 'autorestv3' of https://github.com/Azure/autorest.python
Browse files Browse the repository at this point in the history
…into autorestv3

* 'autorestv3' of https://github.com/Azure/autorest.python:
  LRO Final get default (#502)
  LRO + Paging tests (#501)
  Increase XMS test coverage (#500)
  Paging tests (#499)
  Re-enable file large test (#498)
  making empty nextLink none (#497)
  Add coverage report back (#492)
  Update to last m4 to fix bug 93 (#495)
  updated m4 to 4.10.240 (#488)
  add check for models and enums having same name (#491)
  Fix error in multiapi script that is removing _version file if it already exists (#490)
  Optional constant params in signature (#489)
  Add CI configuration for publishing v5 development releases
  Get azure-mgmt-core from PyPI (#481)
  Revert "making criterion to initialize models same as importing models in operation groups" (#483)
  • Loading branch information
iscai-msft committed Mar 16, 2020
2 parents 24c59e5 + 9961869 commit a5fa9ea
Show file tree
Hide file tree
Showing 51 changed files with 635 additions and 848 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ AutoRest needs the below config to pick this up as a plug-in - see https://githu
pass-thru:
- model-deduplicator
- subset-reducer
# version: 3.0.6258
use-extension:
"@autorest/modelerfour": "4.9.234"
"@autorest/modelerfour": "4.10.246"

modelerfour:
group-parameters: true
Expand Down
38 changes: 36 additions & 2 deletions autorest/codegen/models/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .imports import FileImport, ImportType
from .base_model import BaseModel
from .base_schema import BaseSchema
from .constant_schema import ConstantSchema


_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -80,6 +81,35 @@ def __init__(
self.multiple_media_types_type_annot: Optional[str] = None
self.multiple_media_types_docstring_type: Optional[str] = None

@property
def constant(self) -> bool:
"""Returns whether a parameter is a constant or not.
Checking to see if it's required, because if not, we don't consider it
a constant because it can have a value of None.
"""
if not isinstance(self.schema, ConstantSchema):
return False
return self.required

@property
def in_method_signature(self) -> bool:
return not(
# If I only have one value, I can't be set, so no point being in signature
self.constant
# If i'm not in the method code, no point in being in signature
or not self.in_method_code
# If I'm grouped, my grouper will be on signature, not me
or self.grouped_by
# If I'm body and it's flattened, I'm not either
or (self.location == ParameterLocation.Body and self.flattened)
# If I'm a kwarg, don't include in the signature
or self.is_kwarg
)

@property
def in_method_code(self) -> bool:
return not (isinstance(self.schema, ConstantSchema) and self.location == ParameterLocation.Other)

@property
def implementation(self) -> str:
# https://github.com/Azure/autorest.modelerfour/issues/81
Expand All @@ -100,8 +130,12 @@ def _default_value(self) -> Tuple[Optional[Any], str, str]:
default_value = None
default_value_declaration = "None"
else:
default_value = self.schema.default_value
default_value_declaration = self.schema.default_value_declaration
if isinstance(self.schema, ConstantSchema):
default_value = self.schema.constant_value
default_value_declaration = default_value
else:
default_value = self.schema.default_value
default_value_declaration = self.schema.default_value_declaration
if default_value is not None and self.required:
_LOGGER.warning(
"Parameter '%s' is required and has a default value, this combination is not recommended",
Expand Down
33 changes: 9 additions & 24 deletions autorest/codegen/models/parameter_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from typing import cast, List, Callable, Optional

from .parameter import Parameter, ParameterLocation
from .constant_schema import ConstantSchema
from .object_schema import ObjectSchema


Expand Down Expand Up @@ -93,35 +92,22 @@ def constant(self) -> List[Parameter]:
not have impact on any generation at this level
"""
return self.get_from_predicate(
lambda parameter: isinstance(parameter.schema, ConstantSchema) and not parameter.flattened
lambda parameter: parameter.constant
)

@property
def method(self) -> List[Parameter]:
"""The list of parameter used in method signature.
"""

def is_parameter_in_signature(parameter: Parameter) -> bool:
"""A predicate to tell if this parameter deserves to be in the signature.
"""
return not (
# Constant are never on signature
isinstance(parameter.schema, ConstantSchema)
# Client level should not be on Method, etc.
or parameter.implementation != self.implementation
# If I'm grouped, my grouper will be on signature, not me
or parameter.grouped_by
# If I'm body and it's flattened, I'm not either
or (parameter.location == ParameterLocation.Body and self.is_flattened)
# If I'm a kwarg, don't include in the signature
or parameter.is_kwarg
)


signature_parameters_no_default_value = []
signature_parameters_default_value = []
for parameter in self.parameters:
if is_parameter_in_signature(parameter):

# Client level should not be on Method, etc.
parameters_of_this_implementation = self.get_from_predicate(
lambda parameter: parameter.implementation == self.implementation
)
for parameter in parameters_of_this_implementation:
if parameter.in_method_signature:
if not parameter.client_default_value and parameter.required:
signature_parameters_no_default_value.append(parameter)
else:
Expand All @@ -147,8 +133,7 @@ def build_flattened_object(self) -> str:
raise ValueError("This method can't be called if the operation doesn't need parameter flattening")

parameters = self.get_from_predicate(
lambda parameter: parameter.location == ParameterLocation.Other
and not isinstance(parameter.schema, ConstantSchema)
lambda parameter: parameter.in_method_code
)
parameter_string = ", ".join(
[f"{param.target_property_name}={param.serialized_name}"
Expand Down
12 changes: 11 additions & 1 deletion autorest/codegen/serializers/model_init_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,21 @@ def __init__(self, code_model: CodeModel, env: Environment) -> None:
self.env = env

def serialize(self) -> str:
schemas = sorted(self.code_model.sorted_schemas, key=lambda x: x.name)
schemas = [s.name for s in self.code_model.sorted_schemas]
schemas.sort()
enums = [e.enum_type for e in self.code_model.enums.values()] if self.code_model.enums else None

if enums:
enums.sort()

# check to see if we have any duplicate names between enum and object schemas
model_enum_name_intersection = set(schemas).intersection(set(enums))
if model_enum_name_intersection:
raise ValueError(
"We have models and enums sharing the following names: {}".format(
", ".join(model_enum_name_intersection)
)
)

template = self.env.get_template("model_init.py.jinja2")
return template.render(code_model=self.code_model, schemas=schemas, enums=enums)
6 changes: 3 additions & 3 deletions autorest/codegen/templates/model_init.py.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

try:
{% for schema in schemas %}
from ._models_py3 import {{ schema.name }}
from ._models_py3 import {{ schema }}
{% endfor %}
except (SyntaxError, ImportError):
{% for schema in schemas %}
from ._models import {{ schema.name }} # type: ignore
from ._models import {{ schema }} # type: ignore
{% endfor %}
{% if enums %}

Expand All @@ -20,7 +20,7 @@ from ._{{ code_model.module_name }}_enums import (

__all__ = [
{% for schema in schemas %}
'{{ schema.name }}',
'{{ schema }}',
{% endfor %}
{% if enums %}
{% for enum in enums %}
Expand Down
4 changes: 2 additions & 2 deletions autorest/codegen/templates/operation.py.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

{{ operation.parameters.build_flattened_object() }}
{% endif %}
{% if operation.parameters.constant|selectattr("implementation", "equalto", "Method")|selectattr("original_parameter", "equalto", None) %}
{% for constant_parameter in operation.parameters.constant|selectattr("implementation", "equalto", "Method")|selectattr("original_parameter", "equalto", None) %}
{% if operation.parameters.constant|selectattr("implementation", "equalto", "Method")|selectattr("original_parameter", "equalto", None)|selectattr("in_method_code") %}
{% for constant_parameter in operation.parameters.constant|selectattr("implementation", "equalto", "Method")|selectattr("original_parameter", "equalto", None)|selectattr("in_method_code") %}
{{ constant_parameter.serialized_name }} = {{ constant_parameter.schema.constant_value }}
{% endfor %}
{% endif %}
Expand Down
4 changes: 2 additions & 2 deletions autorest/codegen/templates/paging_operation.py.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{% endif %}
{% endmacro %}
{% macro param_documentation_string(parameter) %}:param {{ parameter.serialized_name }}: {{ parameter.description }}{% endmacro %}
{% set next_link_str = "deserialized." + operation.next_link_name if operation.next_link_name else "None" %}
{% set next_link_str = "deserialized." + operation.next_link_name + " or None" if operation.next_link_name else "None" %}
{# actual template starts here #}
{% if code_model.options['tracing'] and operation.want_tracing %}
@distributed_trace
Expand Down Expand Up @@ -124,7 +124,7 @@
{% if operation.default_exception %}
error = self._deserialize(models.{{ operation.default_exception.schema.name }}, response)
{% endif %}
map_error(status_code=response.status_code, response=response, error_map=error_map{{ ", model=error" if operation.default_exception else "" }})
map_error(status_code=response.status_code, response=response, error_map=error_map)
raise HttpResponseError(response=response{{ ", model=error" if operation.default_exception else "" }}{{ ", error_format=ARMErrorFormat" if code_model.options['azure_arm'] else "" }})

return pipeline_response
Expand Down
7 changes: 6 additions & 1 deletion autorest/multiapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,12 @@ def process(self) -> bool:
multiapi_serializer.serialize_multiapi_operation_mixins()
)

if not self._autorestapi.read_file("_version.py"):
if self._autorestapi.read_file("_version.py"):
self._autorestapi.write_file(
"_version.py",
self._autorestapi.read_file("_version.py")
)
else:
self._autorestapi.write_file(
Path("_version.py"),
multiapi_serializer.serialize_multiapi_version()
Expand Down
7 changes: 6 additions & 1 deletion eng/pipelines/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,9 @@ jobs:
inputs:
testResultsFiles: 'test-junit-vanilla-ci.xml'
testRunTitle: '$(OSName) Python $(PythonVersion) - vanilla'
searchFolder: '$(TestFolder)/vanilla'
searchFolder: '$(TestFolder)/vanilla'

- script: |
npm run coverage-push -- $(Build.Repository.Name) $(Build.SourceBranch) $(github-token) $(storage-coverage-user) $(storage-coverage-pass)
workingDirectory: node_modules/@microsoft.azure/autorest.testserver
displayName: 'Publish coverage report to stroage account'
59 changes: 59 additions & 0 deletions eng/pipelines/publish-dev-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
trigger: none
pr: none

variables:
NodeVersion: '12.x'
PythonVersion: '3.6'
TestFolder: '$(Build.SourcesDirectory)/test/'

pool:
vmImage: 'ubuntu-16.04'

steps:
- task: NodeTool@0
displayName: 'Install Node.js $(NodeVersion)'
inputs:
versionSpec: '$(NodeVersion)'

- task: UsePythonVersion@0
displayName: 'Use Python 3.6'
inputs:
versionSpec: 3.6

- script: |
cd $(Build.SourcesDirectory)
pip install -r dev_requirements.txt
npm install -g autorest
npm install
displayName: 'Prepare Environment for Generation'
- script: |
pylint autorest
displayName: 'Pylint'
- script: |
mypy autorest
displayName: 'Mypy'
- script: |
pytest test/unittests
displayName: 'Unit tests'
- script: |
inv regenerate
displayName: 'Regenerate Code'
- script: |
pip install tox coverage==4.5.4
displayName: 'Install Env Specific Reqs in Target PyVersion $(PythonVersion)'
- script: |
cd $(TestFolder)/azure
tox -e ci
displayName: 'Execute "azure" Tests - Python $(PythonVersion)'
- script : |
export DEV_VERSION=$(node -p -e "require('./package.json').version")-dev.$BUILD_BUILDNUMBER
npm version --no-git-tag-version $DEV_VERSION
npm pack
npx publish-release --token $(azuresdk-github-pat) --repo autorest.python --owner azure --name "Autorest for Python v$DEV_VERSION" --tag v$DEV_VERSION --notes='Preview version of autorest for python v5' --prerelease --editRelease false --assets autorest-python-$DEV_VERSION.tgz --target_commitish $(Build.SourceBranchName)
displayName: 'Publish development release'
Loading

0 comments on commit a5fa9ea

Please sign in to comment.