Skip to content

[#505] create an atomic ACLs endpoint#808

Open
d-w-moore wants to merge 13 commits intoirods:mainfrom
d-w-moore:505.m
Open

[#505] create an atomic ACLs endpoint#808
d-w-moore wants to merge 13 commits intoirods:mainfrom
d-w-moore:505.m

Conversation

@d-w-moore
Copy link
Copy Markdown
Collaborator

No test yet, will undraft when I have one.
Exercised now with this script:

# run as rods after 
# $ irm -fr b; itouch b
# $ iadmin mkzone twilight remote
# $ iadmin mkuser dan rodsuser
# $ iadmin mkuser charlie#twilight rodsuser

import irods
from irods.access import iRODSAccess
from irods.exception import iRODSException

s = irods.helpers.make_session()

try:
  pass
  s.acls._call_atomic_acl_api(
   "/tempZone/home/rods/b",
   iRODSAccess("write","","dan"),
   iRODSAccess("write","","public"),
   iRODSAccess("read","","charlie","twilight"),
 )
except iRODSException as exc:
  print(f'{exc!r}')
  e = exc
  print (e.server_msg.get_json_encoded_struct())
#except Exception as exc:
#  print(repr(exc))
else:
  print ('---> success')
  pass

@d-w-moore d-w-moore marked this pull request as draft March 20, 2026 23:28
@d-w-moore d-w-moore self-assigned this Mar 21, 2026
@d-w-moore d-w-moore marked this pull request as ready for review March 21, 2026 04:45
@d-w-moore
Copy link
Copy Markdown
Collaborator Author

How would the team feel about my deprecating _iRODSAccess_pre_4_3_0, since we're now officially not supporting iRODS < 4.3.0 in PRC?

@korydraughn
Copy link
Copy Markdown
Contributor

The leading underscore indicates that symbol is private to the implementation. If that's the case, no objections here.

@korydraughn
Copy link
Copy Markdown
Contributor

Then again, if it's an implementation detail, then we don't have to deprecate it. We can just remove it.

@d-w-moore
Copy link
Copy Markdown
Collaborator Author

d-w-moore commented Mar 23, 2026

Ready for review. ACLOperation now created as part of an improved interface for atomic ACLs call.

@korydraughn
Copy link
Copy Markdown
Contributor

Spotted this in the type checking workflow.

irods/manager/access_manager.py:54: error: Incompatible types in assignment (expression has type "list[Any]", target has type "str")  [assignment]

Copy link
Copy Markdown
Contributor

@korydraughn korydraughn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good so far.

@d-w-moore
Copy link
Copy Markdown
Collaborator Author

d-w-moore commented Mar 26, 2026

Sorry for the forced push... just put some ruff changes through and added a structure that maps all permission keys to their respective codes - including all synonyms. It will help someone that say wants to do this:

sorted( [*ses.acls.get(object) , *my_ACLOperation_list ], 
               key= lambda acl:irods.access.all_permissions[acl.access_name] )

which would sort the whole list of retrieved permissions and new applicable ACLOperations together, ordering by increasing numeric permission code.

Yes, I know - very niche. But it affords the customer some pretty good flexibility.

@d-w-moore
Copy link
Copy Markdown
Collaborator Author

linters and tests are queued up.

Code is ready for final review, I think.

Copy link
Copy Markdown
Contributor

@alanking alanking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we're rounding the corner. Still see a couple unresolved comments

… casual corruption.

RUF012 points out that instances of the class can casually modify an unmutable class variable, eg.:

class A:
  value = []
  def f(self,*y): self.value += [*y]
@d-w-moore
Copy link
Copy Markdown
Collaborator Author

I think it's ready for final eyes.... Squashing.

Copy link
Copy Markdown
Contributor

@korydraughn korydraughn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're in the final stretch.

from irods.path import iRODSPath


_ichmod_listed_permissions = (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason behind including ichmod in the variable name?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were copy/paste from output of man ichmod. Definitely open to suggestions on that one.

Comment on lines +137 to +139
# Useful if we wish to force an explicitly specified local zone to an implicit zone spec in the copy, for equality testing:
if '' != implied_zone == other.user_zone:
other.user_zone = ''
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain L138.

I'm trying to guess what it does. Here's what I got (without looking up python docs) ... L138 can be rewritten as:

if '' != implied_zone and implied_zone == other.user_zone:
    other.user_zone = ''

Is my interpretation correct? What does it accomplish?

If implied_zone is tempZone and other.user_zone is tempZone, other.user_zone is cleared. implied_zone remains nonempty.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the correct interpretation.

We're forcing other, ie the return value to have null length in the zone field if it matches a non empty "implied" value.

Any modification to the variable implied_zone would of course have no effect on any code external to the call frame. (That's just a python thing.)



(
_ichmod_synonym_mapping := {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Highlighting this for follow-up depending on the results of the other ichmod conversation.

Comment on lines +207 to +229
class _deprecated:
class _iRODSAccess_pre_4_3_0(_iRODSAccess_base):
codes = collections.OrderedDict(
(key.replace("_", " "), value)
for key, value in iRODSAccess.codes.items()
if key in ("own", "write", "modify_object", "read", "read_object", "null")
)
strings = collections.OrderedDict((number, string) for string, number in codes.items())
def __init__(self, *args, **kwargs):
warnings.warn(
"_iRODSAccess_pre_4_3_0 is deprecated and will be removed in a future version. Use iRODSAccess instead.",
DeprecationWarning,
stacklevel=2
)
super().__init__(*args,**kwargs)

_deprecated_names = {'_iRODSAccess_pre_4_3_0':_deprecated._iRODSAccess_pre_4_3_0}

def __getattr__(name):
if name in _deprecated_names:
warnings.warn(f"{name} is deprecated", DeprecationWarning, stacklevel=2)
return _deprecated_names[name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this do what's intended?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested it manually only. I wonder if a test is in order to make sure; wouldn't be that difficult.

`<session>.permissions` was therefore removed in v2.0.0
in favor of `<session>.acls`.

Atomic ACLs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider including "Permissions" in the title. That will make the section easier to find for some readers.

@d-w-moore d-w-moore force-pushed the 505.m branch 2 times, most recently from 4c99900 to 968d9cd Compare March 28, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants