Skip to main content

Lux Logo

PyPI version GitHub stars GitHub release

LuxY is a Python wrapper for Yale's Lux API. Lux allows users to search and filter the collections of Yale's museums and libraries, as well as external collections. This lets you find and connect with the cultural heritage collections across Yale's museums, archives, and libraries in new ways and all in one place.

LuxY gives you a Pythonic way to interact with the Lux API, making it easier to search and filter the collections and even download the data in JSON format. It can handle pagination, nested filters, and more.

Installation

To get started, install LuxY using pip:

pip install luxy

Usage

The classes of LuxY replicate the classes of the Lux API. They are:

  1. PeopleGroups (agent) - People and Groups that are either individuals or organizations
  2. Objects (item) - Physical objects in Yale's collections
  3. Works (work) - Visual and textual works, including images, texts, and other creative expressions
  4. Places (place) - Geographic locations and named spaces
  5. Concepts (concept) - Types, materials, languages, measurement units, currencies and other conceptual entities
  6. Events (event) - Historical events and occurrences
  7. Collections (set) - Collections and sets of objects curated by Yale's institutions

Each of these has common and unique filters that take different data types, from strings to numbers to dates. LuxY also supports nested filters, which are used to filter by multiple levels of the hierarchy. This allows users to create complex queries similar to the ones found in the Lux UI.

Understanding Options

Each filter has a set of options that can be used to filter the data. These options are stored in the get_options() method.

from luxy import PeopleGroups

options = PeopleGroups().get_options()
print(options)

# pretty print the options
PeopleGroups().list_filters()

People Groups

from luxy import PeopleGroups

result = PeopleGroups().filter(name="Rembrandt").get()
print(result.url)
print(result.view_url)
print(result.json)

Objects

from luxy import Objects

result = Objects().filter(name="Rembrandt").get()
print(result.url)
print(result.view_url)
print(result.json)

Works

from luxy import Works

result = Works().filter(name="Painting").get()
print(result.url)
print(result.view_url)
print(result.json)

Places

from luxy import Places

result = Places().filter(name="Amsterdam").get()
print(result.url)
print(result.view_url)
print(result.json)

Concepts

from luxy import Concepts

result = Concepts().filter(name="gilding").get()
print(result.url)
print(result.view_url)
print(result.json)

Events

from luxy import Events

result = Events().filter(name="Thirty Years War").get()
print(result.url)
print(result.view_url)
print(result.json)

Collections

from luxy import Collections

result = Collections().filter(name="Letters").get()
print(result.url)
print(result.view_url)
print(result.json)

Working with Numerical Filters

Numerical filters are a bit tricky because they require a tuple with the value and the comparison operator.

from luxy import Objects

result = Objects().filter(height=(1, ">=")).get()
print(result.url)
print(result.view_url)
print(result.json)

Working with Date Filters

Date filters are a bit tricky because they require a tuple with the value and the comparison operator. The value should be a string in the format of YYYY-MM-DDTHH:MM:SS.SSSZ.

from luxy import Objects

result = Objects().filter(encounteredDate=("1987-01-01T00:00:00.000Z", ">=")).get()
print(result.url)
print(result.view_url)
print(result.json)

Complex Example

from luxy import PeopleGroups

result = (
    PeopleGroups()
    .filter(recordType="person")
    .filter(hasDigitalImage=True)
    .filter(text="rembrandt")
    .filter(gender={"name": "male"})
    .get()
)

# print the number of results
print("Number of results:", result.num_results)

# print the url
print("URL:", result.url)

# print the json
print("JSON:", result.json)

Expected Output

