Example #1
0
 def test_svg(self):
     def mock_open(name, mode):
         self.assertEqual(mode, "rb")
         return stream
     
     class MockOle:
         def __init__(ole, file):
             self.assertIs(file, stream)
             super().__init__()
         
         def openstream(ole, name):
             self.assertEqual(name, "FileHeader")
             return stream
     
     class mock_os:
         def stat(fileno):
             return None
     
     stream = BytesIO()
     stream.fileno = lambda: stream
     
     sch = (
         b"\x00",
         b"|RECORD=31|FONTIDCOUNT=1|SIZE1=10|FONTNAME1=Times New Roman"
             b"|SYSTEMFONT=1"
             b"|AREACOLOR=16317695|BORDERON=T|CUSTOMX=|CUSTOMY="
             b"|DISPLAY_UNIT=4|HOTSPOTGRIDON=T|HOTSPOTGRIDSIZE="
             b"|SNAPGRIDON=T|SNAPGRIDSIZE=|VISIBLEGRIDON=T"
             b"|VISIBLEGRIDSIZE=10|ISBOC=T|SHEETNUMBERSPACESIZE=4"
             b"|USEMBCS=T\x00",
         b"|RECORD=15|LOCATION.X=100|LOCATION.Y=200|XSIZE=40|YSIZE=30"
             b"|COLOR=7846673|AREACOLOR=3381725|ISSOLID=T|OWNERPARTID=-1"
             b"|UNIQUEID=\x00",
     )
     for list in sch:
         stream.write(len(list).to_bytes(4, "little"))
         stream.write(list)
     stream.seek(0)
     
     output = StringIO()
     with patch("altium.open", mock_open), \
             patch("altium.OleFileIO", MockOle), \
             patch("altium.os", mock_os), \
             redirect_stdout(output):
         altium.convert("dummy.SchDoc", svg.Renderer)
     
     output = XML(output.getvalue())
     SVG = "{http://www.w3.org/2000/svg}"
     
     self.assertEqual(output.tag, SVG + "svg")
     for [dimension, expected] in (("width", 11.506), ("height", 7.606)):
         with self.subTest(dimension):
             value = output.get(dimension)
             self.assertTrue(value.endswith("in"))
             self.assertAlmostEqual(float(value[:-2]), expected, 3)
     for [name, value] in (
         ("viewBox", "-0.3,-760.3 1150.6,760.6"),
         ("stroke-width", "1"),
     ):
         with self.subTest(name):
             self.assertEqual(output.get(name), value)
     
     [style, defs, border, sheet] = output
     self.assertEqual(style.tag, SVG + "style")
     self.assertEqual(defs.tag, SVG + "defs")
     self.assertEqual(border.tag, SVG + "g")
     self.assertCountEqual(border.items(), (
         ("transform", "translate(0, -760)"),
     ))
     
     self.assertEqual(sheet.tag, SVG + "rect")
     self.assertCountEqual(sheet.items(), (
         ("transform",  "translate(100, -200)"),
         ("width", "40"), ("height", "30"),
         ("stroke-width", "0.6"), ("class", "solid"),
         ("style", "fill: #DD9933; stroke: #11BB77"),
     ))
