Skip to content

Commit

Permalink
Merge pull request #280 from iBridges-for-iRODS/develop
Browse files Browse the repository at this point in the history
v1.2.0
  • Loading branch information
chStaiger authored Nov 4, 2024
2 parents cce9048 + ad70ef4 commit 826306a
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 32 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
include:
- os: windows-latest
python-version: "3.12"
Expand All @@ -29,16 +29,13 @@ jobs:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Clone the repository
uses: actions/checkout@v4
cache: 'pip'

- name: Install dependencies
run: |
pip install --upgrade pip
pip install ".[test]"
- name: Test with pytest
Expand All @@ -59,11 +56,14 @@ jobs:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: "pip"


- name: Install dependencies
run: |
pip install --upgrade pip
pip install ".[test]"
- name: Lint with Ruff
Expand Down
2 changes: 1 addition & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Dockerised integration tests of iBridges with iRODS
1. Clone iBridges

```sh
git clone --branch develop https://github.com/UtrechtUniversity/iBridges.git
git clone --branch develop https://github.com/iBridges-for-iRODS/iBridges.git
```

Execute the following commands in the root ibridges directory:
Expand Down
28 changes: 28 additions & 0 deletions docker/irods_client/tests/test_search.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from pytest import mark

from ibridges import IrodsPath, search_data, upload
Expand Down Expand Up @@ -58,3 +59,30 @@ def test_find_meta(session, item_name, request, metadata, is_found):

res = _found(search_data(session, metadata=metadata), ipath)
assert res == is_found

@mark.parametrize("metadata,is_found", [
(MetaSearch("author", "Ben"), True),
(MetaSearch(units="KG"), True)
])
@mark.parametrize("item_name", ["collection", "dataobject"])
def test_find_case_ins_meta(session, item_name, request, metadata, is_found):
item = request.getfixturevalue(item_name)
ipath = IrodsPath(session, item.path)
ipath.meta.clear()
ipath.meta.add("Author", "Ben")
ipath.meta.add("Mass", "10", "kg")

res = _found(search_data(session, metadata=metadata), ipath)
assert res == is_found
res = _found(search_data(session, metadata=metadata, case_sensitive=True), ipath)
with pytest.raises(AssertionError):
assert res == is_found


@mark.parametrize("item_name", ["collection", "dataobject"])
def test_find_case_ins_path(session, item_name, request):
item = request.getfixturevalue(item_name)
ipath = IrodsPath(session, item.path)
assert _found(search_data(session, path_pattern=item.name.upper()), item.path)
with pytest.raises(AssertionError):
assert _found(search_data(session, path_pattern=item.name.upper(), case_sensitive=True), item.path)
2 changes: 1 addition & 1 deletion docs/source/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ create the environment file for you. Below are the currently (known) plugins, se
* - Organization
- Link
* - Utrecht University
- https://github.com/UtrechtUniversity/ibridges-servers-uu
- https://github.com/iBridges-for-iRODS/ibridges-servers-uu

After installation, you will be able to create an `irods_environment.json` by simply answering questions such as which email-address
you have. First find the server name with:
Expand Down
23 changes: 18 additions & 5 deletions docs/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ An advantage compared to the iCommands is that iBridges also works on Mac OS and

**I found a bug or have a feature request, where do I go?**
------------------------------------------------------------------------
Our development is done on `GitHub <https://github.com/UtrechtUniversity/iBridges>`__ Look under the `Issues` section
Our development is done on `GitHub <https://github.com/iBridges-for-iRODS/iBridges>`__ Look under the `Issues` section
whether the bug or feature request has already been reported. If not, we heartily welcome creating a new issue. We
try to get back to you as soon as possible, at least within a few days.


**I want to contribute to iBridges, where do I go?**
----------------------------------------------------

Our development is done on `GitHub <https://github.com/UtrechtUniversity/iBridges>`__ We are welcoming contributions
Our development is done on `GitHub <https://github.com/iBridges-for-iRODS/iBridges>`__ We are welcoming contributions
by pull requests. You can also ask for new features/ideas in our issue tracker.


Expand Down Expand Up @@ -85,10 +85,23 @@ Warnings can also be switched off through python's `warnings` package:

.. code-block:: python
import warnings
warnings.filterwarnings("ignore")
import warnings
warnings.filterwarnings("ignore")
**My metadata with keys starting with `org_` do not show up in the iBridges metadata.**
---------------------------------------------------------------------------------------

iBridges **does not show** metadata that contain a key starting with the prefix `org_`. This is due to data security reasons on `Yoda systems <https://github.com/UtrechtUniversity/yoda>`__.
By default, iBridges **does not show** metadata that contain a key starting with the prefix `org_`. This is due to data security reasons on `Yoda systems <https://github.com/UtrechtUniversity/yoda>`__.

