Developer Interface#

Session#

class pysjtu.session.BaseSession#

Bases: object

Base session

class pysjtu.session.Session(username='', password='', cookies=None, ocr=None, session_file=None, retry=None, base_url='https://i.sjtu.edu.cn', **kwargs)#

Bases: BaseSession

A pysjtu session with login management, cookie persistence, etc.

Usage:

>>> import pysjtu
>>> s = pysjtu.Session()
>>> s.login('user@sjtu.edu.cn', 'something_secret')
>>> s.get('https://i.sjtu.edu.cn')
<Response [200 OK]>
>>> s.dump('session_file')

Or as a context manager:

>>> with pysjtu.Session(username='user@sjtu.edu.cn', password='something_secret') as s:
...     s.get('https://i.sjtu.edu.cn')
...     s.dump('session_file')
<Response [200 OK]>

>>> with pysjtu.Session(session_file='session_file', mode='r+b')) as s:
...     s.get('https://i.sjtu.edu.cn')
<Response [200 OK]>

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • username (str) – JAccount username.

  • password (str) – JAccount password.

  • cookies (Optional[Union[Cookies, CookieJar]]) – The cookie to be used on each request.

  • ocr (Optional[Recognizer]) – The captcha Recognizer.

  • session_file (Optional[Union[BinaryIO, str, Path]]) – The file which a session is loaded from & saved to.

  • retry (Optional[list]) – A list contains retry delays. If it’s exhausted, an exception will be raised.

  • base_url (str) – Base url of backend APIs.

