Repository: pydicom/pydicom

Issue:
`dir(Dataset)` doesn't include all class attributes
There are quite a few class attributes missing from `dir(Dataset)`:
```python
>>> from pydicom.data import get_testdata_file
>>> ds = get_testdata_file("CT_small.dcm", read=True)
>>> "is_implicit_VR" in dir(ds)
False
>>> hasattr(ds, "is_implicit_VR")
True
>>> "pixel_array" in dir(ds)
True
```

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) Report
> Merging [#1600](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (5d2142d) into [master](https://codecov.io/gh/pydicom/pydicom/commit/7c85e1ba2e933a8d2cb238380b1f0e99a1746e47?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (7c85e1b) will **decrease** coverage by `9.30%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/pydicom/pydicom/pull/1600/graphs/tree.svg?width=650&height=150&src=pr&token=YciLV15Lwr&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom)](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom)

```diff
@@            Coverage Diff             @@
##           master    #1600      +/-   ##
==========================================
- Coverage   97.56%   88.26%   -9.31%     
==========================================
  Files          66       66              
  Lines       10626    10393     -233     
==========================================
- Hits        10367     9173    -1194     
- Misses        259     1220     +961     
```


| [Impacted Files](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | Coverage Δ | |
|---|---|---|
| [pydicom/dataset.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9kYXRhc2V0LnB5) | `94.36% <100.00%> (-4.70%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/util.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3V0aWwucHk=) | `18.41% <0.00%> (-81.59%)` | :arrow_down: |
| [pydicom/waveforms/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS93YXZlZm9ybXMvbnVtcHlfaGFuZGxlci5weQ==) | `20.31% <0.00%> (-79.69%)` | :arrow_down: |
| [pydicom/encoders/gdcm.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9lbmNvZGVycy9nZGNtLnB5) | `20.96% <0.00%> (-75.81%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL251bXB5X2hhbmRsZXIucHk=) | `27.14% <0.00%> (-72.86%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/gdcm\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL2dkY21faGFuZGxlci5weQ==) | `26.22% <0.00%> (-66.46%)` | :arrow_down: |
| [pydicom/overlays/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9vdmVybGF5cy9udW1weV9oYW5kbGVyLnB5) | `35.18% <0.00%> (-64.82%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/pillow\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3BpbGxvd19oYW5kbGVyLnB5) | `31.73% <0.00%> (-64.43%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/rle\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3JsZV9oYW5kbGVyLnB5) | `36.97% <0.00%> (-63.03%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/pylibjpeg\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3B5bGlianBlZ19oYW5kbGVyLnB5) | `40.74% <0.00%> (-57.41%)` | :arrow_down: |
| ... and [16 more](https://codecov.io/gh/pydicom/pydicom/pull/1600/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom). Last update [7c85e1b...5d2142d](https://codecov.io/gh/pydicom/pydicom/pull/1600?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom).


Patch:
diff --git a/doc/release_notes/v2.3.0.rst b/doc/release_notes/v2.3.0.rst
index cb02fff31..f84333a2b 100644
--- a/doc/release_notes/v2.3.0.rst
+++ b/doc/release_notes/v2.3.0.rst
@@ -41,3 +41,4 @@ Fixes
   (:issue:`1581`)
 * Fixed crashes on Windows and MacOS when using the GDCM plugin to compress
   into *RLE Lossless* (:issue:`1581`)
+* Fixed ``dir(Dataset())`` not returning class attributes (:issue:`1599`)
diff --git a/pydicom/dataset.py b/pydicom/dataset.py
index 033f333a7..6693ebee8 100644
--- a/pydicom/dataset.py
+++ b/pydicom/dataset.py
@@ -641,19 +641,16 @@ class Dataset:
                 self._private_blocks = {}
 
     def __dir__(self) -> List[str]:
-        """Give a list of attributes available in the :class:`Dataset`.
+        """Return a list of methods, properties, attributes and element
+        keywords available in the :class:`Dataset`.
 
         List of attributes is used, for example, in auto-completion in editors
         or command-line environments.
         """
-        # Force zip object into a list
-        meths = set(list(zip(
-            *inspect.getmembers(self.__class__, inspect.isroutine)))[0])
-        props = set(list(zip(
-            *inspect.getmembers(self.__class__, inspect.isdatadescriptor)))[0])
-        dicom_names = set(self.dir())
-        alldir = sorted(props | meths | dicom_names)
-        return alldir
+        names = set(super().__dir__())
+        keywords = set(self.dir())
+
+        return sorted(names | keywords)
 
     def dir(self, *filters: str) -> List[str]:
         """Return an alphabetical list of element keywords in the


Test patch:
diff --git a/pydicom/tests/test_dataset.py b/pydicom/tests/test_dataset.py
index 5f7b4884a..89e42deff 100644
--- a/pydicom/tests/test_dataset.py
+++ b/pydicom/tests/test_dataset.py
@@ -450,6 +450,12 @@ class TestDataset:
         assert 'John' == self.ds[0x10, 0x10].value
         assert 'Johnny' == self.ds[0x10, 0x12].value
 
+    def test_dir_attr(self):
+        """Dataset.__dir__ returns class attributes"""
+        ds = Dataset()
+        assert hasattr(ds, "is_implicit_VR")
+        assert "is_implicit_VR" in dir(ds)
+
     def test_dir_subclass(self):
         """Dataset.__dir__ returns class specific dir"""
 
@@ -1875,7 +1881,7 @@ class TestFileDataset:
         """Ensure that we don't use inherited dict functionality"""
         ds = Dataset()
         di = dict()
-        expected_diff = {'__class__', '__doc__', '__hash__', 'fromkeys'}
+        expected_diff = {'fromkeys'}
         if sys.version_info[:2] >= (3, 8):
             expected_diff.add('__reversed__')
         if sys.version_info[:2] >= (3, 9):