Example #2
0
    def request(self, method, url, body=None, headers=None, credentials=None,
                num_redirects=0):
        if url in self.perm_redirects:
            url = self.perm_redirects[url]
        method = method.upper()

        if headers is None:
            headers = {}
        headers.setdefault('Accept', 'application/json')
        headers['User-Agent'] = self.user_agent

        cached_resp = None
        if method in ('GET', 'HEAD'):
            cached_resp = self.cache.get(url)
            if cached_resp is not None:
                etag = cached_resp[1].get('etag')
                if etag:
                    headers['If-None-Match'] = etag

        if body is None:
            headers.setdefault('Content-Length', '0')
        else:
            if isinstance(body, str):
                body = body.encode('utf-8')
            elif isinstance(body, (dict, list, tuple)):
                body = json.encode(body).encode('utf-8')
                headers.setdefault('Content-Type', 'application/json')
            if isinstance(body, bytes):
                headers.setdefault('Content-Length', str(len(body)))
            else:
                headers['Transfer-Encoding'] = 'chunked'

        authorization = basic_auth(credentials)
        if authorization:
            headers['Authorization'] = authorization

        path_query = urlunsplit(('', '') + urlsplit(url)[2:4] + ('',))
        conn = self._get_connection(url)

        def _try_request_with_retries(retries):
            while True:
                try:
                    return _try_request()
                except socket.error as e:
                    ecode = e.args[0]
                    if ecode not in self.retryable_errors:
                        raise
                    try:
                        delay = next(retries)
                    except StopIteration:
                        # No more retries, raise last socket error.
                        raise e
                    time.sleep(delay)
                    conn.close()

        def _try_request():
            try:
                conn.putrequest(method, path_query, skip_accept_encoding=True)
                for header in headers:
                    conn.putheader(header, headers[header])
                conn.endheaders()
                if body is not None:
                    if isinstance(body, str):
                        conn.send(body.encode('utf-8'))
                    elif isinstance(body, bytes):
                        conn.send(body)
                    else: # assume a file-like object and send in chunks
                        while True:
                            chunk = body.read(CHUNK_SIZE)
                            encoding = getattr(body, 'encoding') or 'utf-8'
                            if not chunk:
                                break
                            conn.send(b''.join(
                                map(lambda item: item.encode(encoding),
                                    ['%x\r\n' % len(chunk), chunk, '\r\n'])
                            ))
                        conn.send(b'0\r\n\r\n')
                return conn.getresponse()
            except BadStatusLine as e:
                # httplib raises a BadStatusLine when it cannot read the status
                # line saying, "Presumably, the server closed the connection
                # before sending a valid response."
                # Raise as ECONNRESET to simplify retry logic.
                if e.line == '' or e.line == "''":
                    raise socket.error(errno.ECONNRESET)
                else:
                    raise

        resp = _try_request_with_retries(iter(self.retry_delays))
        status = resp.status

        # Handle conditional response
        if status == 304 and method in ('GET', 'HEAD'):
            resp.read()
            self._return_connection(url, conn)
            status, msg, data = cached_resp
            if data is not None:
                data = StringIO(data)
            return status, msg, data
        elif cached_resp:
            del self.cache[url]

        # Handle redirects
        if status == 303 or \
                method in ('GET', 'HEAD') and status in (301, 302, 307):
            resp.read()
            self._return_connection(url, conn)
            if num_redirects > self.max_redirects:
                raise RedirectLimit('Redirection limit exceeded')
            location = resp.getheader('location')
            if status == 301:
                self.perm_redirects[url] = location
            elif status == 303:
                method = 'GET'
            return self.request(method, location, body, headers,
                                num_redirects=num_redirects + 1)

        data = None
        streamed = False

        # Read the full response for empty responses so that the connection is
        # in good state for the next request
        if method == 'HEAD' or resp.headers.get('content-length') == '0' or \
                status < 200 or status in (204, 304):
            resp.read()
            self._return_connection(url, conn)

        # Buffer small non-JSON response bodies
        elif int(resp.headers.get('content-length', sys.maxsize)) < CHUNK_SIZE:
            data = resp.read().decode('utf-8')
            self._return_connection(url, conn)

        # For large or chunked response bodies, do not buffer the full body,
        # and instead return a minimal file-like object
        else:
            data = ResponseBody(resp,
                                lambda: self._return_connection(url, conn))
            streamed = True

        # Handle errors
        if status >= 400:
            ctype = resp.headers.get('content-type')
            if data is not None and 'application/json' in ctype:
                data = json.decode(data)
                error = data.get('error'), data.get('reason')
            elif method != 'HEAD':
                error = resp.read()
                self._return_connection(url, conn)
            else:
                error = ''
            if status == 401:
                raise Unauthorized(error)
            elif status == 404:
                raise ResourceNotFound(error)
            elif status == 409:
                raise ResourceConflict(error)
            elif status == 412:
                raise PreconditionFailed(error)
            else:
                raise ServerError((status, error))

        # Store cachable responses
        if not streamed and method == 'GET' and 'etag' in resp.msg:
            self.cache[url] = (status, resp.msg, data)
            if len(self.cache) > CACHE_SIZE[1]:
                self._clean_cache()

        if not streamed and data is not None:
            data = StringIO(data)

        return status, resp.msg, data
