def test_regression_7110(self): """ Regression test for bug #7110. When using select_related(), we must query the Device and Building tables using two different aliases (each) in order to differentiate the start and end Connection fields. The net result is that both the "connections = ..." queries here should give the same results without pulling in more than the absolute minimum number of tables (history has shown that it's easy to make a mistake in the implementation and include some unnecessary bonus joins). """ b=Building.objects.create(name='101') dev1=Device.objects.create(name="router", building=b) dev2=Device.objects.create(name="switch", building=b) dev3=Device.objects.create(name="server", building=b) port1=Port.objects.create(port_number='4',device=dev1) port2=Port.objects.create(port_number='7',device=dev2) port3=Port.objects.create(port_number='1',device=dev3) c1=Connection.objects.create(start=port1, end=port2) c2=Connection.objects.create(start=port2, end=port3) connections=Connection.objects.filter(start__device__building=b, end__device__building=b).order_by('id') self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections], [(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')]) connections=Connection.objects.filter(start__device__building=b, end__device__building=b).select_related().order_by('id') self.assertEqual([(c.id, six.text_type(c.start), six.text_type(c.end)) for c in connections], [(c1.id, 'router/4', 'switch/7'), (c2.id, 'switch/7', 'server/1')]) # This final query should only have seven tables (port, device and building # twice each, plus connection once). Thus, 6 joins plus the FROM table. self.assertEqual(str(connections.query).count(" JOIN "), 6)
def date_error_message(self, lookup_type, field, unique_for): opts = self._meta return _("%(field_name)s must be unique for %(date_field)s %(lookup)s.") % { "field_name": six.text_type(capfirst(opts.get_field(field).verbose_name)), "date_field": six.text_type(capfirst(opts.get_field(unique_for).verbose_name)), "lookup": lookup_type, }
def test_change_form_deletion_when_invalid(self): """ Make sure that a change form that is filled out, but marked for deletion doesn't cause validation errors. """ PoemFormSet = inlineformset_factory(Poet, Poem, can_delete=True) poet = Poet.objects.create(name='test') poem = poet.poem_set.create(name='test poem') data = { 'poem_set-TOTAL_FORMS': '1', 'poem_set-INITIAL_FORMS': '1', 'poem_set-MAX_NUM_FORMS': '0', 'poem_set-0-id': six.text_type(poem.id), 'poem_set-0-poem': six.text_type(poem.id), 'poem_set-0-name': 'x' * 1000, } formset = PoemFormSet(data, instance=poet) # Make sure this form doesn't pass validation. self.assertEqual(formset.is_valid(), False) self.assertEqual(Poem.objects.count(), 1) # Then make sure that it *does* pass validation and delete the object, # even though the data isn't actually valid. data['poem_set-0-DELETE'] = 'on' formset = PoemFormSet(data, instance=poet) self.assertEqual(formset.is_valid(), True) formset.save() self.assertEqual(Poem.objects.count(), 0)
def test_intermeiary(self): r1 = Reporter.objects.create(first_name="John", last_name="Smith") r2 = Reporter.objects.create(first_name="Jane", last_name="Doe") a = Article.objects.create( headline="This is a test", pub_date=datetime(2005, 7, 27) ) w1 = Writer.objects.create(reporter=r1, article=a, position="Main writer") w2 = Writer.objects.create(reporter=r2, article=a, position="Contributor") self.assertQuerysetEqual( a.writer_set.select_related().order_by("-position"), [ ("John Smith", "Main writer"), ("Jane Doe", "Contributor"), ], lambda w: (six.text_type(w.reporter), w.position) ) self.assertEqual(w1.reporter, r1) self.assertEqual(w2.reporter, r2) self.assertEqual(w1.article, a) self.assertEqual(w2.article, a) self.assertQuerysetEqual( r1.writer_set.all(), [ ("John Smith", "Main writer") ], lambda w: (six.text_type(w.reporter), w.position) )
def test_abstract(self): # The Student and Worker models both have 'name' and 'age' fields on # them and inherit the __unicode__() method, just as with normal Python # subclassing. This is useful if you want to factor out common # information for programming purposes, but still completely # independent separate models at the database level. w1 = Worker.objects.create(name="Fred", age=35, job="Quarry worker") w2 = Worker.objects.create(name="Barney", age=34, job="Quarry worker") s = Student.objects.create(name="Pebbles", age=5, school_class="1B") self.assertEqual(six.text_type(w1), "Worker Fred") self.assertEqual(six.text_type(s), "Student Pebbles") # The children inherit the Meta class of their parents (if they don't # specify their own). self.assertQuerysetEqual( Worker.objects.values("name"), [ {"name": "Barney"}, {"name": "Fred"}, ], lambda o: o ) # Since Student does not subclass CommonInfo's Meta, it has the effect # of completely overriding it. So ordering by name doesn't take place # for Students. self.assertEqual(Student._meta.ordering, []) # However, the CommonInfo class cannot be used as a normal model (it # doesn't exist as a model). self.assertRaises(AttributeError, lambda: CommonInfo.objects.all()) # A StudentWorker which does not exist is both a Student and Worker # which does not exist. self.assertRaises(Student.DoesNotExist, StudentWorker.objects.get, pk=12321321 ) self.assertRaises(Worker.DoesNotExist, StudentWorker.objects.get, pk=12321321 ) # MultipleObjectsReturned is also inherited. # This is written out "long form", rather than using __init__/create() # because of a bug with diamond inheritance (#10808) sw1 = StudentWorker() sw1.name = "Wilma" sw1.age = 35 sw1.save() sw2 = StudentWorker() sw2.name = "Betty" sw2.age = 24 sw2.save() self.assertRaises(Student.MultipleObjectsReturned, StudentWorker.objects.get, pk__lt=sw2.pk + 100 ) self.assertRaises(Worker.MultipleObjectsReturned, StudentWorker.objects.get, pk__lt=sw2.pk + 100 )
def test_overriding_prefetch(self): with self.assertNumQueries(3): qs = Author.objects.prefetch_related('books', 'books__read_by') lists = [[[six.text_type(r) for r in b.read_by.all()] for b in a.books.all()] for a in qs] self.assertEqual(lists, [ [["Amy"], ["Belinda"]], # Charlotte - Poems, Jane Eyre [["Amy"]], # Anne - Poems [["Amy"], []], # Emily - Poems, Wuthering Heights [["Amy", "Belinda"]], # Jane - Sense and Sense ]) with self.assertNumQueries(3): qs = Author.objects.prefetch_related('books__read_by', 'books') lists = [[[six.text_type(r) for r in b.read_by.all()] for b in a.books.all()] for a in qs] self.assertEqual(lists, [ [["Amy"], ["Belinda"]], # Charlotte - Poems, Jane Eyre [["Amy"]], # Anne - Poems [["Amy"], []], # Emily - Poems, Wuthering Heights [["Amy", "Belinda"]], # Jane - Sense and Sense ])
def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'): """ Similar to smart_bytes, except that lazy instances are resolved to strings, rather than kept as lazy objects. If strings_only is True, don't convert (some) non-string-like objects. """ if isinstance(s, bytes): if encoding == 'utf-8': return s else: return s.decode('utf-8', errors).encode(encoding, errors) if strings_only and (s is None or isinstance(s, int)): return s if isinstance(s, Promise): return six.text_type(s).encode(encoding, errors) if not isinstance(s, six.string_types): try: if six.PY3: return six.text_type(s).encode(encoding) else: return bytes(s) except UnicodeEncodeError: if isinstance(s, Exception): # An Exception subclass containing non-ASCII data that doesn't # know how to print itself properly. We shouldn't raise a # further exception. return ' '.join([force_bytes(arg, encoding, strings_only, errors) for arg in s]) return six.text_type(s).encode(encoding, errors) else: return s.encode(encoding, errors)
def get_initkwargs(cls, form_list, initial_dict=None, instance_dict=None, condition_dict=None, *args, **kwargs): """ Creates a dict with all needed parameters for the form wizard instances. * `form_list` - is a list of forms. The list entries can be single form classes or tuples of (`step_name`, `form_class`). If you pass a list of forms, the wizardview will convert the class list to (`zero_based_counter`, `form_class`). This is needed to access the form for a specific step. * `initial_dict` - contains a dictionary of initial data dictionaries. The key should be equal to the `step_name` in the `form_list` (or the str of the zero based counter - if no step_names added in the `form_list`) * `instance_dict` - contains a dictionary whose values are model instances if the step is based on a ``ModelForm`` and querysets if the step is based on a ``ModelFormSet``. The key should be equal to the `step_name` in the `form_list`. Same rules as for `initial_dict` apply. * `condition_dict` - contains a dictionary of boolean values or callables. If the value of for a specific `step_name` is callable it will be called with the wizardview instance as the only argument. If the return value is true, the step's form will be used. """ kwargs.update({ 'initial_dict': initial_dict or {}, 'instance_dict': instance_dict or {}, 'condition_dict': condition_dict or {}, }) init_form_list = SortedDict() assert len(form_list) > 0, 'at least one form is needed' # walk through the passed form list for i, form in enumerate(form_list): if isinstance(form, (list, tuple)): # if the element is a tuple, add the tuple to the new created # sorted dictionary. init_form_list[six.text_type(form[0])] = form[1] else: # if not, add the form with a zero based counter as unicode init_form_list[six.text_type(i)] = form # walk through the new created list of forms for form in six.itervalues(init_form_list): if issubclass(form, formsets.BaseFormSet): # if the element is based on BaseFormSet (FormSet/ModelFormSet) # we need to override the form variable. form = form.form # check if any form contains a FileField, if yes, we need a # file_storage added to the wizardview (by subclassing). for field in six.itervalues(form.base_fields): if (isinstance(field, forms.FileField) and not hasattr(cls, 'file_storage')): raise NoFileStorageConfigured # build the kwargs for the wizardview instances kwargs['form_list'] = init_form_list return kwargs
def test_pickle_complex(self): # See ticket #16563 x = SimpleLazyObject(complex_object) pickled = pickle.dumps(x) unpickled = pickle.loads(pickled) self.assertEqual(unpickled, x) self.assertEqual(six.text_type(unpickled), six.text_type(x)) self.assertEqual(unpickled.name, x.name)
def __str__(self): """ Returns the string representation. If GDAL is installed, it will be 'pretty' OGC WKT. """ try: return six.text_type(self.srs) except: return six.text_type(self.wkt)
def force_text(s, encoding='utf-8', strings_only=False, errors='strict'): """ Similar to smart_text, except that lazy instances are resolved to strings, rather than kept as lazy objects. If strings_only is True, don't convert (some) non-string-like objects. """ # Handle the common case first, saves 30-40% when s is an instance of # six.text_type. This function gets called often in that setting. if isinstance(s, six.text_type): return s if strings_only and is_protected_type(s): return s try: if not isinstance(s, six.string_types): if hasattr(s, '__unicode__'): s = s.__unicode__() else: try: if six.PY3: if isinstance(s, bytes): s = six.text_type(s, encoding, errors) else: s = six.text_type(s) else: s = six.text_type(bytes(s), encoding, errors) except UnicodeEncodeError: if not isinstance(s, Exception): raise # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII data without special # handling to display as a string. We need to handle this # without raising a further exception. We do an # approximation to what the Exception's standard str() # output should be. s = ' '.join([force_text(arg, encoding, strings_only, errors) for arg in s]) else: # Note: We use .decode() here, instead of six.text_type(s, encoding, # errors), so that if s is a SafeBytes, it ends up being a # SafeText at the end. s = s.decode(encoding, errors) except UnicodeDecodeError as e: if not isinstance(s, Exception): raise DjangoUnicodeDecodeError(s, *e.args) else: # If we get to here, the caller has passed in an Exception # subclass populated with non-ASCII bytestring data without a # working unicode method. Try to handle this without raising a # further exception by individually forcing the exception args # to unicode. s = ' '.join([force_text(arg, encoding, strings_only, errors) for arg in s]) return s
def linenumbers(value, autoescape=None): """Displays text with line numbers.""" lines = value.split('\n') # Find the maximum width of the line count, for use with zero padding # string format command width = six.text_type(len(six.text_type(len(lines)))) if not autoescape or isinstance(value, SafeData): for i, line in enumerate(lines): lines[i] = ("%0" + width + "d. %s") % (i + 1, line) else: for i, line in enumerate(lines): lines[i] = ("%0" + width + "d. %s") % (i + 1, escape(line)) return mark_safe('\n'.join(lines))
def test_tuple_list_display(self): """ Regression test for #17128 (ChangeList failing under Python 2.5 after r16319) """ swallow = Swallow.objects.create( origin='Africa', load='12.34', speed='22.2') model_admin = SwallowAdmin(Swallow, admin.site) superuser = self._create_superuser('superuser') request = self._mocked_authenticated_request('/swallow/', superuser) response = model_admin.changelist_view(request) # just want to ensure it doesn't blow up during rendering self.assertContains(response, six.text_type(swallow.origin)) self.assertContains(response, six.text_type(swallow.load)) self.assertContains(response, six.text_type(swallow.speed))
def make_bytes(value): if isinstance(value, int): value = six.text_type(value) if isinstance(value, six.text_type): value = value.encode('ascii') # force conversion to bytes in case chunk is a subclass return bytes(value)
def __mod__(self, rhs): if self._delegate_bytes and not six.PY3: return bytes(self) % rhs elif self._delegate_text: return six.text_type(self) % rhs else: raise AssertionError('__mod__ not supported for non-string types')
def format_organisation_number(gd): if gd['century'] is None: century = '' else: century = gd['century'] return six.text_type(century + gd['year'] + gd['month'] + gd['day'] + gd['serial'] + gd['checksum'])
def test_save_as_new_with_new_inlines(self): """ Existing and new inlines are saved with save_as_new. Regression for #14938. """ efnet = Network.objects.create(name="EFNet") host1 = Host.objects.create(hostname="irc.he.net", network=efnet) HostFormSet = inlineformset_factory(Network, Host) # Add a new host, modify previous host, and save-as-new data = { 'host_set-TOTAL_FORMS': '2', 'host_set-INITIAL_FORMS': '1', 'host_set-MAX_NUM_FORMS': '0', 'host_set-0-id': six.text_type(host1.id), 'host_set-0-hostname': 'tranquility.hub.dal.net', 'host_set-1-hostname': 'matrix.de.eu.dal.net' } # To save a formset as new, it needs a new hub instance dalnet = Network.objects.create(name="DALnet") formset = HostFormSet(data, instance=dalnet, save_as_new=True) self.assertTrue(formset.is_valid()) formset.save() self.assertQuerysetEqual( dalnet.host_set.order_by("hostname"), ["<Host: matrix.de.eu.dal.net>", "<Host: tranquility.hub.dal.net>"] )
def get_date_error_message(self, date_check): return ugettext("Please correct the duplicate data for %(field_name)s " "which must be unique for the %(lookup)s in %(date_field)s.") % { 'field_name': date_check[2], 'date_field': date_check[3], 'lookup': six.text_type(date_check[1]), }
def as_table(self): "Returns this formset rendered as HTML <tr>s -- excluding the <table></table>." # XXX: there is no semantic division between forms here, there # probably should be. It might make sense to render each form as a # table row with each field as a td. forms = ' '.join([form.as_table() for form in self]) return mark_safe('\n'.join([six.text_type(self.management_form), forms]))
def test_no_empty_option(self): "If a model's ForeignKey has blank=False and a default, no empty option is created (Refs #10792)." option = ChoiceOptionModel.objects.create(name='default') choices = list(ChoiceFieldForm().fields['choice'].choices) self.assertEqual(len(choices), 1) self.assertEqual(choices[0], (option.pk, six.text_type(option)))
def __next__(self): chunk = next(self._iterator) if isinstance(chunk, int): chunk = six.text_type(chunk) if isinstance(chunk, six.text_type): chunk = chunk.encode(self._charset) # force conversion to bytes in case chunk is a subclass return bytes(chunk)
def simple_unlimited_args_kwargs(one, two='hi', *args, **kwargs): """Expected simple_unlimited_args_kwargs __doc__""" # Sort the dictionary by key to guarantee the order for testing. sorted_kwarg = sorted(six.iteritems(kwargs), key=operator.itemgetter(0)) return "simple_unlimited_args_kwargs - Expected result: %s / %s" % ( ', '.join([six.text_type(arg) for arg in [one, two] + list(args)]), ', '.join(['%s=%s' % (k, v) for (k, v) in sorted_kwarg]) )
def value_to_db_datetime(self, value): """ Transform a datetime value to an object compatible with what is expected by the backend driver for datetime columns. """ if value is None: return None return six.text_type(value)
def test_full_clear(self): """ Integration happy-path test that a model FileField can actually be set and cleared via a ModelForm. """ form = DocumentForm() self.assertTrue('name="myfile"' in six.text_type(form)) self.assertTrue('myfile-clear' not in six.text_type(form)) form = DocumentForm(files={'myfile': SimpleUploadedFile('something.txt', b'content')}) self.assertTrue(form.is_valid()) doc = form.save(commit=False) self.assertEqual(doc.myfile.name, 'something.txt') form = DocumentForm(instance=doc) self.assertTrue('myfile-clear' in six.text_type(form)) form = DocumentForm(instance=doc, data={'myfile-clear': 'true'}) doc = form.save(commit=False) self.assertEqual(bool(doc.myfile), False)
def test_m2m_to_inheriting_model(self): qs = AuthorWithAge.objects.prefetch_related('books_with_year') with self.assertNumQueries(2): lst = [[six.text_type(book) for book in author.books_with_year.all()] for author in qs] qs = AuthorWithAge.objects.all() lst2 = [[six.text_type(book) for book in author.books_with_year.all()] for author in qs] self.assertEqual(lst, lst2) qs = BookWithYear.objects.prefetch_related('aged_authors') with self.assertNumQueries(2): lst = [[six.text_type(author) for author in book.aged_authors.all()] for book in qs] qs = BookWithYear.objects.all() lst2 = [[six.text_type(author) for author in book.aged_authors.all()] for book in qs] self.assertEqual(lst, lst2)
def _checksum(self, value): chars = '0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ' s = sum(i * chars.index(c) for i, c in zip(reversed(range(19)), value)) checksum = 10 - s % 10 if checksum == 10: return '0' return six.text_type(checksum)
def value_to_db_time(self, value): if value is None: return None # SQLite doesn't support tz-aware datetimes if timezone.is_aware(value): raise ValueError("SQLite backend does not support timezone-aware times.") return six.text_type(value)
def build_request_repr(request, path_override=None, GET_override=None, POST_override=None, COOKIES_override=None, META_override=None): """ Builds and returns the request's representation string. The request's attributes may be overridden by pre-processed values. """ # Since this is called as part of error handling, we need to be very # robust against potentially malformed input. try: get = (pformat(GET_override) if GET_override is not None else pformat(request.GET)) except Exception: get = '<could not parse>' if request._post_parse_error: post = '<could not parse>' else: try: post = (pformat(POST_override) if POST_override is not None else pformat(request.POST)) except Exception: post = '<could not parse>' try: cookies = (pformat(COOKIES_override) if COOKIES_override is not None else pformat(request.COOKIES)) except Exception: cookies = '<could not parse>' try: meta = (pformat(META_override) if META_override is not None else pformat(request.META)) except Exception: meta = '<could not parse>' path = path_override if path_override is not None else request.path return force_str('<%s\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % (request.__class__.__name__, path, six.text_type(get), six.text_type(post), six.text_type(cookies), six.text_type(meta)))
def assertHTMLEqual(self, html1, html2, msg=None): """ Asserts that two HTML snippets are semantically the same. Whitespace in most cases is ignored, and attribute ordering is not significant. The passed-in arguments must be valid HTML. """ dom1 = assert_and_parse_html(self, html1, msg, 'First argument is not valid HTML:') dom2 = assert_and_parse_html(self, html2, msg, 'Second argument is not valid HTML:') if dom1 != dom2: standardMsg = '%s != %s' % ( safe_repr(dom1, True), safe_repr(dom2, True)) diff = ('\n' + '\n'.join(difflib.ndiff( six.text_type(dom1).splitlines(), six.text_type(dom2).splitlines()))) standardMsg = self._truncateMessage(standardMsg, diff) self.fail(self._formatMessage(msg, standardMsg))
def test_get(self): """ Test that objects retrieved with .get() get the prefetch behavior. """ # Need a double with self.assertNumQueries(3): author = Author.objects.prefetch_related('books__read_by').get(name="Charlotte") lists = [[six.text_type(r) for r in b.read_by.all()] for b in author.books.all()] self.assertEqual(lists, [["Amy"], ["Belinda"]]) # Poems, Jane Eyre