Repository: koxudaxi/datamodel-code-generator

Issue:
Optional command to generate code without constr
**Is your feature request related to a problem? Please describe.**

The inclusion of `constr` in the generated datamodel when it contains regular expressions can cause the generated code to fail checks in mypy and flake8.

Specifically, with `https://github.com/compose-spec/compose-spec/blob/master/schema/compose-spec.json` as the target file, the following command attempts to generate the code.
````
datamodel-codegen --input compose-spec.json --input-file-type jsonschema --output model.py --field-constraints --target-python-version 3.8
````

Part of the generated result contains the following code
```
    services: Optional[Dict[constr(regex=r'^[a-zA-Z0-9._-]+$'), Service]] = None
````
This fails on mypy and flake8 checks.

**Describe the solution you'd like**

The reason for the failure seems to be the use of constr, so I would like an optional command that outputs in a format that does not contain constr (nor conint).

**Describe alternatives you've considered**

If there is already an optional command that accomplishes this kind of functionality, it would be great to know.
I have already tried the `--field-constraints`, `-use-annotated` option commands, etc., but they did not solve this problem.

**Additional context**

If it is difficult to express a constraint by regular expression without using constr, I would like to see a behavior that replaces constr with str and outputs a warning.


Thank you for creating such a great package.


Discussion:

Resolving patch:
diff --git a/datamodel_code_generator/format.py b/datamodel_code_generator/format.py
--- a/datamodel_code_generator/format.py
+++ b/datamodel_code_generator/format.py
@@ -51,7 +51,7 @@ def _find_project_root(
     project_root = _find_project_root(tuple(str(s) for s in sources))
     if isinstance(project_root, tuple):
         return project_root[0]
-    else:
+    else:  # pragma: no cover
         return project_root
 
 
diff --git a/datamodel_code_generator/parser/jsonschema.py b/datamodel_code_generator/parser/jsonschema.py
--- a/datamodel_code_generator/parser/jsonschema.py
+++ b/datamodel_code_generator/parser/jsonschema.py
@@ -670,7 +670,7 @@ def parse_item(
                             is_dict=True,
                             dict_key=self.data_type_manager.get_data_type(
                                 Types.string,
-                                pattern=k,
+                                pattern=k if not self.field_constraints else None,
                             ),
                         )
                         for k, v in item.patternProperties.items()


Test patch:
diff --git a/tests/data/expected/main/main_pattern_properties_field_constraints/output.py b/tests/data/expected/main/main_pattern_properties_field_constraints/output.py
new file mode 100644
--- /dev/null
+++ b/tests/data/expected/main/main_pattern_properties_field_constraints/output.py
@@ -0,0 +1,17 @@
+# generated by datamodel-codegen:
+#   filename:  pattern_properties.json
+#   timestamp: 2019-07-26T00:00:00+00:00
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+
+from pydantic import BaseModel
+
+
+class Bar(BaseModel):
+    name: Optional[str] = None
+
+
+class Foo(BaseModel):
+    bar: Dict[str, Bar]
diff --git a/tests/test_main.py b/tests/test_main.py
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -3480,6 +3480,34 @@ def test_jsonschema_pattern_properties():
         main()
 
 
+@freeze_time('2019-07-26')
+def test_jsonschema_pattern_properties_field_constraints():
+    with TemporaryDirectory() as output_dir:
+        output_file: Path = Path(output_dir) / 'output.py'
+        return_code: Exit = main(
+            [
+                '--input',
+                str(JSON_SCHEMA_DATA_PATH / 'pattern_properties.json'),
+                '--output',
+                str(output_file),
+                '--input-file-type',
+                'jsonschema',
+                '--field-constraints',
+            ]
+        )
+        assert return_code == Exit.OK
+        assert (
+            output_file.read_text()
+            == (
+                EXPECTED_MAIN_PATH
+                / 'main_pattern_properties_field_constraints'
+                / 'output.py'
+            ).read_text()
+        )
+    with pytest.raises(SystemExit):
+        main()
+
+
 @freeze_time('2019-07-26')
 def test_jsonschema_titles():
     with TemporaryDirectory() as output_dir: