Skip to content

Conversation

JonnyWong16
Copy link
Collaborator

@JonnyWong16 JonnyWong16 commented Mar 11, 2021

Description

This is a complete rewrite of the library search feature. See doc string for LibrarySection.search() for complete details and examples.

Deprecated methods

  • LibrarySection.filterFields(): use listFields() instead.
  • LibrarySection.listChoices(): use listFilterChoices() instead.

New methods
See doc strings for each method for complete details and examples.

  • LibrarySection.filterTypes()
  • LibrarySection.getFilterType()
  • LibrarySection.fieldTypes()
  • LibrarySection.getFieldType()
  • LibrarySection.listFilters()
  • LibrarySection.listSorts()
  • LibrarySection.listFields()
  • LibrarySection.listOperators()
  • LibrarySection.listFilterChoices()
  • LibrarySection.hubSearch(): alias for PlexServer.search(query, sectionId=librarySectionID)
  • MovieSection.searchMovies(): alias for LibrarySection.search(libtype='movie')
  • ShowSection.searchSeasons(): alias for LibrarySection.search(libtype='season')

Breaking changes

  • librarySectionID is casted to an int everywhere instead of a str
  • LibrarySection.filters is casted to a bool instead of a str
  • LibrarySection.key is casted to a int instead of a str

Closes #598

Fixes #320
Fixes #392
Fixes #553
Fixes #595
Fixes #623
Fixes #691
Fixes #694
Fixes #695

Type of change

Please delete options that are not relevant.

  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated the docstring for new or existing methods
  • I have added tests when applicable

@meisnate12
Copy link
Contributor

saw this and started playing with the update to see what it could do and when I try this:

ps = PlexServer("http://IP.IP.IP.IP:32400", "thisisnotmytoken", timeout=600)
plex = next((s for s in ps.library.sections() if s.title == "TV Shows"), None)
items = plex.search(**{"genre": "Comedy"})
print(items)

