codecov-io: # [Codecov](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=h1) Report
> Merging [#18](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=desc) into [master](https://codecov.io/gh/linw1995/data_extractor/commit/ee4cc11a17b617461cf93168bbcd81fbbc14db07?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/linw1995/data_extractor/pull/18/graphs/tree.svg?width=650&token=wLe2IyZWQl&height=150&src=pr)](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           master    #18   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           7      7           
  Lines         148    152    +4     
  Branches       20     21    +1     
=====================================
+ Hits          148    152    +4
```


| [Impacted Files](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [data\_extractor/abc.py](https://codecov.io/gh/linw1995/data_extractor/pull/18/diff?src=pr&el=tree#diff-ZGF0YV9leHRyYWN0b3IvYWJjLnB5) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=footer). Last update [ee4cc11...daec6ae](https://codecov.io/gh/linw1995/data_extractor/pull/18?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/data_extractor/abc.py b/data_extractor/abc.py
index 0c2434e..115b15e 100644
--- a/data_extractor/abc.py
+++ b/data_extractor/abc.py
@@ -3,6 +3,7 @@
 ====================================
 """
 # Standard Library
+import inspect
 import warnings
 
 from abc import abstractmethod
@@ -20,8 +21,41 @@ class ComplexExtractorMeta(type):
     def __init__(cls, name: str, bases: Tuple[type], attr_dict: Dict[str, Any]):
         super().__init__(name, bases, attr_dict)
         field_names: List[str] = []
+
+        __init_args = inspect.getfullargspec(getattr(cls, "__init__")).args
+
         for key, attr in attr_dict.items():
             if isinstance(type(attr), ComplexExtractorMeta):
+                if key in __init_args:
+                    frame = inspect.currentframe()
+                    assert (
+                        frame is not None
+                    ), "If running in an implementation without Python stack frame support this function returns None."
+                    try:
+                        outer_frame = frame.f_back
+
+                        filename = outer_frame.f_code.co_filename
+                        firstlineno = outer_frame.f_lineno
+                        lines, _ = inspect.findsource(outer_frame)
+
+                        for lineno, line in enumerate(lines[firstlineno:], start=1):
+                            if line.strip().startswith(key):
+                                break
+                        else:  # pragma: no cover
+                            assert False, "This line is never executed."
+
+                        lineno += firstlineno
+                        index = inspect.indentsize(line)
+                    finally:
+                        del outer_frame
+                        del frame
+
+                    line = line.strip()
+                    raise SyntaxError(
+                        f"{line!r} overwriten the parameter {key!r} of '{name}.__init__' method.",
+                        (filename, lineno, index, line),
+                    )
+
                 field_names.append(key)
 
         cls._field_names = field_names

The field name is the same as Item's parameter in Item.

```python3
class Parameter(Item):
    name = Field(XPathExtractor("./span[@class='name']"))
    default = Field(XPathExtractor("./span[@class='default']"))

extractor = Parameter(XPathExtractor("./li[@class='parameter']", default=None)
```
the `default=None` parameter overwrites the Field `default = Field(XPathExtractor("./span[@class='default']"))` of Item.
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index decde7e..7f8cbe9 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -1,4 +1,5 @@
 # Standard Library
+import inspect
 import textwrap
 
 # Third Party Library
@@ -8,6 +9,7 @@ import pytest
 from data_extractor.exceptions import ExtractError
 from data_extractor.item import Field, Item
 from data_extractor.json import JSONExtractor
+from data_extractor.lxml import XPathExtractor
 
 
 def test_exception_trace(json0):
@@ -47,3 +49,17 @@ def test_exception_trace(json0):
             """
         ).strip()
     )
+
+
+def test_field_name_overwrite_item_parameter():
+    with pytest.raises(SyntaxError) as catch:
+
+        class Parameter(Item):
+            name = Field(XPathExtractor("./span[@class='name']"))
+            default = Field(XPathExtractor("./span[@class='default']"))
+
+    exc = catch.value
+    assert exc.filename == __file__
+    assert exc.lineno == inspect.currentframe().f_lineno - 4
+    assert exc.offset == 12
+    assert exc.text == "default = Field(XPathExtractor(\"./span[@class='default']\"))"

pip install -e .
parse_log_pytest
Pipfile
pytest
3.7
Pipfile
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
certifi @ file:///croot/certifi_1671487769961/work/certifi
cssselect==1.2.0
-e git+https://github.com/linw1995/data_extractor.git@ee4cc11a17b617461cf93168bbcd81fbbc14db07#egg=data_extractor
decorator==5.1.1
exceptiongroup==1.2.2
importlib-metadata==6.7.0
iniconfig==2.0.0
jsonpath-rw==1.4.0
lxml==5.3.1
packaging==24.0
pipfile==0.0.2
pluggy==1.2.0
ply==3.11
pytest==7.4.4
six==1.17.0
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==2.0.1
typing_extensions==4.7.1
zipp==3.15.0

name: data_extractor
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - pipfile=0.0.2=py_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - cssselect==1.2.0
      - decorator==5.1.1
      - exceptiongroup==1.2.2
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - jsonpath-rw==1.4.0
      - lxml==5.3.1
      - packaging==24.0
      - pluggy==1.2.0
      - ply==3.11
      - pytest==7.4.4
      - six==1.17.0
      - tomli==2.0.1
      - typing-extensions==4.7.1
      - zipp==3.15.0
prefix: /opt/conda/envs/data_extractor

tests/test_exceptions.py::test_field_name_overwrite_item_parameter
tests/test_exceptions.py::test_exception_trace
data_extractor/abc.py
data_extractor/abc.py