request(method, url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • method (str) – HTTP method for the new Request object: GET, OPTIONS, HEAD, POST, PUT, PATCH, or DELETE.

  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

get(url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a GET request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

options(url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a OPTIONS request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

head(url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a HEAD request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

post(url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a POST request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

put(url, *, validate_session=True, auto_renew=True, **kwargs)#

Send a PUT request. If asked, validate the current session and renew it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

patch(url, *, validate_session=True, auto_renew=True, **kwargs)#

Sends a PATCH request. If asked, validates the current session and renews it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

delete(url, *, validate_session=True, auto_renew=True, **kwargs)#

Sends a DELETE request. If asked, validates the current session and renews it when necessary.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:
  • url (Union[URL, str]) – URL for the new Request object.

  • validate_session (bool) – (optional) Whether to validate the current session.

  • auto_renew (bool) – (optional) Whether to renew the session when it expires. Works when validate_session is True.

Return type:

Response

login(username, password)#

Log in JAccount using given username & password.

Parameters:
  • username (str) – JAccount username.

  • password (str) – JAccount password.

Raises:

LoginException – Failed to log in after several attempts.

logout(purge_session=True)#

Log out JAccount.

Parameters:

purge_session (bool) – (optional) Whether to purge local session info. May causes inconsistency, so use with caution.

loads(d)#

Read a session from a given dict. A warning will be given if username or password field is missing.

Parameters:

d (dict) – a dict contains a session.

load(fp)#

Read a session from a given file. A warning will be given if username or password field is missing.

Parameters:

fp (Union[BinaryIO, str, Path]) – a binary file object / filepath contains a session.

dumps()#

Return a dict represents the current session. A warning will be given if username or password field is missing.

Returns:

a dict represents the current session.

Return type:

dict

dump(fp)#

Write the current session to a given file. A warning will be given if username or password field is missing.

Parameters:

fp (Union[BinaryIO, str, Path]) – a binary file object/ filepath as the destination of session data.

property cookies: Union[Cookies, CookieJar]#

Get or set the cookie to be used on each request. Session validation is performed on each set event.

Raises:

SessionException – when given cookie doesn’t contain a valid session.

property timeout: Timeout#

Get or set the timeout to be used on each request.

property base_url: URL#

Base url of backend APIs.

Client#

class pysjtu.client.Client(session)#

Bases: ProfileMixin, SelectionMixin, ScheduleMixin, CourseLibMixin, ExamMixin, GPAMixin, ScoreMixin, BaseClient

A pysjtu client with schedule query, score query, exam query, etc.

Usage:

>>> import pysjtu
>>> s = pysjtu.Session(username="user@sjtu.edu.cn", password="something_secret")
>>> client = pysjtu.Client(session=s)
>>> sched = client.schedule(2019, 0)
>>> sched
[<ScheduleCourse 军事理论 week=[range(9, 17)] day=1 time=range(1, 3)>, ...]
>>> sched.filter(time=range(3,5), day=range(2, 4))
[<ScheduleCourse 程序设计思想与方法(C++) week=[range(1, 10), range(11, 17)] day=2 time=range(3, 5)>,
<ScheduleCourse 大学英语(4) week=[range(1, 17)] day=3 time=range(3, 5)>]
Parameters:

session (BaseSession) – The Session to be built upon.

property term_start_date: date#

Get the term start date for the current term.

property student_id: int#

Get the student id of the current session.

pysjtu.client.create_client(username='', password='', cookies=None, ocr=None, session_file=None, retry=None, base_url='https://i.sjtu.edu.cn', **kwargs)#

Create a new Client with given options.

This is just a shortcut for Client(Session(*args, **kwargs)). To manipulate or reuse underlying Session object, use pysjtu.session.Session and Client instead.

Returns:

an authenticated Client.

Return type:

Client

Note

Anything that has request-compatible get, post methods and a _cache_store dict can be accepted as a Session.

Recognizers#

class pysjtu.ocr.Recognizer#

Bases: object

Base class for Recognizers

class pysjtu.ocr.JCSSRecognizer(url='https://jcss.lightquantum.me', **kwargs)#

Bases: Recognizer

An online recognizer using JCSS (JAccount Captcha Solver Service). This is the default recognizer for pysjtu.session.Session. You don’t need to install any extra packages to use it.

It shares the same backend implementation with NNRecognizer, but is deployed on a remote server.

By default, it uses the public instance of JCSS, but you can also deploy your own. See PhotonQuantum/jcss-rs.

For additional keyword arguments, see https://www.python-httpx.org/api.

Parameters:

url (str) – The URL of the JCSS instance.

class pysjtu.ocr.NNRecognizer(model_file=None)#

Bases: Recognizer

A Neural Network based captcha recognizer.

It feeds the image directly into a pre-trained deep model to predict the answer.

It consumes more memory and computing power than LegacyRecognizer. By using the provided model, the accuracy is around 99%.

It’s currently the default recognizer.

Usage:

>>> import pysjtu
>>> s = pysjtu.Session(ocr=NNRecognizer("nn_model.onnx"))
>>> s.login('user@sjtu.edu.cn', 'something_secret')
Parameters:

model_file (Optional[str]) – Pretrained ONNX model file (use built-in model if not specified).

recognize(img)#

Predict the captcha.

Parameters:

img (bytes) – A bytes array containing the captcha image.

Returns:

captcha in plain text.

class pysjtu.ocr.LegacyRecognizer(model_file=None)#

Bases: Recognizer

A legacy captcha recognizer. DEPRECATED.

It first applies projection-based algorithm to the input image, then use a pre-trained SVM model to predict the answer.

It’s memory and cpu efficient, but has a low accuracy. It’s recommended to use NNRecognizer instead.

Usage:

>>> import pysjtu
>>> s = pysjtu.Session(ocr=LegacyRecognizer("svm_model.onnx"))
>>> s.login('user@sjtu.edu.cn', 'something_secret')
Parameters:

model_file (Optional[str]) – Pretrained ONNX model file (use built-in model if not specified).

recognize(img)#

Predict the captcha.

Parameters:

img (bytes) – A bytes array containing the captcha image.

Returns:

captcha in plain text.

Schema#

Utilities helpful for creating the model for a new API. If you want to contribute to this project, you may want to read this.

This package uses marshmallow and marshmallow_dataclass to define the schema of the data.

Example

from marshmallow_dataclass import dataclass
from marshmallow import EXCLUDE
from pysjtu.fields import SplitField

@dataclass(base_schema=FinalizeHook(LoadDumpSchema))    # to support separate alias for load and dump
class Foo(Result):
    bar: str
    baz: int = mfield(required=True, load_key="baz_id")
    names: WithField(List[str], field=SplitField, sep=",") = mfield(required=True)

For more complex use cases, you can read the schema of GPAQueryParams for reference.

class pysjtu.schema.HookedSchema(*, only=None, exclude=(), many=False, context=None, load_only=(), dump_only=(), partial=False, unknown=None)#

Bases: Schema

A Schema that supports hooks.

This is a helper wrapper for marshmallow.Schema, which supports ordered hooks.

The original decorator hooks provided by marshmallow do not ensure execution order if multiple hooks present. This class uses inheritance to ensure execution order.

To use this class, inherit from it and use pysjtu.schema.FinalizeHook() to transform the class into a Schema.

pysjtu.schema.FinalizeHook(cls)#

Transform a HookedSchema into a Schema.

Return type:

Type[Schema]

class pysjtu.schema.LoadDumpSchema(*, only=None, exclude=(), many=False, context=None, load_only=(), dump_only=(), partial=False, unknown=None)#

Bases: HookedSchema

A Schema that supports load and dump key renaming.

Use load_key and dump_key in field metadata to specify the key to be used in load and dump.

pysjtu.schema.mfield(default=<dataclasses._MISSING_TYPE object>, *, required=False, raw=False, load_key=<class 'pysjtu.schema.UNSET'>, dump_key=<class 'pysjtu.schema.UNSET'>, data_key=<class 'pysjtu.schema.UNSET'>, load_default=<class 'pysjtu.schema.UNSET'>, dump_default=<class 'pysjtu.schema.UNSET'>, **kwargs)#

Helper method to create a marshmallow field with metadata.

This method is a wrapper for dataclasses.field() that adds metadata to the field. It also supports the load_key and dump_key metadata, which are used by LoadDumpSchema.

pysjtu.schema.WithField(ty, field=None, **kwargs)#

Helper functor to attach custom serializer/deserializer to a field.

Parameters:
  • ty (Type[T]) – The type of the field.

  • field (Optional[Type[Field]]) – The marshmallow field (serializer/deserializer) to be attached.

Return type:

Callable[[T], T]

Exceptions#

exception pysjtu.exceptions.LoadWarning#

Bases: UserWarning

Missing fields in the loaded dict, which may cause a SessionException later.

exception pysjtu.exceptions.DumpWarning#

Bases: UserWarning

Missing fields in the dumped dict, which may cause a SessionException later.

exception pysjtu.exceptions.GPACalculationException#

Bases: Exception

A failure has been reported by the remote server when calculating GPA.

exception pysjtu.exceptions.SelectionNotAvailableException#

Bases: Exception

Course selection function is not available at this time.

exception pysjtu.exceptions.SelectionClassFetchException#

Bases: Exception

Unable to fetch selection class information.

exception pysjtu.exceptions.RegistrationException#

Bases: Exception

Base exception for class registration failures.

exception pysjtu.exceptions.DropException#

Bases: Exception

Base exception for class drop failures.

exception pysjtu.exceptions.FullCapacityException#

Bases: RegistrationException

There’s no room for this class.

exception pysjtu.exceptions.TimeConflictException#

Bases: RegistrationException

There’s a time conflict when registering for this class.

exception pysjtu.exceptions.SessionException#

Bases: Exception

The session is expired or invalid, and we can’t renew it automatically.

exception pysjtu.exceptions.LoginException#

Bases: Exception

An error occurred when logging into the website

exception pysjtu.exceptions.OCRException#

Bases: Exception

An error occurred when solving captcha

exception pysjtu.exceptions.ServiceUnavailable#

Bases: Exception

The website is down or under maintenance.