<commit_before>import requests
import json
import getpass


class AuthenticationError(Exception):
    """AuthenticationError"""


class NotAuthenticatedError(Exception):
    """NotAuthenticatedError"""


class PiazzaAPI(object):
    """Tiny wrapper around Piazza's Internal API

    Example:
        >>> p = PiazzaAPI("hl5qm84dl4t3x2")
        >>> p.user_auth()
        Email: ...
        Password: ...
        >>> p.get(181)
        ...
        
    :type  network_id: str
    :param network_id: This is the ID of the network (or class) from which
        to query posts
    """
    def __init__(self, network_id):
        self._nid = network_id
        self.base_api_url = 'https://piazza.com/logic/api'
        self.cookies = None

    def user_auth(self, email=None, password=None):
        """Login with email, password and get back a session cookie

        :type  email: str
        :param email: The email used for authentication
        :type  password: str
        :param password: The password used for authentication
        """
        email = raw_input("Email: ") if email is None else email
        password = <PASSWORD>() if password is None else password

        login_url = self.base_api_url
        login_data = {
            "method": "user.login",
            "params": {
                "email": email,
                "pass": password
            }
        }
        login_params = {"method": "user.login"}
        # If the user/password match, the server respond will contain a
        #  session cookie that you can use to authenticate future requests.
        r = requests.post(
            login_url,
            data=json.dumps(login_data),
            params=login_params
        )
        if r.json()["result"] not in ["OK"]:
            raise AuthenticationError(
                "Could not authenticate.\n{}".format(r.json())
            )
        self.cookies = r.cookies

    def demo_auth(self, auth=None, url=None):
        """Authenticate with a "Share Your Class" URL using a demo user.

        You may provide either the entire ``url`` or simply the ``auth`` parameter.

        :param url: Example - "https://piazza.com/demo_login?nid=hbj11a1gcvl1s6&auth=<PASSWORD>"
        :param auth: Example - "<PASSWORD>"
        """
        assert all([
            auth or url,  # Must provide at least one
            not (auth and url)  # Cannot provide more than one
        ])
        if url is None:
            url = "https://piazza.com/demo_login"
            params = dict(nid=self._nid, auth=auth)
            res = requests.get(url, params=params)
        else:
            res = requests.get(url)
        self.cookies = res.cookies

    def get(self, cid, nid=None):
        """Get data from post `cid` in network `nid`

        :type  nid: str
        :param nid: This is the ID of the network (or class) from which
            to query posts. This is optional and only to override the existing
            `network_id` entered when created the class
        :type  cid: str|int
        :param cid: This is the post ID which we grab
        :returns: Python object containing returned data
        """
        if self.cookies is None:
            raise NotAuthenticatedError("You must authenticate before making any other requests.")

        nid = nid if nid else self._nid
        content_url = self.base_api_url
        content_params = {"method": "get.content"}
        content_data = {
            "method": "content.get",
            "params": {
                "cid": cid,
                "nid": nid
            }
        }
        return requests.post(
            content_url,
            data=json.dumps(content_data),
            params=content_params,
            cookies=self.cookies
        ).json()

    def enroll_students(self, student_emails, nid=None):
        """Enroll students in a network `nid`

        :type  student_emails: list of str
        :param student_emails: A listing of email addresses to enroll
            in the network (or class). This can be a list of length one.
        :type  nid: str
        :param nid: This is the ID of the network to add students
            to. This is optional and only to override the existing
            `network_id` entered when created the class
        """
        if self.cookies is None:
            raise NotAuthenticatedError("You must authenticate before making any other requests.")

        nid = nid if nid else self._nid

        content_url = self.base_api_url
        content_params = {"method": "network.update"}
        content_data = {
            "method": "network.update",
            "params": {
                "id": nid,
                "from": "ClassSettingsPage",
                "add_students": json.dump(student_emails)
            }
        }

        return requests.post(
            content_url,
            data=json.dumps(content_data),
            params=content_params,
            cookies=self.cookies
        ).json()

<commit_msg>fix typo :poop:<commit_after>import requests
import json
import getpass


class AuthenticationError(Exception):
    """AuthenticationError"""


class NotAuthenticatedError(Exception):
    """NotAuthenticatedError"""


class PiazzaAPI(object):
    """Tiny wrapper around Piazza's Internal API

    Example:
        >>> p = PiazzaAPI("hl5qm84dl4t3x2")
        >>> p.user_auth()
        Email: ...
        Password: ...
        >>> p.get(181)
        ...
        
    :type  network_id: str
    :param network_id: This is the ID of the network (or class) from which
        to query posts
    """
    def __init__(self, network_id):
        self._nid = network_id
        self.base_api_url = 'https://piazza.com/logic/api'
        self.cookies = None

    def user_auth(self, email=None, password=None):
        """Login with email, password and get back a session cookie

        :type  email: str
        :param email: The email used for authentication
        :type  password: str
        :param password: The password used for authentication
        """
        email = raw_input("Email: ") if email is None else email
        password = get<PASSWORD>() if password is None else password

        login_url = self.base_api_url
        login_data = {
            "method": "user.login",
            "params": {
                "email": email,
                "pass": password
            }
        }
        login_params = {"method": "user.login"}
        # If the user/password match, the server respond will contain a
        #  session cookie that you can use to authenticate future requests.
        r = requests.post(
            login_url,
            data=json.dumps(login_data),
            params=login_params
        )
        if r.json()["result"] not in ["OK"]:
            raise AuthenticationError(
                "Could not authenticate.\n{}".format(r.json())
            )
        self.cookies = r.cookies

    def demo_auth(self, auth=None, url=None):
        """Authenticate with a "Share Your Class" URL using a demo user.

        You may provide either the entire ``url`` or simply the ``auth`` parameter.

        :param url: Example - "https://piazza.com/demo_login?nid=hbj11a1gcvl1s6&auth=<PASSWORD>"
        :param auth: Example - "<PASSWORD>"
        """
        assert all([
            auth or url,  # Must provide at least one
            not (auth and url)  # Cannot provide more than one
        ])
        if url is None:
            url = "https://piazza.com/demo_login"
            params = dict(nid=self._nid, auth=auth)
            res = requests.get(url, params=params)
        else:
            res = requests.get(url)
        self.cookies = res.cookies

    def get(self, cid, nid=None):
        """Get data from post `cid` in network `nid`

        :type  nid: str
        :param nid: This is the ID of the network (or class) from which
            to query posts. This is optional and only to override the existing
            `network_id` entered when created the class
        :type  cid: str|int
        :param cid: This is the post ID which we grab
        :returns: Python object containing returned data
        """
        if self.cookies is None:
            raise NotAuthenticatedError("You must authenticate before making any other requests.")

        nid = nid if nid else self._nid
        content_url = self.base_api_url
        content_params = {"method": "get.content"}
        content_data = {
            "method": "content.get",
            "params": {
                "cid": cid,
                "nid": nid
            }
        }
        return requests.post(
            content_url,
            data=json.dumps(content_data),
            params=content_params,
            cookies=self.cookies
        ).json()

    def enroll_students(self, student_emails, nid=None):
        """Enroll students in a network `nid`

        :type  student_emails: list of str
        :param student_emails: A listing of email addresses to enroll
            in the network (or class). This can be a list of length one.
        :type  nid: str
        :param nid: This is the ID of the network to add students
            to. This is optional and only to override the existing
            `network_id` entered when created the class
        """
        if self.cookies is None:
            raise NotAuthenticatedError("You must authenticate before making any other requests.")

        nid = nid if nid else self._nid

        content_url = self.base_api_url
        content_params = {"method": "network.update"}
        content_data = {
            "method": "network.update",
            "params": {
                "id": nid,
                "from": "ClassSettingsPage",
                "add_students": json.dumps(student_emails)
            }
        }

        return requests.post(
            content_url,
            data=json.dumps(content_data),
            params=content_params,
            cookies=self.cookies
        ).json()


{'fraction_non_alphanumeric': 0.09188242164687561, 'fraction_numerical': 0.002725326065797158, 'mean_word_length': 1.708937516477722, 'pattern_counts': {'":': 32, '<': 9, '<?xml version=': 0, '>': 27, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2793438', 'n_tokens_mistral': 2981, 'n_tokens_neox': 2721, 'n_words': 882}