i get the error

  File "C:\Users\meisn\Documents\Python\Plex Meta Manager\test.py", line 67, in <module>
    items = plex.search(**{"show.genre": "Comedy"})
  File "C:\Users\meisn\Documents\Python\Plex Meta Manager\venv\lib\site-packages\plexapi\library.py", line 1064, in search
    filter_args.append(self._validateFilterField(field, values, libtype))
  File "C:\Users\meisn\Documents\Python\Plex Meta Manager\venv\lib\site-packages\plexapi\library.py", line 768, in _validateFilterField
    result = self._validateFieldValue(filterField, values, libtype)
  File "C:\Users\meisn\Documents\Python\Plex Meta Manager\venv\lib\site-packages\plexapi\library.py", line 811, in _validateFieldValue
    filterChoices = self.listFilterChoices(filterField.key, libtype)
  File "C:\Users\meisn\Documents\Python\Plex Meta Manager\venv\lib\site-packages\plexapi\library.py", line 735, in listFilterChoices
    raise NotFound('Unknown filter: %s. '
plexapi.exceptions.NotFound: Unknown filter: show.genre. Available filters: ['genre', 'year', 'contentRating', 'studio', 'collection', 'director', 'actor', 'writer', 'producer', 'unwatchedLeaves', 'unmatched', 'label']

if I change items = plex.search(**{"genre": "Comedy"}) to items = plex.search(**{"show.genre": "Comedy"})
I get the exact same error

also, I tried specifying the libtype="show" and received the same error message

@JonnyWong16
Copy link
Collaborator Author

Try it now. Let me know if you find any other errors.

@meisnate12
Copy link
Contributor

ok it works now I'm working on an update for my program for once this comes out if I find anything else I'll let you know

@meisnate12
Copy link
Contributor

ok so now im trying to use the & operator this is my code

ps = PlexServer("http://IP.IP.IP.IP:32400", "thisisnotmytoken", timeout=600)
plex = next((s for s in ps.library.sections() if s.title == "Movies"), None)
print(len(plex.search(**{"genre": "Comedy"})))
print(len(plex.search(**{"genre": "Action"})))
print(len(plex.search(**{"genre": ["Comedy", "Action"]})))
print(len(plex.search(**{"genre&": ["Comedy", "Action"]})))
print(len(plex.search(**{"genre": "Comedy", "genre&": ["Action"]})))

with the results:

690    <--- this is the correct number of movies I have with Comedy
702    <--- this is the correct number of movies I have with Action
1254   <--- this is the correct number of movies I have with Comedy or Action
1980   <--- this is my total number of movies in plex according to the plex search in the UI I should have 138 with both Genre tags
690    <--- this is the number of movies I have with Comedy adding the `genre&` did nothing

it seems to me that the & search isn't working correctly unless I'm using it wrong

@JonnyWong16
Copy link
Collaborator Author

Fixed the & operator.

Fixes pushingkarmaorg#694
When using a PlexAPI operator, fetchItems may return zero results in the first container causing the loop to break early. This changes the break condition to check if the container exceeds the total number of items therefore there will be no more items to fetch.
Fixes pushingkarmaorg#695
totalSize was getting overwritten when using search with a different libtype. This makes totalSize independant from search.
@meisnate12
Copy link
Contributor

duration search doesn't seem to work. I either get all items in my library or 0 items depending on if I use << or >> no matter what int I gave it.

@JonnyWong16
Copy link
Collaborator Author

I cannot reproduce the issue.

>>> movies = plex.library.section("Movies")
>>> len(movies.all())
1937
>>> duration = 5400000  # 1.5 hours in milliseconds
>>> len(movies.search(**{"duration<<": duration}))
288
>>> len(movies.search(**{"duration>>": duration})) 
1649

@meisnate12
Copy link
Contributor

ok yea that ones my mess up it does work sorry

@JonnyWong16 JonnyWong16 marked this pull request as ready for review March 19, 2021 23:03
@Hellowlol
Copy link
Collaborator

This looks awesome. Great work!

@Hellowlol Hellowlol merged commit 1beee64 into pushingkarmaorg:master Mar 21, 2021
@Montellese
Copy link
Contributor

Thanks for all these changes.

I noticed that your change to split _totalSize and _totalViewSize has made it impossible to determine how many collections are in a movie section or how many seasons or episodes are in a tvshow section. I need this information to be able to perform paginated search requests. If I access the private LibrarySection._totalViewSize member instead of using the public LibrarySection.totalSize property everything works fine again. How should we fix / resolve this?

Furthermore I noticed that you changed all library section IDs from str to int which I like. But the docstring at https://github.com/pkkid/python-plexapi/blob/2bde2344084721d7015167af4762d3bc397fe5d2/plexapi/library.py#L65 still says that the expected sectionID is a str instead of int.

@JonnyWong16
Copy link
Collaborator Author

Thanks. See #712.

@meisnate12
Copy link
Contributor

meisnate12 commented Mar 24, 2021

I was trying to do a title search using a list like so

print(len(plex.search(**{"title": "Star"})))                # Worked returned 32
print(len(plex.search(**{"title": "Wars"})))                # Worked returned 16
print(len(plex.search(**{"title": ["Wars"]})))              # Failed returned 0
print(len(plex.search(**{"title": ["Star", "Wars"]})))      # Failed returned 0
print(len(plex.search(**{"title&": ["Star", "Wars"]})))     # Worked returned 13

and while getting the correct results for some searches, using a list with title results in 0 items returned. Is there any way to do an OR title search? If not could it be added in? I tried similar tests with the other string I'm using, which is studio, and it was able to or together values ok

@JonnyWong16
Copy link
Collaborator Author

That's a bug I missed because title is already an argument for search() so the**kwarg for title is not being applied.

This should be a workaround for title OR specifically until it's fixed.

plex.search(title="Star,Wars")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment