Repository: pydicom/pydicom

Issue:
Revise the type annotation for pydicom.datadict.dictionary_has_tag()
**Describe the bug**

The documentation of [`pydicom.datadict.dictionary_has_tag()`](https://pydicom.github.io/pydicom/dev/reference/generated/pydicom.datadict.dictionary_has_tag.html#pydicom.datadict.dictionary_has_tag) suggests that a query using keywords (instead of a tag integer) would work:

```python
pydicom.datadict.dictionary_has_tag(tag: Union[int, str, Tuple[int, int], pydicom.tag.BaseTag]) -> bool
```

However, the function only accepts integer arguments.

```python
from pydicom.datadict import dictionary_has_tag, keyword_dict
dictionary_has_tag("PixelData")
# Returns False

dictionary_has_tag(keyword_dict["PixelData"])
# Returns True
```

(The problem may apply to other functions as well...)

**Expected behavior**
Following the docs, `dictionary_has_tag("PixelData")` should return True. 

It would be nice, if the flexible conversion of tags from names or hex-tuples (as the type annotation suggests) would also be possible for this function.

**Your environment**
```text
module       | version
------       | -------
platform     | macOS-10.14.6-x86_64-i386-64bit
Python       | 3.9.0 (v3.9.0:9cf6752276, Oct  5 2020, 11:29:23)  [Clang 6.0 (clang-600.0.57)]
pydicom      | 2.2.2
gdcm         | _module not found_
jpeg_ls      | _module not found_
numpy        | 1.20.1
PIL          | 8.0.1
pylibjpeg    | _module not found_
openjpeg     | _module not found_
libjpeg      | _module not found_
```




Discussion:
Yeah, it should be plain old `int`. Not sure how I missed that one...

The keyword to tag conversion is actually kind of (relatively) expensive, and this function is used in our initial dataset parsing so we want it to be fast.

Patch:
diff --git a/pydicom/datadict.py b/pydicom/datadict.py
--- a/pydicom/datadict.py
+++ b/pydicom/datadict.py
@@ -249,9 +249,10 @@ def get_entry(tag: TagType) -> Tuple[str, str, str, str, str]:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose entry is to be retrieved. Only entries
-        in the official DICOM dictionary will be checked, not entries in the
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose entry is to be retrieved, in any of the
+        forms accepted by :func:`~pydicom.tag.Tag`. Only entries in the
+        official DICOM dictionary will be checked, not entries in the
         private dictionary.
 
     Returns
@@ -292,8 +293,9 @@ def dictionary_is_retired(tag: TagType) -> bool:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose retirement status is being checked.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose retirement status is being checked, in
+        any of the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -306,9 +308,7 @@ def dictionary_is_retired(tag: TagType) -> bool:
     KeyError
         If the tag is not present in the DICOM data dictionary.
     """
-    if 'retired' in get_entry(tag)[3].lower():
-        return True
-    return False
+    return 'retired' in get_entry(tag)[3].lower()
 
 
 def dictionary_VR(tag: TagType) -> str:
@@ -318,9 +318,9 @@ def dictionary_VR(tag: TagType) -> str:
 
     Parameters
     ----------
-    tag : int
+    tag : int or str or Tuple[int, int]
         The tag for the element whose value representation (VR) is being
-        retrieved.
+        retrieved, in any of the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -342,9 +342,9 @@ def dictionary_VM(tag: TagType) -> str:
 
     Parameters
     ----------
-    tag : int
+    tag : int or str or Tuple[int, int]
         The tag for the element whose value multiplicity (VM) is being
-        retrieved.
+        retrieved, in any of the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -366,8 +366,9 @@ def dictionary_description(tag: TagType) -> str:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose description is being retrieved.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose description is being retrieved, in any
+        of the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -389,8 +390,9 @@ def dictionary_keyword(tag: TagType) -> str:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose keyword is being retrieved.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose keyword is being retrieved, in any of
+        the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -410,8 +412,9 @@ def dictionary_has_tag(tag: TagType) -> bool:
 
     Parameters
     ----------
-    tag : int
-        The tag to check.
+    tag : int or str or Tuple[int, int]
+        The tag to check, in any of the forms accepted by
+        :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -419,7 +422,10 @@ def dictionary_has_tag(tag: TagType) -> bool:
         ``True`` if the tag corresponds to an element present in the official
         DICOM data dictionary, ``False`` otherwise.
     """
-    return (tag in DicomDictionary)
+    try:
+        return Tag(tag) in DicomDictionary
+    except Exception:
+        return False
 
 
 def keyword_for_tag(tag: TagType) -> str:
@@ -427,8 +433,9 @@ def keyword_for_tag(tag: TagType) -> str:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose keyword is being retrieved.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose keyword is being retrieved, in any of
+        the forms accepted by :func:`~pydicom.tag.Tag`.
 
     Returns
     -------
@@ -514,9 +521,10 @@ def get_private_entry(
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose entry is to be retrieved. Only entries
-        in the private dictionary will be checked.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose entry is to be retrieved, in any of the
+        forms accepted by :func:`~pydicom.tag.Tag`. Only entries in the
+        private dictionary will be checked.
     private_creator : str
         The name of the private creator.
 
@@ -574,9 +582,9 @@ def private_dictionary_VR(tag: TagType, private_creator: str) -> str:
 
     Parameters
     ----------
-    tag : int
+    tag : int or str or Tuple[int, int]
         The tag for the element whose value representation (VR) is being
-        retrieved.
+        retrieved, in any of the forms accepted by :func:`~pydicom.tag.Tag`.
     private_creator : str
         The name of the private creator.
 
@@ -598,9 +606,9 @@ def private_dictionary_VM(tag: TagType, private_creator: str) -> str:
 
     Parameters
     ----------
-    tag : int
+    tag : int or str or Tuple[int, int]
         The tag for the element whose value multiplicity (VM) is being
-        retrieved.
+        retrieved, in any of the forms accepted by :func:`~pydicom.tag.Tag`.
     private_creator : str
         The name of the private creator.
 
@@ -622,8 +630,9 @@ def private_dictionary_description(tag: TagType, private_creator: str) -> str:
 
     Parameters
     ----------
-    tag : int
-        The tag for the element whose description is being retrieved.
+    tag : int or str or Tuple[int, int]
+        The tag for the element whose description is being retrieved, in any
+        of the forms accepted by :func:`~pydicom.tag.Tag`.
     private_creator : str
         The name of the private createor.
 


Test patch:
diff --git a/pydicom/tests/test_dictionary.py b/pydicom/tests/test_dictionary.py
--- a/pydicom/tests/test_dictionary.py
+++ b/pydicom/tests/test_dictionary.py
@@ -30,6 +30,8 @@ def test_dict_has_tag(self):
         """Test dictionary_has_tag"""
         assert dictionary_has_tag(0x00100010)
         assert not dictionary_has_tag(0x11110010)
+        assert dictionary_has_tag("PatientName")
+        assert not dictionary_has_tag("PatientMane")
 
     def test_repeater_has_tag(self):
         """Test repeater_has_tag"""