Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ jobs:
tox:
strategy:
fail-fast: false
max-parallel: 5
matrix:
python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
python: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
Expand Down
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ requests = "*"
kazoo = "*"

[requires]
python_version = "3.9"
python_version = "3.10"
379 changes: 225 additions & 154 deletions Pipfile.lock

Large diffs are not rendered by default.

14 changes: 1 addition & 13 deletions get-solr-download-url.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
#!/usr/bin/env python
# encoding: utf-8

from __future__ import absolute_import, division, print_function, unicode_literals

import sys
from itertools import chain
from urllib.parse import urljoin

import requests

# Try to import urllib from the Python 3 reorganized stdlib first:
try:
from urllib.parse import urljoin
except ImportError:
try:
from urlparse.parse import urljoin
except ImportError:
from urlparse import urljoin


if len(sys.argv) != 2:
print("Usage: %s SOLR_VERSION" % sys.argv[0], file=sys.stderr)
sys.exit(1)
Expand Down
163 changes: 32 additions & 131 deletions pysolr.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function, unicode_literals

import ast
import datetime
import logging
import os
import random
import re
import time
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _get_version
from xml.etree import ElementTree # noqa: ICN001

import requests

try:
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _get_version
except ImportError:
# python < 3.8
from importlib_metadata import PackageNotFoundError
from importlib_metadata import version as _get_version

try:
from kazoo.client import KazooClient, KazooState
except ImportError:
Expand All @@ -31,42 +22,10 @@
except ImportError:
import json

try:
# Python 3.X
from urllib.parse import urlencode
except ImportError:
# Python 2.X
from urllib import urlencode

try:
# Python 3.X
from urllib.parse import quote
except ImportError:
# Python 2.X
from urllib import quote

try:
# Python 3.X
import html.entities as htmlentities
except ImportError:
# Python 2.X
import htmlentitydefs as htmlentities

try:
# Python 3.X
from http.client import HTTPException
except ImportError:
from httplib import HTTPException

try:
# Python 2.X
unicode_char = unichr
except NameError:
# Python 3.X
unicode_char = chr
# Ugh.
long = int # NOQA: A001

import html.entities as htmlentities
from http.client import HTTPException
from urllib.parse import quote, urlencode

__author__ = "Daniel Lindsley, Joseph Kocherhans, Jacob Kaplan-Moss, Thomas Rieder"
__all__ = ["Solr"]
Expand Down Expand Up @@ -110,33 +69,14 @@ def emit(self, record):
LOG.addHandler(stream)


def is_py3():
try:
basestring
return False
except NameError:
return True


IS_PY3 = is_py3()


def force_unicode(value):
"""
Forces a bytestring to become a Unicode string.
"""
if IS_PY3:
# Python 3.X
if isinstance(value, bytes):
value = value.decode("utf-8", errors="replace")
elif not isinstance(value, str):
value = str(value)
else:
# Python 2.X
if isinstance(value, str):
value = value.decode("utf-8", "replace")
elif not isinstance(value, basestring): # NOQA: F821
value = unicode(value) # NOQA: F821
if isinstance(value, bytes):
value = value.decode("utf-8", errors="replace")
elif not isinstance(value, str):
value = str(value)

return value

Expand All @@ -145,12 +85,8 @@ def force_bytes(value):
"""
Forces a Unicode string to become a bytestring.
"""
if IS_PY3:
if isinstance(value, str):
value = value.encode("utf-8", "backslashreplace")
else:
if isinstance(value, unicode): # NOQA: F821
value = value.encode("utf-8")
if isinstance(value, str):
value = value.encode("utf-8", "backslashreplace")

return value

Expand All @@ -171,46 +107,30 @@ def fixup(m):
# character reference
try:
if text[:3] == "&#x":
return unicode_char(int(text[3:-1], 16))
return chr(int(text[3:-1], 16))
else:
return unicode_char(int(text[2:-1]))
return chr(int(text[2:-1]))
except ValueError:
pass
else:
# named entity
try:
text = unicode_char(htmlentities.name2codepoint[text[1:-1]])
text = chr(htmlentities.name2codepoint[text[1:-1]])
except KeyError:
pass
return text # leave as is

return re.sub(r"&#?\w+;", fixup, text)


