{
"info": {
"author": "Jeff Hui",
"author_email": "jeff@jeffhui.net",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2.6",
"Topic :: Software Development :: Libraries"
],
"description": "Overview\n========\n\n``rpi_courses`` is a simple Python_ library for reading and using RPI_'s\ncourse schedule. This has been extracted from YACS_.\n\nIt can parse the `XML files`_ provided on RPI's SIS system and provides a\nprimitive object-oriented API layer to access the course information.\n\nAlso, it provides rudimentary method to computing schedules using constraints.\n\n.. _Python: http://python.org/\n.. _RPI: http://rpi.edu/\n.. _XML files: http://sis.rpi.edu/reg/rocs/\n.. _YACS: https://github.com/jeffh/YACS\n\nUsage\n-----\n\nTo install::\n\n pip install RPICourses\n\nThen you can import it to your python scripts::\n\n from rpi_courses import CourseCatalog, list_sis_files\n\n``list_sis_files`` accepts an optional URL argument, the default url is\nassumed to be \"http://sis.rpi.edu/reg/\". This function expects to\nread an apache-style file listing page. It scrapes all the files listed\nthere that end with a xml file extension and returns the full URLs to those\nfiles::\n\n >>> files = list_sis_files()\n >>> files\n [u'http://sis.rpi.edu/reg/rocs/201001.xml',\n u'http://sis.rpi.edu/reg/rocs/201005.xml',\n u'http://sis.rpi.edu/reg/rocs/201009.xml',\n u'http://sis.rpi.edu/reg/rocs/201101.xml']\n\n\n``CourseCatalog`` is the class that parses and stores all the course info.\n\nThe constructor accepts a BeautifulSoup_ or BeautifulStoneSoup_ instance. You\nreally should use the Stone variant.\n\nBut you don't even need to touch that at all! Just use the static methods::\n\n >>> c = CourseCatalog.from_url(files[-1])\n # wait a bit... and then you own the data, muhahaha!\n\nThere's also ``CourseCatalog.from_stream`` to read from an file-handle-like\nstream; ``CourseCatalog.from_file`` to read from a given file path; and\nfinally ``CourseCatalog.from_xml_str`` to read from a string.\n\nEach one of the static methods will instantiate a BeautifulStoneSoup instance\nbehind the curtains an.\n\nNow there are the following properties to access after parsing:\n\n- ``timestamp`` is the raw timestamp (int) when the xml file was last updated.\n- ``datetime`` is the python Datetime_ object of the raw timestamp.\n- ``year`` the year the xml course catalog refers to.\n- ``month`` the starting month of the semester the course catalog refers to.\n- ``semester`` the english representation of the semester this catalog refers to.\n- ``name`` the SEMESTER and YEAR as a string.\n- ``crosslistings`` a dict mapping a CRN to it's associated CRNs. Related CRNs\n refer to similar classes (ie - same class in different dept).\n- ``courses`` a dict mapping a string of (name, dept, code) to a Course object.\n\nWith the most important being the Course object with contains:\n\n- ``name`` the name of the course.\n- ``dept`` the department code that provides this course.\n- ``num`` the course number the department provides. (e.g. dept + num = \"PHYS 2100\")\n- ``cred`` the credit range the course provides.\n- ``sections`` a collection of sections this course has.\n- ``available_sections`` a collection of sections that are still availble (has seats).\n \nThere is also a ``grade_type`` property, which seems unused. For sections have the following\nproperties:\n\n- ``crn`` the CRN this section refers to.\n- ``seats_taken`` the number of seats already taken.\n- ``seats_total`` the number of seats total for this section..\n- ``num`` the section number.\n- ``periods`` the time periods this section meets.\n- ``notes`` a tuple of notes about the section.\n \nFinally, the periods are instanced that have the following properties:\n\n- ``type`` the type of session.\n- ``instructor`` the instructor that teaches/oversees this period\n- ``start`` the starting time of the period. Times are in military integer format (e.g. - 2100)\n- ``end`` the ending time of the period. Times are in miliary integer format (e.g. - 2100)\n- ``location`` the location of the period.\n- ``int_days`` the collection of days (as integers) which the period meets. 0 is Monday.\n \nBut there are also additional computed properties which aid in analysis of a period:\n\n- ``time_range`` returns a tuple of (start, end) properties\n- ``tba`` returns True if the course's time range is not yet specified (To Be Announced)\n- ``is_lecture`` returns True if the period is a lecture time slot.\n- ``is_studio`` returns True if the period is a studio time slot.\n- ``is_lab`` returns True if the period is a lab time slot.\n- ``is_testing_period`` returns True if the period is test-taking time slot.\n- ``is_recitation`` returns True if the period is a recitation time slot.\n- ``days`` returns a tuple of english-friendly names of int_days.\n \nEach object has a ``conflicts_with`` method to determine of another like object has a time\nconflict.\n\n.. _BeautifulSoup: http://www.crummy.com/software/BeautifulSoup/documentation.html#Parsing HTML\n.. _BeautifulStoneSoup: http://www.crummy.com/software/BeautifulSoup/documentation.html#Parsing XML\n.. _Datetime: http://docs.python.org/library/datetime.html\n\nScheduler\n---------\n\nBesides just fetching courses, you can also generate schedules::\n\n from rpi_schedule import compute_schedules\n # get selected courses\n \n # returns a collection of dictionaries whose keys=courses and values=sections\n compute_schedules(courses)\n \nAlternatively, a you can restrict the time ranges available to compute by passing in\nan iterable of TimeRange objects as the second argument::\n\n from rpi_schedule import compute_schedules, TimeRange\n \n # ensure the schedule has 12pm - 2pm open.\n compute_schedules(courses, (TimeRange(start=1200, end=1400, days=(0,1)),))\n\nUnderneath the hood, ``compute_schedule`` is a simple wrapper to the Scheduler object::\n\n def compute_schedules(courses, excluded_times=(), free_sections_only=True, problem=None, return_generator=False):\n s = Scheduler(free_sections_only, problem)\n s.exclude_times(*tuple(excluded_times))\n return s.find_schedules(courses, return_generator)\n\n\nTODOs\n=====\n\nMajor/Minor Requirements\n------------------------\n\nIf possible, provide some way to access the course requirements for every major. This would\nrequire a massive undertaking.\n\nSolver Optimizations\n--------------------\n\nThe current course solver is a naive implementation. Optimize it by providing more\ndetailed constraints and apply better solver algorithms.\n\nThe solver library has been moved to a `separate library`_.\n\n.. separate library: http://github.com/jeffh/pyconstraints\n\nNotes Analysis\n--------------\n\nThere are a lot of data that can be extracted from the section.notes attribute that\ncould be placed into their own properties for easier & abstracted access.\n\nIdeally, the notes that are properly analyzed should be removed from the notes property.\n\nPrerequisites and Co-requisites\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nAutomatically detect & lookup course prereqs, which are detailed in section NOTES::\n\n PRE-REQ: PHYS 23330 & MATH 4600\n\tPRE-REQ: PHYS 1100 OR 1150 AND PHYS 1200 OR 1250\n\tPRE-REQ: PHYS 2110 OR PHYS 2510, AND MATH 2010 AND MATH 2400\n\tPRE-REQ: STSS 2300 OR PERMISSION OF INSTRUCTOR\n\tPRE-REQ: PHYS 2330 AND MATH 4600\n\tPRE-REQ: BIOL 4620 AND BIOL 4760 OR CHEM 4760 OR BCBP 4760\n\tPRE-REQ: CSCI 2300\n PRE-REQ; INTRODUCTORY COMM OR SOCIAL SCIENCE COURSE\n\tPRE-REQ: ENGR 2250 & ENGR 2530 & CIVL 2670\n\tPRE-REQ: ANY FILM COURSE OR PERMISION OF INSTRUCTOR\n\tPRE-REQ: MANE 4480\n \nThis text needs to be parsed, but relaxed enough to gloss over inconsistencies of the\ntext provided. The API should provide properties in section and course objects to see\ncourse prereqs, the course object needs to filter out duplicates that the collective\nsections would provide.\n\nPrereqs can span multiple lines::\n\n PRE-REQ: PHYS 1100 OR 1150 AND PHYS 1200 OR 1250 \n AND CSCI 1100\n\nCo-requisites are similar to prereqs::\n\n CO-REQ: MANE-4010\n \nThere are a few prereqs that is different:: \n\n\tANY 1000/2000 LEVEL WRITING COURSE\n\tPRE-REQ: ANY WRIT COURSE\n PRE-REQ: ONE WRIT OR COMM COURSEOR ONE COMM INTENSIVE COURSE\n\n\"Meets with\" Courses\n~~~~~~~~~~~~~~~~~~~~~~\n\nAutomatically detect and lookup when a course/section meets with X course::\n\n MEETS WITH PHIL 2961 / COGS 2960\n\tMEETS WITH ERTH 4690/ ENVE 4110\n MEETS WITH PSYC 4967\n MEETS WITH COGS 4960 & CSCI 4969\n\tMEETS WITH ARTS 4010 & ITWS 4961\n\tMEETS WITH BIOL 4710/01\n\tMEETS WITH BIOL 4770, CHEM 4770\n\tMEETS WITH BCBP 4640 & BIOL 4640/6640\n\tMEETS WITH MANE 4750/6830\n\tMEETS WITH CSCI 6960, ITWS 4962/6961, ERTH 4963/6963\n\tMEETS WITHENGR 4100, ITWS 4300/6300\n \nThe good part is that this format is pretty consistent, but harder to parse out the\nspecific course(s). Since more than one course can be listed, the API should support\nmore than one course. A section number may be provided to the other course it meets with.\n\nFulfills requirements\n~~~~~~~~~~~~~~~~~~~~~~~\n\nCertain courses/sections are noted to fulfill a given requirement::\n\n COMMUNICATION INTENSIVE\n\tFULFILLS COMM INTENSIVE REQUIREMENT\n\tCOMM INTENSIVE\n\tFULFILLS EMAC THESIS\n\tFULFILLS EMAC THESIS REQUIREMENT\n \nThis is simple to check, as all are marked identically. There may\nbe an edge case where some (but not all) sections contain this note -- then is\na course communication intensive?\n\nCourse Restrictions\n~~~~~~~~~~~~~~~~~~~\n\nSome courses are restricted by majors or other requirements::\n\n RESTRICTED TO ARCH MAJORS\n\tOPEN TO ALL MAJORS EXCEPT ARCH\n\tRESTRICTED TO EART, EMAC, GSAS MAJORS, OTHERS 12/13\n\tRESTRICTED TO EMAC, COMM, COMM-IT MAJORS\n\tRESTRICTED TO SENIOR CHME MAJORS\n\tRESTRICTED TO HCIN,TCOM, CMRT, ITWS MAJORS\n\tRESTRICTED TO IT MAJORS\n\tRESTRICTED TO COMM, ITWS & EMAC MAJORS\n\tRESTRICTED TO EMAC, EART AND ITWS MAJORS\n\t\nThese are varied and hard to analysis without matching the direct strings. Be careful\nthat some sections make it multi-lined::\n\n RESTRICTED TO EMAC, COMM, COMM-IT, EART,GSAS \n DSIS, IT-ARTS MAJORS\n\nCertain sections are available only to particular students in a particular region::\n\n INDIA STUDENTS ONLY\n\tNYC STUDENTS ONLY\n\tNEW YORK CITY STUDENTS ONLY\n\tINDIA ARCH STUDENTS ONLY\n\tINDIA PROGRAM STUDENTS ONLY\n\tRESTRICTED TO BIAM STUDENTS\n\nThe ones listed above are the only ones found at the time of writing (Jul 25, 2011), but\nauto-detecting others kinds shouldn't be too hard to do. There seems to be only one of these\nper section/course -- so a property that defines this only restriction will suffice.\n\nWait-Listed / By Permission\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis course is waitlisted and requires contacting a designated person::\n\n CONTACT E. LARGE (LARGEE@RPI.EDU) TO BE PUT ON WAITLIST\n\tCONTACT ELIZABETH LARGE (LARGEE@RPI.EDU) TO BE ADDEDTO WAIT LIST\n\t\nThis seems pretty rare -- should wait listed be implemented?\nAlternatively a course may be blocked until approved by some process::\n\n BY AUDITION ONLY\n ENROLLMENT BY PERMISSION OF INSTRUCTOR\n\tPERMISSION OF INSTRUCTOR REQUIRED\n\tPERMISSION OF INSTRUCTOR\n\nRemember that the permission of instructor may also be in a PRE-REQS note::\n\n PRE-REQ; INTRODUCTORY COMM OR SOCIAL SCIENCE COURSEOR PERMISSION OF INSTRUCTOR\n \nSection Availability\n~~~~~~~~~~~~~~~~~~~~\n\nSome courses are available on a particular semester::\n\n COURSE TAUGHT 2ND HALF OF SEMESTER\n\tCOURSE TAUGHT SECOND HALF OF SEMESTER\n\tCOURSE TAUGHT FIRST HALF OF SEMESTER\n\nMiscellaneous \n~~~~~~~~~~~~~\n\nPhD. Courses::\n\n PhD COURSE\n \nThis are listed under the COMMUNICATION INTERNSHIP course::\n\n ORGANIZATIONAL MEETING WED 1/26\n\tORGANIZATIONAL MEETING WED. 1/26/11\n \nThis is listed under the INTERFACE DESIGN course::\n\n KNOWLEDGE OF AUTHORING SOFTWARE FOR \n MULTIMEDIA OR WEB DEVELOPMENT\n\nor::\n\n KNOWLEDGE OF INTERACTICE AUTHORING SOFTWARE\n \nUnder HUMAN-MEDIA INTERACTION:: \n\n\tCOUNTS AS ADVANCED HCI TOPICS\n\nWhat's the point of a location for this section? This is noted in COMPUTER AIDED MACHINE II::\n \n\tCOURSE WILL MEET IN JEC 2323\n\nI don't know what this means (noted under INVENTOR'S STUDIO; SOLAR DEV. &\nENERGY RENEW.; and RADIOLOGICAL ENGINEERING)::\n\n SENIOR STANDING\n\tJUNIOR OR SENIOR STANDING\n\tTHIS SECTION RESTRICTED TO SENIORS\n\tANY 1000/2000 LEVEL WRITING COURSEOR JR/SR STATUS\n \nCourse Continuation? Filed under SENIOR DESIGN PROJECT::\n\n CONTINUATION OF MANE 4380\n\nPast grade requirements (SPACECRAFT ATTITUDE DYNAMICS)::\n\n\tSTUDENTS SHOULD HAVE EARNED AT LEAST A 'B+' IN \n\tMANE 4100 AND MANE 4170 TO REGISTER FOR THIS COURSE\n\t\nSpecific dates the course meets (GLOBAL BUSINESS & SOCIAL RESPO)::\n\n CLASS MEETS ON 12/13, 12/10, 1/3, 1/10 & 1/17",
"description_content_type": null,
"docs_url": null,
"download_url": "UNKNOWN",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://github.com/jeffh/rpi_courses",
"keywords": null,
"license": "MIT",
"maintainer": null,
"maintainer_email": null,
"name": "RPICourses",
"package_url": "https://pypi.org/project/RPICourses/",
"platform": "UNKNOWN",
"project_url": "https://pypi.org/project/RPICourses/",
"project_urls": {
"Download": "UNKNOWN",
"Homepage": "https://github.com/jeffh/rpi_courses"
},
"release_url": "https://pypi.org/project/RPICourses/1.0.9/",
"requires_dist": null,
"requires_python": null,
"summary": "A data scraping library to read course data from RPI.",
"version": "1.0.9"
},
"last_serial": 1308788,
"releases": {
"1.0.0": [
{
"comment_text": "",
"digests": {
"md5": "d54b2bd5cc10a07cc36c36a72982d6e9",
"sha256": "beaf6915b8d95c49effc3d8830f2e78070167d8252362199349d1b6441c6da05"
},
"downloads": -1,
"filename": "RPICourses-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "d54b2bd5cc10a07cc36c36a72982d6e9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31029,
"upload_time": "2012-08-23T03:25:50",
"url": "https://files.pythonhosted.org/packages/a2/69/6b4b2a0c068aaf0f16e828a6dd842dc044cebb88e4e5cc91e891bdf068cc/RPICourses-1.0.0.tar.gz"
}
],
"1.0.1": [
{
"comment_text": "",
"digests": {
"md5": "03f0e3c88c456bfe07dec250a5220aea",
"sha256": "e4fd2a168a6663394769e8cbf3023627b69d1b59de8803f36226490a6f0bf3d3"
},
"downloads": -1,
"filename": "RPICourses-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "03f0e3c88c456bfe07dec250a5220aea",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31057,
"upload_time": "2012-08-23T03:29:55",
"url": "https://files.pythonhosted.org/packages/b9/f6/8e10140aea8ab3c0ab82b4f480a3806de2900baf7175afca52df6bf633e8/RPICourses-1.0.1.tar.gz"
}
],
"1.0.2": [
{
"comment_text": "",
"digests": {
"md5": "4d856087a7ae43491fd3d6f449ce8a15",
"sha256": "84dd42156fb189173c3b1a2fc40869123280d42cccbe707647ba0852d0cfec24"
},
"downloads": -1,
"filename": "RPICourses-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "4d856087a7ae43491fd3d6f449ce8a15",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31422,
"upload_time": "2012-10-13T03:16:59",
"url": "https://files.pythonhosted.org/packages/fd/19/1124ba0abd83f5701cee4b083997664cf664db694738223042292657914f/RPICourses-1.0.2.tar.gz"
}
],
"1.0.3": [
{
"comment_text": "",
"digests": {
"md5": "202fd04573ec516fad1d050e6aee8845",
"sha256": "e9a90af4033d531ff58a8e4885d799a69fde8f2ab5bb43182af3dd1f2714bbfa"
},
"downloads": -1,
"filename": "RPICourses-1.0.3.tar.gz",
"has_sig": false,
"md5_digest": "202fd04573ec516fad1d050e6aee8845",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31483,
"upload_time": "2012-10-13T03:42:44",
"url": "https://files.pythonhosted.org/packages/b8/63/ea01fa16a06076dfffdfff1ed9ad4f959f415faca50788b3260dc1fcb9d6/RPICourses-1.0.3.tar.gz"
}
],
"1.0.4": [
{
"comment_text": "",
"digests": {
"md5": "44879f7cfd41e9f413371c5885303c24",
"sha256": "d4c3f57ac43240655bf0556128d3980dc5c7bc9997270b327ab273ac34044dc9"
},
"downloads": -1,
"filename": "RPICourses-1.0.4.tar.gz",
"has_sig": false,
"md5_digest": "44879f7cfd41e9f413371c5885303c24",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31528,
"upload_time": "2012-10-13T04:09:47",
"url": "https://files.pythonhosted.org/packages/80/63/e90bf674ca9ec9060c25f52aa68dd2f91956739630f8d03f65ae9e9eff33/RPICourses-1.0.4.tar.gz"
}
],
"1.0.5": [
{
"comment_text": "",
"digests": {
"md5": "45e08cb79871cfa0e3126bd7a704446b",
"sha256": "6360231c26340dcbe57cc1fb1bd05ec772d3c7aac405624f452daae0f8cd3e60"
},
"downloads": -1,
"filename": "RPICourses-1.0.5.tar.gz",
"has_sig": false,
"md5_digest": "45e08cb79871cfa0e3126bd7a704446b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31529,
"upload_time": "2012-10-13T04:20:50",
"url": "https://files.pythonhosted.org/packages/82/f6/c14ee4864228bb1c2cf0cdf471eab6dfd95f95cdf3fccf81cd8af967a07a/RPICourses-1.0.5.tar.gz"
}
],
"1.0.6": [
{
"comment_text": "",
"digests": {
"md5": "925b8a2f4f7450ce21ba57dce87a1105",
"sha256": "4672ddcaa9fca1468347d52c045af2b7f16425b8f0102fefbb60655cec6bcebb"
},
"downloads": -1,
"filename": "RPICourses-1.0.6.tar.gz",
"has_sig": false,
"md5_digest": "925b8a2f4f7450ce21ba57dce87a1105",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31597,
"upload_time": "2013-03-06T03:07:42",
"url": "https://files.pythonhosted.org/packages/c9/c9/6034c38fd64a666a8d14e544ade1bfd79e486d575cafd22accf94af036ad/RPICourses-1.0.6.tar.gz"
}
],
"1.0.7": [
{
"comment_text": "",
"digests": {
"md5": "da3b24ca8fcf4e940c7c4d1cacff0580",
"sha256": "a97be5e2fc08b97189bf7c470ef1b908f15553ce3226a0bb8b90abc0964c9bd9"
},
"downloads": -1,
"filename": "RPICourses-1.0.7.tar.gz",
"has_sig": false,
"md5_digest": "da3b24ca8fcf4e940c7c4d1cacff0580",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31645,
"upload_time": "2013-10-10T04:51:55",
"url": "https://files.pythonhosted.org/packages/aa/6e/06d8e0e89016a4b8174a21cf2fba2fdd9520f2c19ce9471384615140519d/RPICourses-1.0.7.tar.gz"
}
],
"1.0.8": [
{
"comment_text": "",
"digests": {
"md5": "35c8c466c852abec0052465df2c16800",
"sha256": "059d03e439cd3d11582ab6513daea89539db45bf23d8f2fc502105173b7b1379"
},
"downloads": -1,
"filename": "RPICourses-1.0.8.tar.gz",
"has_sig": false,
"md5_digest": "35c8c466c852abec0052465df2c16800",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31658,
"upload_time": "2014-03-10T05:46:34",
"url": "https://files.pythonhosted.org/packages/54/47/aaf8a7f13c7ce060485c903b0bbda4d1427291d789182717a3b58ff3eafe/RPICourses-1.0.8.tar.gz"
}
],
"1.0.9": [
{
"comment_text": "",
"digests": {
"md5": "f71875ebca5b142fc73ed8246f80adcb",
"sha256": "a34fc0de19f86064d7190270d6b6c95d4e6a6b631f611d42f6c86c0226744054"
},
"downloads": -1,
"filename": "RPICourses-1.0.9.tar.gz",
"has_sig": false,
"md5_digest": "f71875ebca5b142fc73ed8246f80adcb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31682,
"upload_time": "2014-11-16T10:46:18",
"url": "https://files.pythonhosted.org/packages/e5/fa/a18d4752bd09457e795e5395371338f82c8bb88c132a02cd45e2e315aca2/RPICourses-1.0.9.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "f71875ebca5b142fc73ed8246f80adcb",
"sha256": "a34fc0de19f86064d7190270d6b6c95d4e6a6b631f611d42f6c86c0226744054"
},
"downloads": -1,
"filename": "RPICourses-1.0.9.tar.gz",
"has_sig": false,
"md5_digest": "f71875ebca5b142fc73ed8246f80adcb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 31682,
"upload_time": "2014-11-16T10:46:18",
"url": "https://files.pythonhosted.org/packages/e5/fa/a18d4752bd09457e795e5395371338f82c8bb88c132a02cd45e2e315aca2/RPICourses-1.0.9.tar.gz"
}
]
}