Skip to content

Commit

Permalink
Merge pull request #114 from pepkit/dev
Browse files Browse the repository at this point in the history
Release v0.7.0
  • Loading branch information
khoroshevskyi authored Jan 19, 2024
2 parents de250ed + 85c8def commit 19299a6
Show file tree
Hide file tree
Showing 21 changed files with 2,323 additions and 175 deletions.
14 changes: 5 additions & 9 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

name: Upload Python Package

on:
Expand All @@ -9,9 +6,10 @@ on:

jobs:
deploy:

name: upload release to PyPI
runs-on: ubuntu-latest

permissions:
id-token: write
steps:
- uses: actions/checkout@v2
- name: Set up Python
Expand All @@ -23,9 +21,7 @@ jobs:
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ agent.project.create(prj_obj, namespace, name, tag)
# examples of update_dict:
update_dict1 = {"is_private" = True}
update_dict2 = {"is_private" = True, name = "new_name"}
update_dict3 = {"project" = prj_obj, "is_private"=True}
update_dict3 = {"project" = prj_obj, "is_private" = True}
update_dict4 = {"project" = prj_obj}
update_dict4 = {"tag" = "new_tag"}

# after creation of the dict, update record by providing update_dict and namespace, name and tag:
agent.project.update(update_dict, namespace, name, tag)
agent.project.update(update_dict, namespace, name, tag, )

# retrieve a project
agent.project.get(namespace, name, tag)
Expand Down
9 changes: 9 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.

