Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
- uses: actions/checkout@v4

- name: Run ruff
run: pipx run ruff check --output-format=github explorer
run: pipx run ruff==0.16.8 check --output-format=github explorer
10 changes: 3 additions & 7 deletions explorer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@

def get_version(short=False):
assert __version_info__["releaselevel"] in ("alpha", "beta", "final")
vers = ["%(major)i.%(minor)i" % __version_info__, ]
vers = [f"{__version_info__['major']}.{__version_info__['minor']}", ]
if __version_info__["patch"]:
vers.append(".%(patch)i" % __version_info__)
vers.append(f".{__version_info__['patch']}")
if __version_info__["releaselevel"] != "final" and not short:
vers.append(
"%s%i" % (
__version_info__["releaselevel"][0],
__version_info__["serial"])
)
vers.append(f"{__version_info__['releaselevel'][0]}{__version_info__['serial']}")
return "".join(vers)


Expand Down
2 changes: 1 addition & 1 deletion explorer/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class UserFactory(DjangoModelFactory):
class Meta:
model = settings.AUTH_USER_MODEL

username = Sequence(lambda n: "User %03d" % n)
username = Sequence(lambda n: f"User {n:03d}")
is_staff = True


Expand Down
27 changes: 16 additions & 11 deletions explorer/tests/test_type_infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ def _get_csv(csv_name):
return csv_bytes


def _is_text_dtype(series):
# pandas < 3 stores text as object; pandas 3 uses a dedicated string dtype
return pd.api.types.is_object_dtype(series) or pd.api.types.is_string_dtype(series)


def _get_json(json_name):
current_script_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(current_script_dir, "json", json_name)
Expand All @@ -34,16 +39,16 @@ class TestCsvToTypedDf(TestCase):

def test_mixed_types(self):
df = csv_to_typed_df(_get_csv("mixed.csv"))
self.assertTrue(pd.api.types.is_object_dtype(df["Value1"]))
self.assertTrue(pd.api.types.is_object_dtype(df["Value2"]))
self.assertTrue(pd.api.types.is_object_dtype(df["Value3"]))
self.assertTrue(_is_text_dtype(df["Value1"]))
self.assertTrue(_is_text_dtype(df["Value2"]))
self.assertTrue(_is_text_dtype(df["Value3"]))

def test_all_types(self):
df = csv_to_typed_df(_get_csv("all_types.csv"))
self.assertTrue(pd.api.types.is_datetime64_ns_dtype(df["Dates"]))
self.assertTrue(pd.api.types.is_datetime64_any_dtype(df["Dates"]))
self.assertTrue(pd.api.types.is_integer_dtype(df["Integers"]))
self.assertTrue(pd.api.types.is_float_dtype(df["Floats"]))
self.assertTrue(pd.api.types.is_object_dtype(df["Strings"]))
self.assertTrue(_is_text_dtype(df["Strings"]))

def test_integer_parsing(self):
df = csv_to_typed_df(_get_csv("integers.csv"))
Expand All @@ -62,27 +67,27 @@ def test_date_parsing(self):
# Day of Year: 2024-024 (Year-DayOfYear)

df = csv_to_typed_df(_get_csv("dates.csv"))
self.assertTrue(pd.api.types.is_datetime64_ns_dtype(df["Dates"]))
self.assertTrue(pd.api.types.is_datetime64_any_dtype(df["Dates"]))


@skipIf(not EXPLORER_USER_UPLOADS_ENABLED, "User uploads not enabled")
class TestJsonToTypedDf(TestCase):

def test_basic_json(self):
df = json_to_typed_df(_get_json("kings.json"))
self.assertTrue(pd.api.types.is_object_dtype(df["Name"]))
self.assertTrue(pd.api.types.is_object_dtype(df["Country"]))
self.assertTrue(_is_text_dtype(df["Name"]))
self.assertTrue(_is_text_dtype(df["Country"]))
self.assertTrue(pd.api.types.is_integer_dtype(df["ID"]))

def test_nested_json(self):
df = json_to_typed_df(_get_json("github.json"))
self.assertTrue(pd.api.types.is_object_dtype(df["subscription_url"]))
self.assertTrue(pd.api.types.is_object_dtype(df["topics"]))
self.assertTrue(_is_text_dtype(df["subscription_url"]))
self.assertTrue(_is_text_dtype(df["topics"]))
self.assertTrue(pd.api.types.is_integer_dtype(df["size"]))
self.assertTrue(pd.api.types.is_integer_dtype(df["owner.id"]))

def test_json_list(self):
df = json_list_to_typed_df(_get_json("list.json"))
self.assertTrue(pd.api.types.is_integer_dtype(df["Item.value.M.unique_connection_count.N"]))
self.assertTrue(pd.api.types.is_object_dtype(df["Item.instanceId.S"]))
self.assertTrue(_is_text_dtype(df["Item.instanceId.S"]))
self.assertEqual(len(df), 5)
2 changes: 1 addition & 1 deletion explorer/views/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
logger = logging.getLogger(__name__)


def query_viewmodel(request, query, title=None, form=None, message=None,
def query_viewmodel(request, query, title=None, form=None, message=None, # noqa: PLR0917
run_query=True, error=None,
rows=app_settings.EXPLORER_DEFAULT_ROWS):
"""
Expand Down
2 changes: 2 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
line-length = 120
# Keep in sync with python_requires in setup.py; ruff can't read it from there.
target-version = "py38"

extend-exclude = [
".ruff_cache",
Expand Down
Loading