Number of results: 131
URL: https://lux.collections.yale.edu/api/search/agent?q=%7B%22AND%22%3A%20%5B%7B%22recordType%22%3A%20%22person%22%7D%2C%20%7B%22hasDigitalImage%22%3A%201%7D%2C%20%7B%22text%22%3A%20%22rembrandt%22%7D%2C%20%7B%22gender%22%3A%20%7B%22id%22%3A%20%22https%3A//lux.collections.yale.edu/data/concept/6f652917-4c07-4d51-8209-fcdd4f285343%22%7D%7D%5D%7D
JSON: {'@context': 'https://linked.art/ns/v1/search.json'...

Working with Pagination

from luxy import PeopleGroups

result = (
    PeopleGroups()
    .filter(endAt={"name": "Amsterdam"})
    .get()
)

# print the number of results
print("Number of results:", result.num_results)
print("Number of pages:", result.num_pages())

for i, page in enumerate(result.get_page_data_all(), 1):
    if i > 2: # Break after 2 pages
        break
    print(f"Page {i}:", page["id"])
    for j, item in enumerate(result.get_items(page)):
        print(f"Item {j}:", result.get_item_data(item)["_label"])

Nested MemberOf Filters

result = (
    Objects()
    .filter(hasDigitalImage=True)
    .filter(
        OR=[
            Objects().memberOf("Letters", depth=2),
            Objects().memberOf("Letters", depth=3),
            Objects().memberOf("Letters", depth=4)
        ]
    )
    .filter(name="letter")
    .get()
)

print(result.url)
print(result.json)

Roadmap

v. 0.0.2

  • Add support for People/Groups
    • Filter by:
      • Has Digital Image
      • Gender
      • Nationality (nationality)
      • Person or Group Class
      • Categorized As (classification)
      • Born/Formed At (startAt)
      • Born/Formed Date
      • Carried Out (carriedOut)
      • Created Object (produced)
      • Created Works (created)
      • Curated (curated)
      • Died/Dissolved At (endAt)
      • Died/Dissolved Date
      • Encountered
      • Founded By
      • Founded Group
      • Have Member
      • ID
      • Identifier
      • Influenced (influenced)
      • Influenced Creation Of Objects
      • Influenced Creation Of Works
      • Member Of (memberOf)
      • Occupation/Role (occupation)
      • Professional Activity Categorized As (professionalActivity)
      • Professionally Active At (activeAt)
      • Professionally Active Date
      • Published (published)
      • Subject Of
  • Add support for Objects
  • Add support for Works
  • Add support for Places
  • Add support for Concepts
  • Add support for Events
  • Add support for Pagination
  • Add support for Downloading Page JSON
  • Add support for Downloading Item JSON
  • Add more filters
  • Add support for date filters
  • Add support for numbers
    • Greater Than
    • Less Than
    • Greater Than or Equal To
    • Less Than or Equal To
    • Equal To
    • Not Equal To
  • Add And support for filters
  • Add support for OR filters
  • Add support for have All of # AND
  • Add support for have Any of # OR
  • Add support for have None of # NOT
  • Add more tests
  • Add more documentation
  • Add a check to make sure a filter exists

Metadata

Release files for luxy 0.0.8

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for luxy 0.0.8
File Size Uploaded
luxy-0.0.8.tar.gz 16.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for luxy 0.0.8
File Interpreter ABI Platform
luxy-0.0.8-py3-none-any.whl Python 3 none any Details

Total release size: 28.7 kB

Release files / luxy-0.0.8.tar.gz

Download URL luxy-0.0.8.tar.gz
Size 16.1 kB
Tags Source
SHA-256 checksum
How to use checksums
4c0fee743de7d212aabbdc4f3765e9e172b94abcfa09e78000dd627d2f9c303d
BLAKE2b-256 checksum
How to use checksums
e083664a80a02cc6286eb3573a82ffa26771760ead03dfc4522b8bd193369c4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.7

Release files / luxy-0.0.8-py3-none-any.whl

Download URL luxy-0.0.8-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
00615d8343b4bd96c40c0e9869bcd4aca02c148fe10ece298828039314f6a3bd
BLAKE2b-256 checksum
How to use checksums
c373f5fca41518a4fa3f84b0e2e09abd334919797a86e24eb347ffccd3220e7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

0.0.8 This release

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

1 release file

0.0.4

1 release file

0.0.3

1 release file

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page