## [0.7.0] -- 2023-01-17
- Added `pop` to project table and annotation model [#107](https://github.com/pepkit/pepdbagent/issues/107)
- Added `forked_from` feature [#73](https://github.com/pepkit/pepdbagent/issues/73)
- Switched to pydantic2 [#105](https://github.com/pepkit/pepdbagent/issues/105)
- Updated requirements (psycopg2 -> psycopg3) [#102](https://github.com/pepkit/pepdbagent/issues/102)
- Added sample module that contains functionality for updating, adding, and deleting samples in the project separately [#111](https://github.com/pepkit/pepdbagent/issues/111)
- Added user and favorite tables with functionality [#104](https://github.com/pepkit/pepdbagent/issues/104)
- Updated the sample update method when updating the whole project. Following this change, samples are updated without changing the ID in the database

## [0.6.0] -- 2023-08-24
- Added date filter to project annotation

Expand Down
7 changes: 5 additions & 2 deletions pepdbagent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
import coloredlogs
import logmuse

from ._version import __version__
from .pepdbagent import *
from pepdbagent._version import __version__
from pepdbagent.pepdbagent import PEPDatabaseAgent

__all__ = ["__version__", "PEPDatabaseAgent"]


_LOGGER = logmuse.init_logger("pepdbagent")
coloredlogs.install(
Expand Down
2 changes: 1 addition & 1 deletion pepdbagent/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.6.0"
__version__ = "0.7.0"
2 changes: 1 addition & 1 deletion pepdbagent/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
DEFAULT_LIMIT = 100

# db_dialects
POSTGRES_DIALECT = "postgresql"
POSTGRES_DIALECT = "postgresql+psycopg"

DEFAULT_LIMIT_INFO = 5

Expand Down
94 changes: 91 additions & 3 deletions pepdbagent/db_utils.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import datetime
import logging
from typing import Any, Optional, List
from typing import Optional, List

from sqlalchemy import (
BigInteger,
FetchedValue,
PrimaryKeyConstraint,
Result,
Select,
String,
event,
select,
TIMESTAMP,
ForeignKey,
ForeignKeyConstraint,
UniqueConstraint,
)
from sqlalchemy.dialects.postgresql import JSON
Expand Down Expand Up @@ -87,17 +85,41 @@ class Projects(Base):
config: Mapped[dict] = mapped_column(JSON, server_default=FetchedValue())
private: Mapped[bool]
number_of_samples: Mapped[int]
number_of_stars: Mapped[int] = mapped_column(default=0)
submission_date: Mapped[datetime.datetime]
last_update_date: Mapped[Optional[datetime.datetime]] = mapped_column(
onupdate=deliver_update_date, default=deliver_update_date
)
pep_schema: Mapped[Optional[str]]
pop: Mapped[Optional[bool]] = mapped_column(default=False)
samples_mapping: Mapped[List["Samples"]] = relationship(
back_populates="sample_mapping", cascade="all, delete-orphan"
)
subsamples_mapping: Mapped[List["Subsamples"]] = relationship(
back_populates="subsample_mapping", cascade="all, delete-orphan"
)
stars_mapping: Mapped[List["Stars"]] = relationship(
back_populates="project_mapping", cascade="all, delete-orphan"
)
views_mapping: Mapped[List["Views"]] = relationship(
back_populates="project_mapping", cascade="all, delete-orphan"
)

# Self-referential relationship. The parent project is the one that was forked to create this one.
forked_from_id: Mapped[Optional[int]] = mapped_column(
ForeignKey("projects.id", ondelete="SET NULL"), nullable=True
)
forked_from_mapping = relationship(
"Projects",
back_populates="forked_to_mapping",
remote_side=[id],
single_parent=True,
cascade="all",
)

forked_to_mapping = relationship(
"Projects", back_populates="forked_from_mapping", cascade="all"
)

__table_args__ = (UniqueConstraint("namespace", "name", "tag"),)

Expand All @@ -113,8 +135,13 @@ class Samples(Base):
sample: Mapped[dict] = mapped_column(JSON, server_default=FetchedValue())
row_number: Mapped[int]
project_id = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"))
sample_name: Mapped[Optional[str]] = mapped_column()
sample_mapping: Mapped["Projects"] = relationship(back_populates="samples_mapping")

views: Mapped[Optional[List["ViewSampleAssociation"]]] = relationship(
back_populates="sample", cascade="all, delete-orphan"
)


class Subsamples(Base):
"""
Expand All @@ -131,6 +158,67 @@ class Subsamples(Base):
subsample_mapping: Mapped["Projects"] = relationship(back_populates="subsamples_mapping")


class User(Base):
"""
User table representation in the database
"""

__tablename__ = "users"

id: Mapped[int] = mapped_column(primary_key=True)
namespace: Mapped[str]
stars_mapping: Mapped[List["Stars"]] = relationship(
back_populates="user_mapping", cascade="all, delete-orphan"
)


class Stars(Base):
"""
FavoriteProjects table representation in the database
"""

__tablename__ = "stars"

user_id = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), primary_key=True)
project_id = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"), primary_key=True)
user_mapping: Mapped[List["User"]] = relationship(back_populates="stars_mapping")
project_mapping: Mapped["Projects"] = relationship(back_populates="stars_mapping")


class Views(Base):
"""
Views table representation in the database
"""

__tablename__ = "views"

id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column()
description: Mapped[Optional[str]]

project_id = mapped_column(ForeignKey("projects.id", ondelete="CASCADE"))
project_mapping = relationship("Projects", back_populates="views_mapping")

samples: Mapped[List["ViewSampleAssociation"]] = relationship(
back_populates="view", cascade="all, delete-orphan"
)

_table_args__ = (UniqueConstraint("namespace", "project_id"),)


class ViewSampleAssociation(Base):
"""
Association table between views and samples
"""

__tablename__ = "views_samples"

sample_id = mapped_column(ForeignKey("samples.id", ondelete="CASCADE"), primary_key=True)
view_id = mapped_column(ForeignKey("views.id", ondelete="CASCADE"), primary_key=True)
sample: Mapped["Samples"] = relationship(back_populates="views")
view: Mapped["Views"] = relationship(back_populates="samples")


class BaseEngine:
"""
A class with base methods, that are used in several classes. e.g. fetch_one or fetch_all
Expand Down
37 changes: 37 additions & 0 deletions pepdbagent/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,40 @@ def __init__(self, msg=""):
class FilterError(PEPDatabaseAgentError):
def __init__(self, msg=""):
super().__init__(f"""pepdbagent filter error. {msg}""")


class ProjectNotInFavorites(PEPDatabaseAgentError):
"""
Project doesn't exist in favorites
"""

def __init__(self, msg=""):
super().__init__(f"""Project is not in favorites list. {msg}""")


class ProjectAlreadyInFavorites(PEPDatabaseAgentError):
"""
Project doesn't exist in favorites
"""

def __init__(self, msg=""):
super().__init__(f"""Project is already in favorites list. {msg}""")


class SampleNotFoundError(PEPDatabaseAgentError):
def __init__(self, msg=""):
super().__init__(f"""Sample does not exist. {msg}""")


class ViewNotFoundError(PEPDatabaseAgentError):
def __init__(self, msg=""):
super().__init__(f"""View does not exist. {msg}""")


class SampleAlreadyInView(PEPDatabaseAgentError):
"""
Sample is already in the view exception
"""

def __init__(self, msg=""):
super().__init__(f"""Sample is already in the view. {msg}""")
Loading

0 comments on commit 19299a6

Please sign in to comment.