Example #3
0
def download_subst(date):
    settings = Settings.objects.all()[0]
    params = {'gpid': settings.gpid,
              'gsh': settings.gsh,
              'action': 'switch',
              'date': date,
              '_LJSL': '2052'}
    serverResponse = url_request('https://lo3gdynia.edupage.org/gcall',
                                 {'Cookie': 'PHPSESSID=' + settings.phpsessid},
                                 params).read().decode('UTF-8')
    log.debug(serverResponse)

    jsdb_start = serverResponse.index('ttdb.fill({') + 10
    jsdb = serverResponse[jsdb_start: serverResponse.find('"}}});', jsdb_start) + 4]
    jsdb = StringIO(jsdb)
    jsdb = json.load(jsdb)

    teachers = jsdb.get('teachers', {})
    classes = jsdb.get('classes', {})
    subjects = jsdb.get('subjects', {})
    classrooms = jsdb.get('classrooms', {})
    periods = jsdb.get('periods', {})
    subType = jsdb.get('substitution_types', {})
    breaks = jsdb.get('breaks', {})

    for i in ['teachers', 'classes', 'subjects', 'classrooms', 'periods', 'breaks']:
        exec(i + '["None"] = ""')

    # Pobieranie czerwonej notatki
    try:
        note_start = serverResponse.index('.innerHTML="', serverResponse.index('.innerHTML="') + 1) + len(
            '.indexHTML="')
        note = serverResponse[note_start: jsdb_start - 10]
        note = note[0: note.index('";gi')]
        note = note.replace('\\n', '')
        note = note.replace('\\"', '"')
        note = note.replace('<br /> <br />', '<br />')
    except ValueError:
        note = ""

    subst = serverResponse[serverResponse.find('dt.DataSource(') + 14:serverResponse.find(');var dt = new')]
    subst = StringIO(subst)
    subst = json.load(subst)

    # zastepstwa = []
    zastepstwa = {}

    for zastepstwo in subst:
        status = {'new_przedmiot': [],
                  'new_nauczyciel': [],
                  'old_nauczyciel': [],
                  'old_przedmiot': [],
                  'new_sala': [],
                  'old_sala': [],
                  'old_klasa': [],
                  'new_klasa': [],
                  'przedmiot': [],
                  'lekcja': [],
                  'notka': '',
                  'klasa': [], }
        for key in zastepstwo:
            if key == 'cancelled':
                status['anulowano'] = zastepstwo[key]
            elif key == 'note':
                status['notka'] = zastepstwo[key]
            elif key == 'substitution_typeid':
                status['typ'] = subType.get(zastepstwo[key], "")
            elif key == 'period':
                if type(periods) is list:
                    status['lekcja'] = periods[int(zastepstwo[key])]
                elif type(periods) is str:
                    status['lekcja'] = zastepstwo[key]
                else:
                    status['lekcja'] = periods.get(zastepstwo[key], 'None')

            elif key == 'subjectid':
                status['przedmiot'] = [subjects[str(zastepstwo[key])]]
            elif key == 'subjectids':
                status['przedmiot'] = [subjects[str(s)] for s in zastepstwo[key]]

            elif key == 'teacherid':
                status['nauczyciel'] = [teachers[str(zastepstwo[key])]]
            elif key == 'teacherids':
                status['nauczyciel'] = [teachers[str(s)] for s in zastepstwo[key]]

            elif key == 'classid':
                status['klasa'] = [classes[str(zastepstwo[key])]]
            elif key == 'classids':
                status['klasa'] = [classes[str(s)] for s in zastepstwo[key]]

            elif key == 'classroomid':
                status['sala'] = [classrooms[str(zastepstwo[key])]]
            elif key == 'classroomids':
                status['sala'] = [classrooms[str(s)] for s in zastepstwo[key]]

            elif key == 'changes':
                for z in zastepstwo[key]:
                    if z['column'] == 'teacherid' or z['column'] == 'teacherids':
                        status['old_nauczyciel'].append(teachers[str(z.get('old'))])

                        n = teachers.get(str(z.get('new')))
                        if n not in [None, '']:
                            status['new_nauczyciel'].append(n)
                    elif z['column'] == 'classroomid' or z['column'] == 'classroomids':
                        status['old_sala'].append(classrooms[str(z.get('old'))])
                        s = classrooms.get(str(z.get('new')))
                        if s not in [None, '']:
                            status['new_sala'].append(s)
                    elif z['column'] == 'subjectid' or z['column'] == 'subjectids':
                        status['old_przedmiot'].append(subjects[str(z.get('old'))])

                        p = subjects.get(str(z.get('new')))
                        if p not in [None, '']:
                            status['new_przedmiot'].append(p)
                    elif z['column'] == 'classid' or z['column'] == 'classids':
                        status['old_klasa'].append(classes[str(z.get('old'))])

                        c = classes.get(str(z.get('new')))
                        if c is not None:
                            status['new_klasa'].append(c)

        log.debug('Klasa: ' + str(status.get('klasa', 'None')) + '\t' + 'Lekcja: ' + str(
            status.get('lekcja', 'None')) + '\n' +
                  'Nauczyciel: ' + str(status['nauczyciel']) + ' -> ' + str(status['new_nauczyciel']) + '\n' +
                  'Przedmiot :' + str(status.get('przedmiot', 'None')) + ' -> ' + str(status['new_przedmiot']) + '\n' +
                  'Sala :' + str(status['sala']) + ' -> ' + str(status['new_sala']) + '\n' +
                  'Typ zastępstwa: ' + str(status.get('typ', 'None')) + '\n\n')

        if len(status['klasa']) == 0:
            status['klasa'].append({'name': ''})

        status['przerwa'] = breaks.get(zastepstwo.get('break'))
        status['klasa'] = sorted(status['klasa'], key=lambda s: s['name'])

        k = ""
        for s in status['klasa']:
            for l in status['old_klasa']:
                if s['name'] == l['name']:
                    k += '<s>' + s['name'] + '</s>, '
                    break
            else:
                k += s['name'] + ', '
        k = k[0:-2]
        status['displayname'] = k

        k = ""
        for s in status['klasa']:
            k += s['name'] + ', '
        k = k[0:-2]
        try:
            zastepstwa[k].append(status)
        except KeyError:
            zastepstwa[k] = [status]
    posortowane = dict(sorted(zastepstwa.items()))
    return {'dane': posortowane, 'notka': note}