Skip to content

Commit

Permalink
Converting OrderedDict to dict
Browse files Browse the repository at this point in the history
  • Loading branch information
swansonk14 committed Nov 12, 2023
1 parent 70137fd commit e36a025
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 45 deletions.
21 changes: 8 additions & 13 deletions tap/tap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import sys
import time
from argparse import ArgumentParser, ArgumentTypeError
from collections import OrderedDict
from copy import deepcopy
from functools import partial
from pathlib import Path
Expand Down Expand Up @@ -85,7 +84,7 @@ def __init__(self,
self.extra_args = []

# Create argument buffer
self.argument_buffer = OrderedDict()
self.argument_buffer = {}

# Create a place to put all of the subparsers
self._subparser_buffer: List[Tuple[str, type, Dict[str, Any]]] = []
Expand Down Expand Up @@ -475,25 +474,22 @@ def parse_args(self: TapType,
return self

@classmethod
def _get_from_self_and_super(cls,
extract_func: Callable[[type], dict],
dict_type: type = dict) -> Union[Dict[str, Any], OrderedDict]:
def _get_from_self_and_super(cls, extract_func: Callable[[type], dict]) -> Union[Dict[str, Any], Dict]:
"""Returns a dictionary mapping variable names to values.
Variables and values are extracted from classes using key starting
with this class and traversing up the super classes up through Tap.
If super class and sub class have the same key, the sub class value is used.
If super class and subclass have the same key, the subclass value is used.
Super classes are traversed through breadth first search.
:param extract_func: A function that extracts from a class a dictionary mapping variables to values.
:param dict_type: The type of dictionary to use (e.g. dict, OrderedDict, etc.)
:return: A dictionary mapping variable names to values from the class dict.
"""
visited = set()
super_classes = [cls]
dictionary = dict_type()
dictionary = {}

while len(super_classes) > 0:
super_class = super_classes.pop(0)
Expand Down Expand Up @@ -536,14 +532,13 @@ def _get_annotations(self) -> Dict[str, Any]:
extract_func=lambda super_class: dict(get_type_hints(super_class))
)

def _get_class_variables(self) -> OrderedDict:
"""Returns an OrderedDict mapping class variables names to their additional information."""
def _get_class_variables(self) -> dict:
"""Returns a dictionary mapping class variables names to their additional information."""
class_variable_names = {**self._get_annotations(), **self._get_class_dict()}.keys()

try:
class_variables = self._get_from_self_and_super(
extract_func=lambda super_class: get_class_variables(super_class),
dict_type=OrderedDict
extract_func=lambda super_class: get_class_variables(super_class)
)

# Handle edge-case of source code modification while code is running
Expand All @@ -557,7 +552,7 @@ def _get_class_variables(self) -> OrderedDict:
class_variables.pop(variable)
# Exception if inspect.getsource fails to extract the source code
except Exception:
class_variables = OrderedDict()
class_variables = {}
for variable in class_variable_names:
class_variables[variable] = {'comment': ''}

Expand Down
7 changes: 3 additions & 4 deletions tap/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from argparse import ArgumentParser, ArgumentTypeError
from base64 import b64encode, b64decode
from collections import OrderedDict
import copy
from functools import wraps
import inspect
Expand Down Expand Up @@ -218,8 +217,8 @@ def source_line_to_tokens(obj: object) -> Dict[int, List[Dict[str, Union[str, in
return line_to_tokens


def get_class_variables(cls: type) -> OrderedDict:
"""Returns an OrderedDict mapping class variables to their additional information (currently just comments)."""
def get_class_variables(cls: type) -> Dict[str, Dict[str, str]]:
"""Returns a dictionary mapping class variables to their additional information (currently just comments)."""
# Get mapping from line number to tokens
line_to_tokens = source_line_to_tokens(cls)

Expand All @@ -228,7 +227,7 @@ def get_class_variables(cls: type) -> OrderedDict:

# Extract class variables
class_variable = None
variable_to_comment = OrderedDict()
variable_to_comment = {}
for tokens in line_to_tokens.values():
for i, token in enumerate(tokens):

Expand Down
40 changes: 12 additions & 28 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from argparse import ArgumentTypeError
from collections import OrderedDict
import json
import os
import subprocess
Expand Down Expand Up @@ -192,31 +191,26 @@ class ClassVariableTests(TestCase):
def test_no_variables(self):
class NoVariables:
pass
self.assertEqual(get_class_variables(NoVariables), OrderedDict())
self.assertEqual(get_class_variables(NoVariables), {})

def test_one_variable(self):
class OneVariable:
arg = 2
class_variables = OrderedDict()
class_variables['arg'] = {'comment': ''}
class_variables = {'arg': {'comment': ''}}
self.assertEqual(get_class_variables(OneVariable), class_variables)

def test_multiple_variable(self):
class MultiVariable:
arg_1 = 2
arg_2 = 3
class_variables = OrderedDict()
class_variables['arg_1'] = {'comment': ''}
class_variables['arg_2'] = {'comment': ''}
class_variables = {'arg_1': {'comment': ''}, 'arg_2': {'comment': ''}}
self.assertEqual(get_class_variables(MultiVariable), class_variables)

def test_typed_variables(self):
class TypedVariable:
arg_1: str
arg_2: int = 3
class_variables = OrderedDict()
class_variables['arg_1'] = {'comment': ''}
class_variables['arg_2'] = {'comment': ''}
class_variables = {'arg_1': {'comment': ''}, 'arg_2': {'comment': ''}}
self.assertEqual(get_class_variables(TypedVariable), class_variables)

def test_separated_variables(self):
Expand All @@ -232,9 +226,7 @@ def func(self):

arg_2: int = 3
"""More comment"""
class_variables = OrderedDict()
class_variables['arg_1'] = {'comment': ''}
class_variables['arg_2'] = {'comment': 'More comment'}
class_variables = {'arg_1': {'comment': ''}, 'arg_2': {'comment': 'More comment'}}
self.assertEqual(get_class_variables(SeparatedVariable), class_variables)

def test_commented_variables(self):
Expand All @@ -251,10 +243,8 @@ def func(self):
arg_2: int = 3 # Arg 2 comment
arg_3 : Dict[str, int] # noqa E203,E262 Poorly formatted comment
"""More comment"""
class_variables = OrderedDict()
class_variables['arg_1'] = {'comment': 'Arg 1 comment'}
class_variables['arg_2'] = {'comment': 'Arg 2 comment'}
class_variables['arg_3'] = {'comment': 'noqa E203,E262 Poorly formatted comment More comment'}
class_variables = {'arg_1': {'comment': 'Arg 1 comment'}, 'arg_2': {'comment': 'Arg 2 comment'},
'arg_3': {'comment': 'noqa E203,E262 Poorly formatted comment More comment'}}
self.assertEqual(get_class_variables(CommentedVariable), class_variables)

def test_bad_spacing_multiline(self):
Expand All @@ -275,7 +265,7 @@ class TrickyMultiline:
line!!
"""

class_variables = OrderedDict()
class_variables = {}
comment = 'Header line Footer\nT\n A\n P\n\n multi\n line!!'
class_variables['foo'] = {'comment': comment}
self.assertEqual(get_class_variables(TrickyMultiline), class_variables)
Expand All @@ -288,9 +278,7 @@ class TripleQuoteMultiline:
hi: str
"""Hello there"""

class_variables = OrderedDict()
class_variables['bar'] = {'comment': 'biz baz'}
class_variables['hi'] = {'comment': 'Hello there'}
class_variables = {'bar': {'comment': 'biz baz'}, 'hi': {'comment': 'Hello there'}}
self.assertEqual(get_class_variables(TripleQuoteMultiline), class_variables)

def test_single_quote_multiline(self):
Expand All @@ -301,9 +289,7 @@ class SingleQuoteMultiline:
hi: str
"Hello there"

class_variables = OrderedDict()
class_variables['bar'] = {'comment': 'biz baz'}
class_variables['hi'] = {'comment': 'Hello there'}
class_variables = {'bar': {'comment': 'biz baz'}, 'hi': {'comment': 'Hello there'}}
self.assertEqual(get_class_variables(SingleQuoteMultiline), class_variables)

def test_functions_with_docs_multiline(self):
Expand All @@ -315,16 +301,14 @@ def f(self):
a: str = 'hello' # noqa F841
"""with docs"""

class_variables = OrderedDict()
class_variables['i'] = {'comment': ''}
class_variables = {'i': {'comment': ''}}
self.assertEqual(get_class_variables(FunctionsWithDocs), class_variables)

def test_dataclass(self):
@class_decorator
class DataclassColumn:
arg: int = 5
class_variables = OrderedDict()
class_variables['arg'] = {'comment': ''}
class_variables = {'arg': {'comment': ''}}
self.assertEqual(get_class_variables(DataclassColumn), class_variables)


Expand Down

0 comments on commit e36a025

Please sign in to comment.