-
Notifications
You must be signed in to change notification settings - Fork 35
SchemaView: format, lint autofix, add typing + docs #389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…n * import Run ruff format on schemaview and schemaview tests
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #389 +/- ##
=======================================
Coverage 63.79% 63.79%
=======================================
Files 63 63
Lines 8946 8938 -8
Branches 2587 2584 -3
=======================================
- Hits 5707 5702 -5
+ Misses 2633 2629 -4
- Partials 606 607 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
from collections.abc import Mapping, Iterator | ||
|
||
from linkml_runtime import SchemaView | ||
from linkml_runtime.utils.schemaview import SchemaView |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use full path for import (this was mostly to make it easier for me to find places where weird stuff was being imported from SchemaView)
@@ -1,37 +1,68 @@ | |||
"""SchemaView, a virtual schema layered on top of a schema plus its import closure.""" | |||
|
|||
from __future__ import annotations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allows nicer ways of expressing typing (i.e. X | Y
, etc.)
if ordered_by in (OrderedBy.LEXICAL, OrderedBy.LEXICAL.value): | ||
return self._order_lexically(elements) | ||
elif ordered_by in (OrderedBy.RANK, OrderedBy.RANK.value): | ||
if ordered_by in (OrderedBy.RANK, OrderedBy.RANK.value): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for else
or elif
after a return
candidate = clist[i] | ||
can_add = False | ||
if candidate.is_a is None: | ||
if candidate.is_a is None or candidate.is_a in [p.name for p in slist]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collapse / combine if
conditions
classes = copy(self._get_dict(CLASSES, imports)) | ||
classes = self.ordered(classes, ordered_by=ordered_by) | ||
return classes | ||
return self.ordered(classes, ordered_by=ordered_by) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return directly, no need to assign to a variable
|
||
slots = self.ordered(slots, ordered_by=ordered_by) | ||
return slots | ||
return self.ordered(slots, ordered_by=ordered_by) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return directly
:return: all enums in schema view | ||
""" | ||
return self._get_dict(ENUMS, imports) | ||
return self.all_enums(imports) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redirect to the non-deprecated function
all_subsets = self.all_subsets(imports=imports) | ||
# {**a,**b} syntax merges dictionary a and b into a single dictionary, removing duplicates. | ||
return {**all_classes, **all_slots, **all_enums, **all_types, **all_subsets} | ||
return self.all_elements(imports) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redirect to non-deprecated function
return _closure(lambda x: self.class_parents(x, imports=imports, mixins=mixins, is_a=is_a), | ||
class_name, | ||
reflexive=reflexive, depth_first=depth_first) | ||
return _closure( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reformatted
if not is_empty(v2): | ||
v = v2 | ||
logger.debug(f'{v} takes precedence over {v2} for {induced_slot.name}.{metaslot_name}') | ||
elif metaslot_name in COMBINE: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else
+ if
=> elif
:return: | ||
""" | ||
self.schema.subsets[subset.name] = type | ||
self.schema.subsets[subset.name] = subset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
:return: | ||
""" | ||
self.schema.types[type.name] = type | ||
self.schema.types[type_def.name] = type_def |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type
is a reserved word in python
schema_path = os.path.join(INPUT_DIR, "schemaview_is_inlined.yaml") | ||
sv = SchemaView(schema_path) | ||
cases = [ | ||
@pytest.mark.parametrize( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use parametrize instead of iterating through a list
|
||
@pytest.fixture | ||
def view(): | ||
def schema_view_with_imports() -> SchemaView: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clearer name
@pytest.fixture(scope="session") | ||
def schema_view_attributes() -> SchemaView: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a fixture for this since it's used in several tests
""" | ||
view = SchemaView(os.path.join(INPUT_DIR, "attribute_edge_cases.yaml")) | ||
expected = [ | ||
@pytest.mark.parametrize( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parametric instead of iterating through a list
@ialarmedalien do I understand it correctly? The conversations that you've opened in this PR are mostly justifying some of the changes, right? So a reviewer that holds those changes as meaningful, can simply comment "makes sense" or so or "thumb-up" your comment and close those conversations, right? |
@ialarmedalien I'm trying to run "ruff" myself just to be sure that I don't look at changes directly applied by the tool and I'm failing. I'm getting an error message. [Edit]: I've seen that Doing so I've realized that we are not specifying I've created this PR to your branch to add it. It might be a good idea to have separate commits to add whatever other ruff linters you think would be meaningful for the project. |
@ialarmedalien I've realized that you are running I'm trying to review this PR, but I'm having difficulties to segregate those changes introduced by [Edit]: I've just found out that you are running These are the commands to reproduce my environment: $ git clone --quiet https://github.com/linkml/linkml-runtime
$ cd linkml-runtime
$ git remote add silvanoc https://github.com/Silvanoc/linkml-runtime
$ git fetch --quiet silvanoc
$ git cherry-pick silvanoc/add-ruff-as-dev-dependency~1
[main a2a0a4e] chore: add ruff to dev dependencies
Date: Wed May 7 12:41:47 2025 +0200
2 files changed, 31 insertions(+), 1 deletion(-)
$ git cherry-pick silvanoc/add-ruff-as-dev-dependency
[main b376d8e] chore(lint): add import sorting
Date: Wed May 7 13:15:32 2025 +0200
1 file changed, 2 insertions(+), 1 deletion(-)
$ poetry install --quiet --only=dev If I let $ poetry run ruff check --fix linkml_runtime/utils/schemaview.py --config pyproject.toml
Found 2 errors (2 fixed, 0 remaining).
$ git diff
diff --git i/linkml_runtime/utils/schemaview.py w/linkml_runtime/utils/schemaview.py
index 1be70a3..3c8145e 100644
--- i/linkml_runtime/utils/schemaview.py
+++ w/linkml_runtime/utils/schemaview.py
@@ -1,25 +1,25 @@
+import collections
+import logging
import os
import sys
import uuid
-import logging
-import collections
-from functools import lru_cache
-from copy import copy, deepcopy
+import warnings
from collections import defaultdict, deque
+from collections.abc import Mapping
+from copy import copy, deepcopy
+from enum import Enum
+from functools import lru_cache
from pathlib import Path, PurePath
from typing import Optional, TypeVar
-from collections.abc import Mapping
-import warnings
-from urllib.parse import urlparse
-from linkml_runtime.utils.namespaces import Namespaces
from deprecated.classic import deprecated
-from linkml_runtime.utils.context_utils import parse_import_map, map_import
-from linkml_runtime.utils.formatutils import camelcase, is_empty, sfx, underscore
-from linkml_runtime.utils.pattern import PatternResolver
-from linkml_runtime.linkml_model.meta import *
+
from linkml_runtime.exceptions import OrderingError
-from enum import Enum
+from linkml_runtime.linkml_model.meta import *
+from linkml_runtime.utils.context_utils import map_import, parse_import_map
+from linkml_runtime.utils.formatutils import camelcase, is_empty, sfx, underscore
+from linkml_runtime.utils.namespaces import Namespaces
+from linkml_runtime.utils.pattern import PatternResolver
logger = logging.getLogger(__name__) The same can be done for the tests file and also with |
The comments are to explain what I did, yes, to make life easier for the reviewer. There's no need to respond unless you particularly want to! 🙂 |
IMO the whole linting, ruff, tox,... set-up in both If looking at Perhaps doing it "right" here first and using it as a pattern for the |
@Silvanoc re: ruff linting: I think it would be better if you made a direct PR to the linkml-runtime repo to update ruff and add it to the dev dependencies so that it gets the attention of the linkml-runtime maintainers. The main reason I didn't add my config into this PR is that I have pretty much all the linters enabled locally, which I would not necessarily suggest for a repo like This is my local config:
I just ran I would love to format and lint auto-fix all the files in this repo, but there is an existing PR (#347) that does this and I didn't want to redo work that has already been done. |
I agree completely! I did some work on the |
The problem without the ruff configuration (thanks for providing it) is that I wanted to look at this PR and I was not capable of taking the chaff (whatever changes Anyway, you can simply ignore/close my PR on your branch.
True! I saw it in the past and forgot it! I'll have a look at it. |
@Silvanoc Apologies for unintentionally giving you a load of detective work to do in figuring out my ruff config! I would have included it as a comment on the PR if I had known. If you look at the last commit of the PR, it contains the edits that I made manually or via VSCode's ruff plugin code fixing feature. Hopefully that will be a little easier to review... |
No worries.
I'm proposing here some changes to streamline linting and formatting. That way we have a clear definition of what we expect, we also enforce it and we enable developers to have it locally. |
4c7db80
to
c7e1c3a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for the big cleanup! (and especially catching that add_subset bug!)
Hmm, I'm not sure this PR was expected to get merged before #347. @ialarmedalien can you please confirm? |
upstream_repo: dalito/linkml
upstream_branch: issue2578-fix-uri-in-snapshot
Note: upstream tests will fail until linkml/linkml#2648 is merged, which relies on a new release of linkml-runtime being made.
I have a minor change to make to the SchemaView package so wanted to spruce up SV and its tests first.
I ran
ruff format
andruff check --fix
to fix "safe" linting errors. See my local ruff config.The changes look rather daunting, but they are all fairly simple. I recommend viewing the commits separately if you have any worries.
commit 1: run ruff format on the files. Alter schemaview.py to pull in specific classes from the
linkml_runtime.linkml_model.meta
instead of*
-importingcommit 2: run the ruff linter auto fixes
commit 3: add in missing typing and basic doc strings. A couple of minor fixes, which I will add comments to.
There is an existing PR that runs formatting and linting auto fixes on the whole codebase, so I have not put in any ruff infrastructure here.