def safe_urlencode(params, doseq=0):
def safe_urlencode(params, doseq=False):
"""
UTF-8-safe version of safe_urlencode
URL-encode parameters using UTF-8 encoding.

The stdlib safe_urlencode prior to Python 3.x chokes on UTF-8 values
which can't fail down to ascii.
This is a wrapper around `urllib.parse.urlencode` that ensures
consistent UTF-8 handling for all parameter values.
"""
if IS_PY3:
return urlencode(params, doseq)

if hasattr(params, "items"):
params = params.items()

new_params = []

for k, v in params:
k = k.encode("utf-8")

if isinstance(v, (list, tuple)):
new_params.append((k, [force_bytes(i) for i in v]))
else:
new_params.append((k, force_bytes(v)))

return urlencode(new_params, doseq)
return urlencode(params, doseq)


def clean_xml_string(s):
Expand Down Expand Up @@ -622,9 +542,9 @@ def _scrape_response(self, headers, response):
full_html = ""
dom_tree = None

# In Python3, response can be made of bytes
if IS_PY3 and hasattr(response, "decode"):
if hasattr(response, "decode"):
response = response.decode()

if response.startswith("<?xml"):
# Try a strict XML parse
try:
Expand Down Expand Up @@ -707,14 +627,8 @@ def _from_python(self, value):
else:
value = "false"
else:
if IS_PY3:
# Python 3.X
if isinstance(value, bytes):
value = str(value, errors="replace") # NOQA: F821
else:
# Python 2.X
if isinstance(value, str):
value = unicode(value, errors="replace") # NOQA: F821
if isinstance(value, bytes):
value = str(value, errors="replace") # NOQA: F821

value = "{0}".format(value)

Expand All @@ -724,7 +638,7 @@ def _to_python(self, value):
"""
Converts values from Solr to native Python values.
"""
if isinstance(value, (int, float, long, complex)):
if isinstance(value, (int, float, complex)):
return value

if isinstance(value, (list, tuple)):
Expand All @@ -740,18 +654,11 @@ def _to_python(self, value):

is_string = False

if IS_PY3:
if isinstance(value, bytes):
value = force_unicode(value)

if isinstance(value, str):
is_string = True
else:
if isinstance(value, str):
value = force_unicode(value)
if isinstance(value, bytes):
value = force_unicode(value)

if isinstance(value, basestring): # NOQA: F821
is_string = True
if isinstance(value, str):
is_string = True

if is_string:
possible_datetime = DATETIME_REGEX.search(value)
Expand Down Expand Up @@ -791,14 +698,8 @@ def _is_null_value(self, value):
if value is None:
return True

if IS_PY3:
# Python 3.X
if isinstance(value, str) and len(value) == 0:
return True
else:
# Python 2.X
if isinstance(value, basestring) and len(value) == 0: # NOQA: F821
return True
if isinstance(value, str) and len(value) == 0:
return True

# TODO: This should probably be removed when solved in core Solr level?
return False
Expand Down Expand Up @@ -1484,7 +1385,7 @@ def __init__(
auth=None,
verify=True,
*args,
**kwargs
**kwargs,
):
url = zookeeper.getRandomURL(collection)
self.auth = auth
Expand All @@ -1502,7 +1403,7 @@ def __init__(
auth=self.auth,
verify=self.verify,
*args,
**kwargs
**kwargs,
)

def _send_request(self, method, path="", body=None, headers=None, files=None):
Expand Down
3 changes: 0 additions & 3 deletions run-tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#!/usr/bin/env python
# encoding: utf-8

from __future__ import absolute_import, print_function, unicode_literals

import faulthandler
import signal
Expand Down
7 changes: 2 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@
],
url="https://github.com/django-haystack/pysolr/",
license="BSD",
install_requires=[
"requests>=2.9.1",
"setuptools",
"importlib_metadata; python_version<'3.8'",
],
install_requires=["requests>=2.9.1", "setuptools"],
python_requires=">=3.10",
extras_require={"solrcloud": ["kazoo>=2.5.0"]},
setup_requires=["setuptools_scm"],
)
2 changes: 0 additions & 2 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# encoding: utf-8

from __future__ import absolute_import, print_function, unicode_literals

from .test_admin import * # NOQA
from .test_client import * # NOQA
from .test_cloud import * # NOQA
4 changes: 0 additions & 4 deletions tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
# -*- coding: utf-8 -*-

from __future__ import absolute_import, unicode_literals

import unittest

from pysolr import SolrCoreAdmin
Expand Down
Loading
Loading