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

Implement motion import #1923

Merged
merged 84 commits into from
Feb 21, 2024

Conversation

luisa-beerboom
Copy link
Member

@luisa-beerboom luisa-beerboom commented Oct 12, 2023

@luisa-beerboom
Copy link
Member Author

Up until now the json_upload seems to work in all cases involving only the required fields (including reason, which is sometimes required), as well as the number field.

Submitter generation in case of omission seems to be working as well.

The categories have been tested in so far that the json_upload seems to work for most common cases (there are still some untested edge cases though)

There are some remaining TODOs and all other fields have not yet been tested at all.
The import too is neither finished, nor tested.

@r-peschke If you wish to have a look at and give feedback to the finished parts sometime next week, please feel free to do so, I'd appreciate that

openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
openslides_backend/action/mixins/import_mixins.py Outdated Show resolved Hide resolved
tests/system/action/motion/test_json_upload.py Outdated Show resolved Hide resolved
if (category_name := entry.get("category_name")) and isinstance(
category_name, str
):
category_prefix = entry.get("category_prefix") or None
Copy link
Member

Choose a reason for hiding this comment

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

You don't need the or None. The get-method returns the value, if the dictionary has the attribute or it returns None.

Copy link
Member Author

Choose a reason for hiding this comment

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

I need or None because I need this to ignore empty strings

Copy link
Member

Choose a reason for hiding this comment

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

Then please write a test for this edge case:-).

Copy link
Member Author

Choose a reason for hiding this comment

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

Already exists

Copy link
Member

Choose a reason for hiding this comment

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

Then there should be at minimum 1 failing test

Copy link
Member Author

Choose a reason for hiding this comment

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

What do you think should fail?

Copy link
Member

Choose a reason for hiding this comment

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

If the and None is necessary, there should be a reason why it is necessary. I would expect removing it, changes the behaviour. And this change should be manifested in a failing test

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed the or None and it still works, seems it was unnecessary

openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
mapped_fields: List[str] = [],
and_filters: List[Filter] = [],
) -> Dict[str, List[Dict[str, Any]]]:
lookup: Dict[str, List[Dict[str, Any]]] = {}
Copy link
Member

Choose a reason for hiding this comment

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

instead of {} you should use defaultdict(List), the advantage see above

Copy link
Member Author

Choose a reason for hiding this comment

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

There is nothing above

Copy link
Member

Choose a reason for hiding this comment

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

There is nothing above

Sorry, I meant below

Copy link
Member Author

Choose a reason for hiding this comment

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

At what line of what file is that supposed to be? I can't find it

Copy link
Member

Choose a reason for hiding this comment

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

finally you found

Copy link
Member Author

@luisa-beerboom luisa-beerboom Nov 28, 2023

Choose a reason for hiding this comment

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

???

Copy link
Member Author

Choose a reason for hiding this comment

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

I still have no idea what I am supposed to have "found"

openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
Copy link
Member

@r-peschke r-peschke left a comment

Choose a reason for hiding this comment

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

Some small things.

if (category_name := entry.get("category_name")) and isinstance(
category_name, str
):
category_prefix = entry.get("category_prefix") or None
Copy link
Member

Choose a reason for hiding this comment

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

Then there should be at minimum 1 failing test

mapped_fields: List[str] = [],
and_filters: List[Filter] = [],
) -> Dict[str, List[Dict[str, Any]]]:
lookup: Dict[str, List[Dict[str, Any]]] = {}
Copy link
Member

Choose a reason for hiding this comment

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

finally you found

openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
Copy link
Member

@r-peschke r-peschke left a comment

Choose a reason for hiding this comment

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

Reviewed parts of the user(submitter, supporter) validation and I think there are some helpful modifications.

openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
openslides_backend/action/actions/motion/json_upload.py Outdated Show resolved Hide resolved
has_submitter_error: bool = False
for fieldname in ["submitter", "supporter"]:
if users := entry.get(f"{fieldname}s_username"):
if not isinstance(users, list):
Copy link
Member

Choose a reason for hiding this comment

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

From schema validation and import_mixin it's guaranteed to be a list. Write 1 test to check this in a new class and throw an exception, if it is not.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed the if clause and it still works. What should the test check for?

Copy link
Member

Choose a reason for hiding this comment

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

The test should check, whether the action codes recognizes the error, if the given submitters or supporters are not in a list.
The code could repair the problem, i.e make it a list or throw an exception, that it is no list.

Copy link
Member Author

Choose a reason for hiding this comment

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