You can omit this by the following code:

.. code-block:: python
from ibridges.meta import MetaData
# collections
meta = MetaData(IrodsPath(session, "~", "my_coll").collection, blacklist=None)
# data objects
meta = MetaData(IrodsPath(session, "~", "my_obj").dataobject, blacklist=None)
print(meta)
6 changes: 3 additions & 3 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
Welcome to the iBridges documentation!
======================================

`iBridges <https://github.com/UtrechtUniversity/iBridges>`__ is a Python library to connect to iRODS servers in a simplified and safe manner.
`iBridges <https://github.com/iBridges-for-iRODS/iBridges>`__ is a Python library to connect to iRODS servers in a simplified and safe manner.
iBridges consists of three major components: a Python API for Python programmers, a Command Line Interface and a Graphical user interface.
The documentation presented here is for the Python API and Command Line Interface. The documentation for the Graphical User Interface is
located on a separate `page <https://chstaiger.github.io/iBridges-Gui/>`__.

.. note::
The project is in active development, current features are stable and the documentation is complete. However, we are still actively developing new features and improving the existing ones. We appreciate help, suggestions, issues and bug reports in our issue tracker on `GitHub <https://github.com/UtrechtUniversity/iBridges>`__.
The project is in active development, current features are stable and the documentation is complete. However, we are still actively developing new features and improving the existing ones. We appreciate help, suggestions, issues and bug reports in our issue tracker on `GitHub <https://github.com/iBridges-for-iRODS/iBridges>`__.


iBridges is a wrapper around the `python-irodsclient <https://github.com/irods/python-irodsclient>`__. While the
python-irodsclient is very powerful and feature rich, we aim to provide an easier API for users (mainly researchers)
that do not have any technical knowledge of iRods.

We provide extensive tutorials on how to work with data in iRODS. Please consult our `tutorials <https://github.com/UtrechtUniversity/iBridges/tree/main/tutorials>`__ page.
We provide extensive tutorials on how to work with data in iRODS. Please consult our `tutorials <https://github.com/iBridges-for-iRODS/iBridges/tree/main/tutorials>`__ page.

.. toctree::
:hidden:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/ipath.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ We strongly recommend using :class:`IrodsPath` over using strings for the follow
- :class:`IrodsPath` is **more convenient** since there are many methods and attributes available such as: the name, size and parent of the iRODS path.
- The string representation of the :class:`IrodsPath` is available through :code:`str(ipath)`.

A complete tutorial on iRODS paths can be followed `here <https://github.com/UtrechtUniversity/iBridges/tree/main/tutorials>`__. For an overview of
A complete tutorial on iRODS paths can be followed `here <https://github.com/iBridges-for-iRODS/iBridges/tree/main/tutorials>`__. For an overview of
all functionality connected to the :class:`IrodsPath`, see the :doc:`API documentation <api/generated/ibridges.path.IrodsPath>`.

IrodsPath
Expand Down
14 changes: 9 additions & 5 deletions ibridges/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys
from argparse import RawTextHelpFormatter
from pathlib import Path
from typing import Optional, Union
from typing import Literal, Optional, Union

from ibridges.data_operations import download, sync, upload
from ibridges.interactive import DEFAULT_IENV_PATH, DEFAULT_IRODSA_PATH, interactive_auth
Expand Down Expand Up @@ -278,7 +278,7 @@ def ibridges_setup():
if len(env_providers) == 0:
print(
"No server information was found. To use this function, please install a plugin"
" such as:\n\nhttps://github.com/UtrechtUniversity/ibridges-servers-uu"
" such as:\n\nhttps://github.com/iBridges-for-iRODS/ibridges-servers-uu"
"\n\nAlternatively create an irods_environment.json by yourself or with the help "
"of your iRODS administrator."
)
Expand Down Expand Up @@ -374,9 +374,11 @@ def _parse_remote(remote_path: Union[None, str], session: Session) -> IrodsPath:
return IrodsPath(session, remote_path[7:])
return IrodsPath(session, remote_path[6:])


def _get_metadata_path(args, ipath: IrodsPath, lpath: Union[str, Path],
mode: str) -> Union[None, str, Path]:
metadata = False if not hasattr(args, "metadata") else args.metadata
metadata: Union[Literal[False], Path, None
] = False if not hasattr(args, "metadata") else args.metadata
if ipath.dataobject_exists() and metadata is None:
raise ValueError("Supply metadata path for downloading metadata of data objects.")
if mode == "download":
Expand All @@ -385,8 +387,10 @@ def _get_metadata_path(args, ipath: IrodsPath, lpath: Union[str, Path],
default_meta_path = Path(lpath, ".ibridges_metadata.json")
else:
raise ValueError("Internal error, contact the iBridges team.")
metadata = metadata if metadata is not None else default_meta_path
metadata = None if metadata is False else metadata
if metadata is None:
return default_meta_path
if metadata is False:
return None
return metadata


Expand Down
6 changes: 5 additions & 1 deletion ibridges/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ def __iter__(self) -> Iterator:
"""Iterate over all metadata key/value/units triplets."""
if self.blacklist is None:
yield from self.item.metadata.items()
return
for meta in self.item.metadata.items():
if re.match(self.blacklist, meta.name) is None:
if self.blacklist and re.match(self.blacklist, meta.name) is None:
yield meta
else:
warnings.warn(f"Ignoring metadata entry with value {meta.name}, because it matches "
Expand Down Expand Up @@ -148,6 +149,9 @@ def add(self, key: str, value: str, units: Optional[str] = None):
try:
if (key, value, units) in self:
raise ValueError("ADD META: Metadata already present")
if self.blacklist:
if re.match(self.blacklist, key):
raise ValueError(f"ADD META: Key must not start with {self.blacklist}.")
self.item.metadata.add(key, value, units)
except irods.exception.CAT_NO_ACCESS_PERMISSION as error:
raise PermissionError("UPDATE META: no permissions") from error
Expand Down
13 changes: 10 additions & 3 deletions ibridges/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def search_data( # pylint: disable=too-many-branches
checksum: Optional[str] = None,
metadata: Union[None, MetaSearch, list[MetaSearch], list[tuple]] = None,
item_type: Optional[str] = None,
case_sensitive: bool = False
) -> list[IrodsPath]:
"""Search for collections, data objects and metadata.
Expand Down Expand Up @@ -72,6 +73,8 @@ def search_data( # pylint: disable=too-many-branches
item_type:
Type of the item to search for, by default None indicating both data objects and collections
are returned. Set to "data_object" for data objects and "collection" for collections.
case_sensitive:
Case sensitive search for Paths and metadata. Default: False
Raises
------
Expand Down Expand Up @@ -148,17 +151,21 @@ def search_data( # pylint: disable=too-many-branches
queries = []
if item_type != "data_object" and checksum is None:
# create the query for collections; we only want to return the collection name
coll_query = session.irods_session.query(icat.COLL_NAME)
coll_query = session.irods_session.query(icat.COLL_NAME, case_sensitive=case_sensitive)
coll_query = coll_query.filter(icat.LIKE(icat.COLL_NAME, _postfix_wildcard(path)))
queries.append((coll_query, "collection"))
if item_type != "collection":
# create the query for data objects; we need the collection name, the data name and checksum
data_query = session.irods_session.query(icat.COLL_NAME, icat.DATA_NAME, icat.DATA_CHECKSUM)
data_query = session.irods_session.query(icat.COLL_NAME,
icat.DATA_NAME,
icat.DATA_CHECKSUM,
case_sensitive=case_sensitive)
data_query = data_query.filter(icat.LIKE(icat.COLL_NAME, _postfix_wildcard(path)))
queries.append((data_query, "data_object"))

data_name_query = session.irods_session.query(icat.COLL_NAME, icat.DATA_NAME,
icat.DATA_CHECKSUM)
icat.DATA_CHECKSUM,
case_sensitive=case_sensitive)
data_name_query.filter(icat.LIKE(icat.COLL_NAME, f"{path}"))
queries.append((data_name_query, "data_object"))

Expand Down
6 changes: 5 additions & 1 deletion ibridges/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,13 @@ def write_pam_password(self):
connection = self.irods_session.pool.get_connection()
pam_passwords = self.irods_session.pam_pw_negotiated
if len(pam_passwords):
actual_password = pam_passwords[0]
else:
actual_password = self._password
if actual_password:
irods_auth_file = self.irods_session.get_irods_password_file()
with open(irods_auth_file, "w", encoding="utf-8") as authfd:
authfd.write(irods.password_obfuscation.encode(pam_passwords[0]))
authfd.write(irods.password_obfuscation.encode(actual_password))
else:
warnings.warn("WARNING -- unable to cache obfuscated password locally")
connection.release()
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ dependencies = [
dynamic = ["version"]

[project.urls]
GitHub = "https://github.com/UtrechtUniversity/iBridges"
documentation = "https://github.com/UtrechtUniversity/iBridges"
GitHub = "https://github.com/iBridges-for-iRODS/iBridges"
documentation = "https://github.com/iBridges-for-iRODS/iBridges"

[project.optional-dependencies]
test = [
Expand All @@ -47,7 +47,7 @@ test = [
"types-tqdm",
]
docs = [
"sphinx<8",
"sphinx<9",
"sphinx-rtd-theme",
"sphinxcontrib-napoleon",
"sphinx-autodoc-typehints",
Expand Down

0 comments on commit 826306a

Please sign in to comment.