codecov-io: # [Codecov](https://codecov.io/gh/SAP/python-pyodata/pull/57?src=pr&el=h1) Report
> Merging [#57](https://codecov.io/gh/SAP/python-pyodata/pull/57?src=pr&el=desc) into [master](https://codecov.io/gh/SAP/python-pyodata/commit/00667d982a54063c18669582dd8eb16a9b2192f4?src=pr&el=desc) will **increase** coverage by `0.07%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/SAP/python-pyodata/pull/57/graphs/tree.svg?width=650&token=nInJCpPrP3&height=150&src=pr)](https://codecov.io/gh/SAP/python-pyodata/pull/57?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master      #57      +/-   ##
==========================================
+ Coverage   91.25%   91.32%   +0.07%     
==========================================
  Files           6        6              
  Lines        2207     2226      +19     
==========================================
+ Hits         2014     2033      +19     
  Misses        193      193
```


| [Impacted Files](https://codecov.io/gh/SAP/python-pyodata/pull/57?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pyodata/v2/service.py](https://codecov.io/gh/SAP/python-pyodata/pull/57/diff?src=pr&el=tree#diff-cHlvZGF0YS92Mi9zZXJ2aWNlLnB5) | `89.7% <100%> (+0.28%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/SAP/python-pyodata/pull/57?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/SAP/python-pyodata/pull/57?src=pr&el=footer). Last update [00667d9...e81d166](https://codecov.io/gh/SAP/python-pyodata/pull/57?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/docs/index.rst b/docs/index.rst
index 2b74cdb..21de391 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -50,6 +50,7 @@ The User Guide
    usage/initialization.rst
    usage/querying.rst
    usage/creating.rst
+   usage/deleting.rst
    usage/function_imports.rst
    usage/metadata.rst
    usage/advanced.rst
diff --git a/docs/usage/README.md b/docs/usage/README.md
index 52ba147..d31f172 100644
--- a/docs/usage/README.md
+++ b/docs/usage/README.md
@@ -4,6 +4,7 @@ The User Guide
 * [Initialization](initialization.rst)
 * [Querying](querying.rst)
 * [Creating](creating.rst)
+* [Deleting](deleting.rst)
 * [Function Imports](function_imports.rst)
 * [Metadata](metadata.rst)
 * [Advanced](advanced.rst)
diff --git a/docs/usage/deleting.rst b/docs/usage/deleting.rst
new file mode 100644
index 0000000..f683fbf
--- /dev/null
+++ b/docs/usage/deleting.rst
@@ -0,0 +1,44 @@
+Deleting
+========
+
+.. _CSRF: https://en.wikipedia.org/wiki/Cross-site_request_forgery
+.. _Requests: https://2.python-requests.org/en/master/
+
+The delete action executes the HTTP method DELETE which is usually protected by
+CSRF_ and therefore you must make some effort to initialize your HTTP Session
+to send DELETE requests acceptable by the remote server.
+
+Let's assume you use the python library Requests_
+
+.. code-block:: python
+
+    import pyodata
+    import requests
+
+    SERVICE_URL = 'http://example.io/TheServiceRoot/'
+
+    session = requests.Session()
+    response = session.head(SERVICE_URL, headers={'x-csrf-token': 'fetch'})
+    token = response.headers.get('x-csrf-token', '')
+    session.headers.update({'x-csrf-token': token})
+
+    theservice = pyodata.Client(SERVICE_URL, session)
+
+
+Deleting an entity
+------------------
+
+You can either delete entity by passing its PropertyRef value to the delete function
+
+.. code-block:: python
+
+    request = service.entity_sets.Employees.delete_entity(23)
+    request.execute()
+
+or by passing the EntityKey object
+
+.. code-block:: python
+
+    key = EntityKey(service.schema.entity_type('Employee'), ID=23)
+    request = service.entity_sets.Employees.delete_entity(key=key)
+    request.execute()
\ No newline at end of file
diff --git a/pyodata/v2/service.py b/pyodata/v2/service.py
index 6190dab..907a39d 100644
--- a/pyodata/v2/service.py
+++ b/pyodata/v2/service.py
@@ -480,6 +480,25 @@ class EntityCreateRequest(ODataHttpRequest):
         return self
 
 
+class EntityDeleteRequest(ODataHttpRequest):
+    """Used for deleting entity (DELETE operations on a single entity)"""
+
+    def __init__(self, url, connection, handler, entity_set, entity_key):
+        super(EntityDeleteRequest, self).__init__(url, connection, handler)
+        self._logger = logging.getLogger(LOGGER_NAME)
+        self._entity_set = entity_set
+        self._entity_key = entity_key
+
+        self._logger.debug('New instance of EntityDeleteRequest for entity type: %s', entity_set.entity_type.name)
+
+    def get_path(self):
+        return self._entity_set.name + self._entity_key.to_key_string()
+
+    def get_method(self):
+        # pylint: disable=no-self-use
+        return 'DELETE'
+
+
 class EntityModifyRequest(ODataHttpRequest):
     """Used for modyfing entities (UPDATE/MERGE operations on a single entity)
 
@@ -1131,6 +1150,25 @@ class EntitySetProxy:
         return EntityModifyRequest(self._service.url, self._service.connection, update_entity_handler, self._entity_set,
                                    entity_key)
 
+    def delete_entity(self, key: EntityKey = None, **kwargs):
+        """Delete the entity"""
+
+        def delete_entity_handler(response):
+            """Check if entity deletion was successful"""
+
+            if response.status_code != 204:
+                raise HttpError(f'HTTP POST for Entity delete {self._name} '
+                                f'failed with status code {response.status_code}',
+                                response)
+
+        if key is not None and isinstance(key, EntityKey):
+            entity_key = key
+        else:
+            entity_key = EntityKey(self._entity_set.entity_type, key, **kwargs)
+
+        return EntityDeleteRequest(self._service.url, self._service.connection, delete_entity_handler, self._entity_set,
+                                   entity_key)
+
 
 # pylint: disable=too-few-public-methods
 class EntityContainer:

Function to delete entity?
Is there a delete entity function?
diff --git a/tests/test_service_v2.py b/tests/test_service_v2.py
index 3a508c8..cdcc1b8 100644
--- a/tests/test_service_v2.py
+++ b/tests/test_service_v2.py
@@ -590,6 +590,46 @@ def test_update_entity(service):
     request.execute()
 
 
+@responses.activate
+def test_delete_entity(service):
+    """Check deleting of entity"""
+
+    responses.add(responses.DELETE, f"{service.url}/Employees(23)", status=204)
+    request = service.entity_sets.Employees.delete_entity(23)
+
+    assert isinstance(request, pyodata.v2.service.EntityDeleteRequest)
+    assert request.execute() is None
+
+
+@responses.activate
+def test_delete_entity_with_key(service):
+    """Check deleting of entity with key"""
+
+    responses.add(responses.DELETE, f"{service.url}/Employees(ID=23)", status=204)
+    key = EntityKey(service.schema.entity_type('Employee'), ID=23)
+    request = service.entity_sets.Employees.delete_entity(key=key)
+
+    assert isinstance(request, pyodata.v2.service.EntityDeleteRequest)
+    assert request.execute() is None
+
+
+@responses.activate
+def test_delete_entity_http_error(service):
+    """Check if error is raisen when deleting unknown entity"""
+
+    responses.add(responses.DELETE, f"{service.url}/Employees(ID=23)", status=404)
+    key = EntityKey(service.schema.entity_type('Employee'), ID=23)
+    request = service.entity_sets.Employees.delete_entity(key=key)
+
+    assert isinstance(request, pyodata.v2.service.EntityDeleteRequest)
+
+    with pytest.raises(HttpError) as caught_ex:
+        request.execute()
+
+    assert str(caught_ex.value).startswith('HTTP POST for Entity delete')
+    assert caught_ex.value.response.status_code == 404
+
+
 def test_update_entity_with_entity_key(service):
     """Make sure the method update_entity handles correctly the parameter key which is EntityKey"""
 

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.9
requirements.txt dev-requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.16
astroid==3.3.9
babel==2.17.0
certifi==2025.1.31
chardet==3.0.4
codecov==2.1.13
coverage==7.8.0
dill==0.3.9
docutils==0.19
exceptiongroup==1.2.2
flake8==7.2.0
idna==2.7
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
isort==6.0.1
Jinja2==3.1.6
lxml==5.3.1
MarkupSafe==3.0.2
mccabe==0.7.0
packaging==24.2
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pyflakes==3.3.2
Pygments==2.19.1
pylint==3.3.6
-e git+https://github.com/SAP/python-pyodata.git@00667d982a54063c18669582dd8eb16a9b2192f4#egg=pyodata
pytest==8.3.5
pytest-cov==6.0.0
requests==2.20.0
responses==0.10.15
setuptools-scm==8.2.0
six==1.17.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
tomli==2.2.1
tomlkit==0.13.2
typing_extensions==4.13.0
urllib3==1.24.3
zipp==3.21.0

name: python-pyodata
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
  - 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=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.16
      - astroid==3.3.9
      - babel==2.17.0
      - certifi==2025.1.31
      - chardet==3.0.4
      - codecov==2.1.13
      - coverage==7.8.0
      - dill==0.3.9
      - docutils==0.19
      - exceptiongroup==1.2.2
      - flake8==7.2.0
      - idna==2.7
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - isort==6.0.1
      - jinja2==3.1.6
      - lxml==5.3.1
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - packaging==24.2
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pylint==3.3.6
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - requests==2.20.0
      - responses==0.10.15
      - setuptools-scm==8.2.0
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - tomli==2.2.1
      - tomlkit==0.13.2
      - typing-extensions==4.13.0
      - urllib3==1.24.3
      - zipp==3.21.0
prefix: /opt/conda/envs/python-pyodata

tests/test_service_v2.py::test_delete_entity tests/test_service_v2.py::test_delete_entity_with_key tests/test_service_v2.py::test_delete_entity_http_error
tests/test_service_v2.py::test_create_entity tests/test_service_v2.py::test_create_entity_code_201 tests/test_service_v2.py::test_create_entity_code_400 tests/test_service_v2.py::test_create_entity_containing_enum tests/test_service_v2.py::test_create_entity_nested tests/test_service_v2.py::test_create_entity_header_x_requested_with tests/test_service_v2.py::test_create_entity_nested_list tests/test_service_v2.py::test_get_entity_property tests/test_service_v2.py::test_entity_url tests/test_service_v2.py::test_entity_entity_set_name tests/test_service_v2.py::test_entity_key_simple tests/test_service_v2.py::test_entity_key_complex tests/test_service_v2.py::test_get_entity_property_complex_key tests/test_service_v2.py::test_entity_key_simple_valid tests/test_service_v2.py::test_entity_key_simple_named_valid tests/test_service_v2.py::test_entity_key_simple_named_invalid tests/test_service_v2.py::test_entity_key_complex_valid tests/test_service_v2.py::test_entity_key_complex_single_value tests/test_service_v2.py::test_function_import_primitive tests/test_service_v2.py::test_function_import_primitive_unexpected_status_code tests/test_service_v2.py::test_function_import_without_return_type tests/test_service_v2.py::test_function_import_without_return_type_wrong_code tests/test_service_v2.py::test_function_import_http_redirect tests/test_service_v2.py::test_function_import_http_bad_request tests/test_service_v2.py::test_function_import_http_sever_error tests/test_service_v2.py::test_function_import_http_not_authorized tests/test_service_v2.py::test_function_import_http_forbidden tests/test_service_v2.py::test_function_import_entity tests/test_service_v2.py::test_update_entity tests/test_service_v2.py::test_update_entity_with_entity_key tests/test_service_v2.py::test_get_entity_with_entity_key_and_other_params tests/test_service_v2.py::test_navigation_multi tests/test_service_v2.py::test_navigation tests/test_service_v2.py::test_navigation_1on1 tests/test_service_v2.py::test_navigation_1on1_get_value_without_proxy tests/test_service_v2.py::test_navigation_when_nes_in_another_ns tests/test_service_v2.py::test_entity_get_value_1on1_with_proxy tests/test_service_v2.py::test_entity_get_value_without_proxy tests/test_service_v2.py::test_entity_get_value_with_proxy tests/test_service_v2.py::test_entity_get_value_without_proxy_error tests/test_service_v2.py::test_navigation_create_entity tests/test_service_v2.py::test_navigation_from_entity_multi tests/test_service_v2.py::test_navigation_from_entity tests/test_service_v2.py::test_get_entity tests/test_service_v2.py::test_get_entity_expanded tests/test_service_v2.py::test_batch_request tests/test_service_v2.py::test_batch_request_failed_changeset tests/test_service_v2.py::test_get_entity_with_entity_key tests/test_service_v2.py::test_entity_proxy_equals tests/test_service_v2.py::test_get_entity_set_query_filter_eq tests/test_service_v2.py::test_get_entity_set_query_filter_ne tests/test_service_v2.py::test_get_entity_set_query_filter_and tests/test_service_v2.py::test_get_entity_set_query_filter_or tests/test_service_v2.py::test_get_entity_set_query_filter_property_error tests/test_service_v2.py::test_count tests/test_service_v2.py::test_count_with_skip tests/test_service_v2.py::test_navigation_count tests/test_service_v2.py::test_navigation_count_with_filter
docs/index.rst docs/usage/README.md pyodata/v2/service.py docs/usage/deleting.rst
docs/index.rst docs/usage/README.md pyodata/v2/service.py docs/usage/deleting.rst