I already have tests that check if it works when the submitters/supporters are not in a list.
It works, even after removing the if clauses. I surmise that the if clauses were unnecessary.
Does this address your concerns for this remark?

entry_list: list[Dict[str, Any]] = []
message_set = set()
lookup = (
self.submitter_lookup
Copy link
Member

Choose a reason for hiding this comment

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

Why do you use 2 different lookups. You could join the data for all users in 1 lookup, because it doesn't matter, where you find the user.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, that is a remainder from when I actually used the lookup class for this, I'll change it

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in json_upload, still have to look at the import

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in import as well

entry_list.append(
{"value": user, "info": ImportState.WARNING}
)
message_set.add(
Copy link
Member

Choose a reason for hiding this comment

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

You could add the multi-referenced usernames and put them finally into one message

Copy link
Member Author

Choose a reason for hiding this comment

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

Done for users

Copy link
Member Author

Choose a reason for hiding this comment

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

Done for tags

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in import as well

)
else:
username_set.add(user)
found_users = lookup.get(user, [])
Copy link
Member

Choose a reason for hiding this comment

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

You cannot get more than one user, the username is unique. If you find duplicate users, you should throw an exception and finish the json_upload immediately,

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

@r-peschke r-peschke left a comment

Choose a reason for hiding this comment

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

Sorry, but there are some things.
Tomorrow I'll continue with import, ...

tests/system/action/motion/test_create.py Outdated Show resolved Hide resolved
)
return self._first_state_id

def _get_field_array(self, entry: dict[str, Any], fieldname: str) -> list[str]:
Copy link
Member

Choose a reason for hiding this comment

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

Seems, that this method is never used

Copy link
Member Author

Choose a reason for hiding this comment

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

I've deleted it

)
recommendation_check = self._check_recommendation_and_state(instance)
if recommendation_check:
errors += recommendation_check
Copy link
Member

Choose a reason for hiding this comment

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

Could you write a test with an error in recommendation_checks?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done (see motion/test_update.py test_only_motion_allowed and ..._2

errors.append(
{
"type": MotionErrorType.MOTION_TYPE,
"message": "You can't give both of lead_motion_id and statute_paragraph_id.",
Copy link
Member

Choose a reason for hiding this comment

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

Missing test for this error

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

errors.append(
{
"type": MotionErrorType.AMENDMENT_PARAGRAPHS,
"message": "You can't give amendment_paragraphs in this context",
Copy link
Member

Choose a reason for hiding this comment

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

Also missing a test for this error

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

payload, meeting_id
)
for err in errors:
fieldname = ""
Copy link
Member

Choose a reason for hiding this comment

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

Maybe the problem will be resolved by other tests, but there is no test with errors passing this code

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

},
)
self.assert_status_code(response, 200)
motion = self.get_model("motion/1")
Copy link
Member

Choose a reason for hiding this comment

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

Here you should use the self.assert_model_exists-method

@luisa-beerboom luisa-beerboom added this pull request to the merge queue Feb 21, 2024
Merged via the queue into OpenSlides:main with commit 8a1a78d Feb 21, 2024
5 checks passed
@luisa-beerboom luisa-beerboom deleted the 1713-motion-import branch February 21, 2024 15:58
peb-adr added a commit that referenced this pull request Mar 12, 2024
* commit '7e10e3f80bc28f6a87cbb7ff426e84dd5fd3ab4f': (90 commits)
  Add cascade deletion to new motion fields (#2243) (#2284)
  Update all translations (#2282)
  Implement certain preventions for changing active speakers state (#2272)
  Update meta (#2269)
  Implement cascade delete for amendments (#2253)
  Automatically create PRs for commits on staging branches (#2256)
  Add staging branches to CI (#2255)
  Fix PoO for others (#2242)
  Make SLLoS ignore point-of-order time (#2240)
  Bump types-bleach in /requirements/partial (#2238)
  Update meta repository (#2235)
  Implement motion import (#1923)
  Enhance speaker creation (#2231)
  Add migration command to clear collectionfield tables (#2217)
  Allow initial_time to be changed regardless of speach status (#2220)
  Bump types-simplejson in /requirements/partial (#2223)
  Bump types-redis in /requirements/partial (#2221)
  Bump pypdf[crypto] from 4.0.1 to 4.0.2 in /requirements/partial (#2222)
  Bump pytest from 8.0.0 to 8.0.1 in /requirements/partial (#2224)
  Bump types-requests in /requirements/partial (#2225)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[imports] Relocate csv imports to the backend: Motion
3 participants