Skip to content
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

Migrate to higlass-schema v0.2.0 (pydantic v2) #155

Merged
merged 3 commits into from
Nov 12, 2024
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 pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ dynamic = ["version"]
readme = "README.md"
dependencies = [
"servir>=0.0.5",
"higlass-schema>=0.0.6,<0.2.0",
"higlass-schema>=0.2.0",
"anywidget>=0.9.0",
"jinja2",
"jupyter-server-proxy>=3.0",
Expand Down
2 changes: 1 addition & 1 deletion src/higlass/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def ensure_list(x: T | list[T] | None) -> list[T]:

def copy_unique(model: ModelT) -> ModelT:
"""Creates a deep copy of a pydantic BaseModel with new UID."""
copy = model.__class__(**model.dict())
copy = model.__class__(**model.model_dump())
if hasattr(copy, "uid"):
setattr(copy, "uid", uid())
return copy
42 changes: 21 additions & 21 deletions src/higlass/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@
)

import higlass_schema as hgs
from pydantic import BaseModel
from pydantic import RootModel

import higlass._display as display
import higlass._utils as utils

__all__ = [
"CombinedTrack",
"EnumTrack",
"HeatmapTrack",
"IndependentViewportProjectionTrack",
"CombinedTrack",
"PluginTrack",
"TrackT",
"View",
"ViewT",
"Viewconf",
"combine",
"concat",
"divide",
"hconcat",
"vconcat",
"lock",
"track",
"vconcat",
"view",
"combine",
"divide",
"lock",
]

if TYPE_CHECKING:
Expand Down Expand Up @@ -383,13 +383,13 @@ def _repr_mimebundle_(self, include=None, exclude=None):
""" "Displays the view config in an IPython environment."""
renderer = display.renderers.get()
plugin_urls = [] if self.views is None else gather_plugin_urls(self.views)
return renderer(self.dict(), plugin_urls=plugin_urls)
return renderer(self.model_dump(), plugin_urls=plugin_urls)

def widget(self, **kwargs):
"""Create a Jupyter Widget display for this view config."""
from higlass._widget import HiGlassWidget

return HiGlassWidget(self.dict(), **kwargs)
return HiGlassWidget(self.model_dump(), **kwargs)

@classmethod
def from_url(cls, url: str, **kwargs):
Expand All @@ -416,7 +416,7 @@ def from_url(cls, url: str, **kwargs):
with urllib.urlopen(request) as response:
raw = response.read()

return cls.parse_raw(raw)
return cls.model_validate_json(raw)

def locks(
self,
Expand Down Expand Up @@ -603,7 +603,7 @@ def mapper(view):
raise ValueError("concat method must be 'vertical' or 'horizontal'.")

# gather views and adjust layout
views = [v.copy(deep=True) for v in b.views]
views = [v.model_copy(deep=True) for v in b.views]
offset = 0 if a.views is None else max(map(mapper, a.views))
for view in views:
curr = getattr(view.layout, field)
Expand All @@ -616,7 +616,7 @@ def mapper(view):
locks = getattr(b, lockattr)
if locks:
if getattr(a, lockattr) is None:
setattr(a, lockattr, locks.copy(deep=True))
setattr(a, lockattr, locks.model_copy(deep=True))
else:
getattr(a, lockattr).locksByViewUid.update(locks.locksByViewUid)
getattr(a, lockattr).locksDict.update(locks.locksDict)
Expand All @@ -634,18 +634,18 @@ def mapper(view):
# TODO: register plugins globally to work here?


class _TrackCreator(BaseModel):
class _TrackCreator(RootModel):
"""Create track instances from their track type.

Used internally by `hg.track` to leverage pydantic's ability to get
the appropriate base model by the track type.

Example:
-------
>>> assert isinstance(_TrackCreator(type="heatmap").__root__, HeatmapTrack)
>>> assert isinstance(_TrackCreator(type="heatmap").root, HeatmapTrack)
"""

__root__: Track
root: Track


@overload
Expand Down Expand Up @@ -688,7 +688,7 @@ def track(
if uid is None:
uid = utils.uid()
data = dict(type=type_, uid=uid, **kwargs)
return _TrackCreator.parse_obj(data).__root__
return _TrackCreator.model_validate(data).root


def view(
Expand Down Expand Up @@ -745,16 +745,16 @@ def view(
if layout is None:
layout = hgs.Layout(x=x, y=y, w=width, h=height)
else:
layout = hgs.Layout(**layout.dict())
layout = hgs.Layout(**layout.model_dump())

if tracks is None:
data = defaultdict(list)
else:
data = defaultdict(list, tracks.dict())
data = defaultdict(list, tracks.model_dump())

for track in _tracks:
if isinstance(track, hgs.Tracks):
track = track.dict()
track = track.model_dump()
for position, track_list in track.items():
data[position].extend(track_list)
else:
Expand Down Expand Up @@ -806,16 +806,16 @@ def combine(t1: Track, t2: Track, uid: str | None = None, **kwargs) -> CombinedT
uid = utils.uid()

if isinstance(t1, CombinedTrack):
copy = CombinedTrack(**t1.dict())
copy.contents.append(t2.__class__(**t2.dict()))
copy = CombinedTrack(**t1.model_dump())
copy.contents.append(t2.__class__(**t2.model_dump()))
for key, val in kwargs.items():
setattr(copy, key, val)
return copy

return CombinedTrack(
type="combined",
uid=uid,
contents=[track.__class__(**track.dict()) for track in (t1, t2)],
contents=[track.__class__(**track.model_dump()) for track in (t1, t2)],
**kwargs,
)

Expand Down
50 changes: 42 additions & 8 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.