| Trees | Indices | Help |
|---|
|
|
1 import re
2 from six.moves.urllib.parse import urlparse
3
4 import flask
5 import wtforms
6 import json
7
8 from flask_wtf.file import FileAllowed, FileRequired, FileField
9
10 try: # get rid of deprecation warning with newer flask_wtf
11 from flask_wtf import FlaskForm
12 except ImportError:
13 from flask_wtf import Form as FlaskForm
14
15 from jinja2 import Markup
16
17 from coprs import constants
18 from coprs import helpers
19 from coprs import models
20 from coprs.logic.coprs_logic import CoprsLogic
21 from coprs.logic.users_logic import UsersLogic
22 from coprs.logic.modules_logic import ModulesLogic
23 from coprs.models import Package
24 from coprs import exceptions
25
26
27 FALSE_VALUES = {False, "false", ""}
31 """
32 Params
33 ------
34 source_type_text : str
35 name of the source type (scm/pypi/rubygems/git_and_tito/mock_scm)
36
37 Returns
38 -------
39 BasePackageForm child
40 based on source_type_text input
41 """
42 if source_type_text == 'scm':
43 return PackageFormScm
44 elif source_type_text == 'pypi':
45 return PackageFormPyPI
46 elif source_type_text == 'rubygems':
47 return PackageFormRubyGems
48 elif source_type_text == 'git_and_tito':
49 return PackageFormTito # deprecated
50 elif source_type_text == 'mock_scm':
51 return PackageFormMock # deprecated
52 elif source_type_text == "custom":
53 return PackageFormCustom
54 else:
55 raise exceptions.UnknownSourceTypeException("Invalid source type")
56
59 widget = wtforms.widgets.ListWidget(prefix_label=False)
60 option_widget = wtforms.widgets.CheckboxInput()
61
64
66 if not message:
67 message = ("A list of http[s] URLs separated by whitespace characters"
68 " is needed ('{0}' doesn't seem to be a valid URL).")
69 self.message = message
70
72 urls = field.data.split()
73 for u in urls:
74 if not self.is_url(u):
75 raise wtforms.ValidationError(self.message.format(u))
76
84
87 """ Allows also `repo://` schema"""
89 parsed = urlparse(url)
90 if parsed.scheme not in ["http", "https", "copr"]:
91 return False
92 if not parsed.netloc:
93 return False
94 # copr://username/projectname
95 # ^^ schema ^^ netlock ^^ path
96 if parsed.scheme == "copr":
97 # check if projectname missed
98 path_split = parsed.path.split("/")
99 if len(path_split) < 2 or path_split[1] == "":
100 return False
101
102 return True
103
107 if not message:
108 message = ("URLs must end with .src.rpm, .nosrc.rpm, or .spec"
109 " ('{0}' doesn't seem to be a valid URL).")
110 super(UrlSrpmListValidator, self).__init__(message)
111
117
121 if not message:
122 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files"
123 self.message = message
124
129
132
134 if not message:
135 if group is None:
136 message = "You already have project named '{}'."
137 else:
138 message = "Group {} ".format(group) + "already have project named '{}'."
139 self.message = message
140 if not user:
141 user = flask.g.user
142 self.user = user
143 self.group = group
144
146 if self.group:
147 existing = CoprsLogic.exists_for_group(
148 self.group, field.data).first()
149 else:
150 existing = CoprsLogic.exists_for_user(
151 self.user, field.data).first()
152
153 if existing and str(existing.id) != form.id.data:
154 raise wtforms.ValidationError(self.message.format(field.data))
155
159 if not message:
160 message = "Name must contain only letters, digits, underscores, dashes and dots."
161 self.message = message
162
168
172 # Allow it to be truly optional and has None value
173 if not field.data:
174 return
175
176 selected = set(field.data.split())
177 enabled = set(self.chroots_list())
178
179 if not (selected <= enabled):
180 raise wtforms.ValidationError("Such chroot is not enabled: {}".format(", ".join(selected - enabled)))
181
184
187
189 if not message:
190 message = "Project's name can not be just number."
191 self.message = message
192
196
213
216
218 if not value:
219 return ''
220 # Replace every whitespace string with one newline
221 # Formats ideally for html form filling, use replace('\n', ' ')
222 # to get space-separated values or split() to get list
223 result = value.strip()
224 regex = re.compile(r"\s+")
225 return regex.sub(lambda x: '\n', result)
226
229
231 if value:
232 return helpers.PermissionEnum("request")
233 return helpers.PermissionEnum("nothing")
234
237
238 @staticmethod
240 class F(FlaskForm):
241 # also use id here, to be able to find out whether user
242 # is updating a copr if so, we don't want to shout
243 # that name already exists
244 id = wtforms.HiddenField()
245 group_id = wtforms.HiddenField()
246
247 name = wtforms.StringField(
248 "Name",
249 validators=[
250 wtforms.validators.DataRequired(),
251 NameCharactersValidator(),
252 CoprUniqueNameValidator(user=user, group=group),
253 NameNotNumberValidator()
254 ])
255
256 homepage = wtforms.StringField(
257 "Homepage",
258 validators=[
259 wtforms.validators.Optional(),
260 wtforms.validators.URL()])
261
262 contact = wtforms.StringField(
263 "Contact",
264 validators=[
265 wtforms.validators.Optional(),
266 EmailOrURL()])
267
268 description = wtforms.TextAreaField("Description")
269
270 instructions = wtforms.TextAreaField("Instructions")
271
272 repos = wtforms.TextAreaField(
273 "External Repositories",
274 validators=[UrlRepoListValidator()],
275 filters=[StringListFilter()])
276
277 initial_pkgs = wtforms.TextAreaField(
278 "Initial packages to build",
279 validators=[
280 UrlListValidator(),
281 UrlSrpmListValidator()],
282 filters=[StringListFilter()])
283
284 disable_createrepo = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
285 unlisted_on_hp = wtforms.BooleanField("Do not display this project on home page", default=False, false_values=FALSE_VALUES)
286 persistent = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
287 auto_prune = wtforms.BooleanField("If backend auto-prunning script should be run for this project", default=True, false_values=FALSE_VALUES)
288 use_bootstrap_container = wtforms.BooleanField("Enable use_bootstrap_container mock's feature (experimental)", default=False, false_values=FALSE_VALUES)
289 follow_fedora_branching = wtforms.BooleanField("If newly branched chroots should be automatically enabled and populated.", default=True, false_values=FALSE_VALUES)
290
291 # Deprecated, use `enable_net` instead
292 build_enable_net = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
293 enable_net = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
294
295 @property
296 def selected_chroots(self):
297 selected = []
298 for ch in self.chroots_list:
299 if getattr(self, ch).data:
300 selected.append(ch)
301 return selected
302
303 def validate(self):
304 if not super(F, self).validate():
305 return False
306
307 if not self.validate_mock_chroots_not_empty():
308 self.errors["chroots"] = ["At least one chroot must be selected"]
309 return False
310 return True
311
312 def validate_mock_chroots_not_empty(self):
313 have_any = False
314 for c in self.chroots_list:
315 if getattr(self, c).data:
316 have_any = True
317 return have_any
318
319 F.chroots_list = list(map(lambda x: x.name,
320 models.MockChroot.query.filter(
321 models.MockChroot.is_active == True
322 ).all()))
323 F.chroots_list.sort()
324 # sets of chroots according to how we should print them in columns
325 F.chroots_sets = {}
326 for ch in F.chroots_list:
327 checkbox_default = False
328 if mock_chroots and ch in map(lambda x: x.name,
329 mock_chroots):
330 checkbox_default = True
331
332 setattr(F, ch, wtforms.BooleanField(ch, default=checkbox_default, false_values=FALSE_VALUES))
333 if ch[0] in F.chroots_sets:
334 F.chroots_sets[ch[0]].append(ch)
335 else:
336 F.chroots_sets[ch[0]] = [ch]
337
338 return F
339
342 verify = wtforms.TextField(
343 "Confirm deleting by typing 'yes'",
344 validators=[
345 wtforms.validators.Required(),
346 wtforms.validators.Regexp(
347 r"^yes$",
348 message="Type 'yes' - without the quotes, lowercase.")
349 ])
350
354
355
356 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online
357 -class BuildFormRebuildFactory(object):
358 @staticmethod
360 class F(FlaskForm):
361 @property
362 def selected_chroots(self):
363 selected = []
364 for ch in self.chroots_list:
365 if getattr(self, ch).data:
366 selected.append(ch)
367 return selected
368
369 memory_reqs = wtforms.IntegerField(
370 "Memory requirements",
371 validators=[
372 wtforms.validators.NumberRange(
373 min=constants.MIN_BUILD_MEMORY,
374 max=constants.MAX_BUILD_MEMORY)],
375 default=constants.DEFAULT_BUILD_MEMORY)
376
377 timeout = wtforms.IntegerField(
378 "Timeout",
379 validators=[
380 wtforms.validators.NumberRange(
381 min=constants.MIN_BUILD_TIMEOUT,
382 max=constants.MAX_BUILD_TIMEOUT)],
383 default=constants.DEFAULT_BUILD_TIMEOUT)
384
385 enable_net = wtforms.BooleanField(false_values=FALSE_VALUES)
386 background = wtforms.BooleanField(false_values=FALSE_VALUES)
387
388 F.chroots_list = list(map(lambda x: x.name, active_chroots))
389 F.chroots_list.sort()
390 F.chroots_sets = {}
391 for ch in F.chroots_list:
392 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES))
393 if ch[0] in F.chroots_sets:
394 F.chroots_sets[ch[0]].append(ch)
395 else:
396 F.chroots_sets[ch[0]] = [ch]
397
398 return F
399
402 @staticmethod
404 form = BuildFormRebuildFactory.create_form_cls(active_chroots)
405 form.package_name = wtforms.StringField(
406 "Package name",
407 validators=[wtforms.validators.DataRequired()])
408 return form
409
412 package_name = wtforms.StringField(
413 "Package name",
414 validators=[wtforms.validators.DataRequired()])
415 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
416
419 scm_type = wtforms.SelectField(
420 "Type",
421 choices=[("git", "Git"), ("svn", "SVN")],
422 default="git")
423
424 clone_url = wtforms.StringField(
425 "Clone url",
426 validators=[
427 wtforms.validators.DataRequired(),
428 wtforms.validators.URL()])
429
430 committish = wtforms.StringField(
431 "Committish",
432 validators=[
433 wtforms.validators.Optional()])
434
435 subdirectory = wtforms.StringField(
436 "Subdirectory",
437 validators=[
438 wtforms.validators.Optional()])
439
440 spec = wtforms.StringField(
441 "Spec File",
442 validators=[
443 wtforms.validators.Optional(),
444 wtforms.validators.Regexp(
445 r"^.+\.spec$",
446 message="RPM spec file must end with .spec")])
447
448 srpm_build_method = wtforms.SelectField(
449 "SRPM build method",
450 choices=[(x, x) for x in ["rpkg", "tito", "tito_test", "make_srpm"]],
451 default="rpkg")
452
453 @property
455 return json.dumps({
456 "type": self.scm_type.data,
457 "clone_url": self.clone_url.data,
458 "subdirectory": self.subdirectory.data,
459 "committish": self.committish.data,
460 "spec": self.spec.data,
461 "srpm_build_method": self.srpm_build_method.data,
462 })
463
466 pypi_package_name = wtforms.StringField(
467 "PyPI package name",
468 validators=[wtforms.validators.DataRequired()])
469
470 pypi_package_version = wtforms.StringField(
471 "PyPI package version",
472 validators=[
473 wtforms.validators.Optional(),
474 ])
475
476 python_versions = MultiCheckboxField(
477 'Build for Python',
478 choices=[
479 ('3', 'python3'),
480 ('2', 'python2')
481 ],
482 default=['3', '2'])
483
484 @property
486 return json.dumps({
487 "pypi_package_name": self.pypi_package_name.data,
488 "pypi_package_version": self.pypi_package_version.data,
489 "python_versions": self.python_versions.data
490 })
491
494 gem_name = wtforms.StringField(
495 "Gem Name",
496 validators=[wtforms.validators.DataRequired()])
497
498 @property
503
506 """
507 @deprecated
508 """
509 git_url = wtforms.StringField(
510 "Git URL",
511 validators=[
512 wtforms.validators.DataRequired(),
513 wtforms.validators.URL()])
514
515 git_directory = wtforms.StringField(
516 "Git Directory",
517 validators=[
518 wtforms.validators.Optional()])
519
520 git_branch = wtforms.StringField(
521 "Git Branch",
522 validators=[
523 wtforms.validators.Optional()])
524
525 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
526
527 @property
529 return json.dumps({
530 "type": 'git',
531 "clone_url": self.git_url.data,
532 "committish": self.git_branch.data,
533 "subdirectory": self.git_directory.data,
534 "spec": '',
535 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito',
536 })
537
540 """
541 @deprecated
542 """
543 scm_type = wtforms.SelectField(
544 "SCM Type",
545 choices=[("git", "Git"), ("svn", "SVN")])
546
547 scm_url = wtforms.StringField(
548 "SCM URL",
549 validators=[
550 wtforms.validators.DataRequired(),
551 wtforms.validators.URL()])
552
553 scm_branch = wtforms.StringField(
554 "Git Branch",
555 validators=[
556 wtforms.validators.Optional()])
557
558 scm_subdir = wtforms.StringField(
559 "Subdirectory",
560 validators=[
561 wtforms.validators.Optional()])
562
563 spec = wtforms.StringField(
564 "Spec File",
565 validators=[
566 wtforms.validators.Optional(),
567 wtforms.validators.Regexp(
568 r"^.+\.spec$",
569 message="RPM spec file must end with .spec")])
570
571 @property
581
584 """
585 @deprecated
586 """
587 clone_url = wtforms.StringField(
588 "Clone Url",
589 validators=[wtforms.validators.DataRequired()])
590
591 branch = wtforms.StringField(
592 "Branch",
593 validators=[wtforms.validators.Optional()])
594
595 @property
605
608 if not string:
609 return string
610
611 if string.split('\n')[0].endswith('\r'):
612 # This script is most probably coming from the web-UI, where
613 # web-browsers mistakenly put '\r\n' as EOL; and that would just
614 # mean that the script is not executable (any line can mean
615 # syntax error, but namely shebang would cause 100% fail)
616 string = string.replace('\r\n', '\n')
617
618 # And append newline to have a valid unix file.
619 if not string.endswith('\n'):
620 string += '\n'
621
622 return string
623
626 script = wtforms.TextAreaField(
627 "Script",
628 validators=[
629 wtforms.validators.DataRequired(),
630 wtforms.validators.Length(
631 max=4096,
632 message="Maximum script size is 4kB"),
633 ],
634 filters=[cleanup_script],
635 )
636
637 builddeps = wtforms.StringField(
638 "Build dependencies",
639 validators=[wtforms.validators.Optional()])
640
641 chroot = wtforms.SelectField(
642 'Mock chroot',
643 choices=[],
644 default='fedora-latest-x86_64',
645 )
646
647 resultdir = wtforms.StringField(
648 "Result directory",
649 validators=[wtforms.validators.Optional()])
650
652 super(PackageFormCustom, self).__init__(*args, **kwargs)
653 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all()
654
655 chroots = [c.name for c in chroot_objects]
656 chroots.sort()
657 chroots = [(name, name) for name in chroots]
658
659 arches = set()
660 for ch in chroot_objects:
661 if ch.os_release == 'fedora':
662 arches.add(ch.arch)
663
664 self.chroot.choices = []
665 if arches:
666 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches]
667
668 self.chroot.choices += chroots
669
670 @property
678
682 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm)
683 form_cls.packages = MultiCheckboxField(
684 "Packages",
685 choices=[(name, name) for name in package_names],
686 default=package_names,
687 validators=[wtforms.validators.DataRequired()])
688 return form_cls
689
693 class F(form):
694 @property
695 def selected_chroots(self):
696 selected = []
697 for ch in self.chroots_list:
698 if getattr(self, ch).data:
699 selected.append(ch)
700 return selected
701
702 F.memory_reqs = wtforms.IntegerField(
703 "Memory requirements",
704 validators=[
705 wtforms.validators.Optional(),
706 wtforms.validators.NumberRange(
707 min=constants.MIN_BUILD_MEMORY,
708 max=constants.MAX_BUILD_MEMORY)],
709 default=constants.DEFAULT_BUILD_MEMORY)
710
711 F.timeout = wtforms.IntegerField(
712 "Timeout",
713 validators=[
714 wtforms.validators.Optional(),
715 wtforms.validators.NumberRange(
716 min=constants.MIN_BUILD_TIMEOUT,
717 max=constants.MAX_BUILD_TIMEOUT)],
718 default=constants.DEFAULT_BUILD_TIMEOUT)
719
720 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES)
721 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)
722
723 # overrides BasePackageForm.package_name and is unused for building
724 F.package_name = wtforms.StringField()
725
726 F.chroots_list = list(map(lambda x: x.name, active_chroots))
727 F.chroots_list.sort()
728 F.chroots_sets = {}
729 for ch in F.chroots_list:
730 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES))
731 if ch[0] in F.chroots_sets:
732 F.chroots_sets[ch[0]].append(ch)
733 else:
734 F.chroots_sets[ch[0]] = [ch]
735 return F
736
741
749
757
762
767
772
776 form = BaseBuildFormFactory(active_chroots, FlaskForm)
777 form.pkgs = FileField('srpm', validators=[
778 FileRequired(),
779 SrpmValidator()])
780 return form
781
786
790 form = BaseBuildFormFactory(active_chroots, FlaskForm)
791 form.pkgs = wtforms.TextAreaField(
792 "Pkgs",
793 validators=[
794 wtforms.validators.DataRequired(message="URLs to packages are required"),
795 UrlListValidator(),
796 UrlSrpmListValidator()],
797 filters=[StringListFilter()])
798 return form
799
802 modulemd = FileField("modulemd", validators=[
803 FileRequired(),
804 # @TODO Validate modulemd.yaml file
805 ])
806
807 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES)
808 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)
809
812 modulemd = FileField("modulemd")
813 scmurl = wtforms.StringField()
814 branch = wtforms.StringField()
815
818 repo_url = wtforms.StringField("repo_url", default='')
819 api_key = wtforms.StringField("api_key", default='')
820
827
830
831 """
832 Validator for editing chroots in project
833 (adding packages to minimal chroot)
834 """
835
836 buildroot_pkgs = wtforms.TextField("Packages")
837
838 repos = wtforms.TextAreaField('Repos',
839 validators=[UrlRepoListValidator(),
840 wtforms.validators.Optional()],
841 filters=[StringListFilter()])
842
843 module_md = FileField("module_md")
844
845 comps = FileField("comps_xml")
846
847 with_opts = wtforms.TextField("With options")
848 without_opts = wtforms.TextField("Without options")
849
851 comment = wtforms.TextAreaField("Comment")
852
855
856 @staticmethod
860
861 builder_default = False
862 admin_default = False
863
864 if permission:
865 if permission.copr_builder != helpers.PermissionEnum("nothing"):
866 builder_default = True
867 if permission.copr_admin != helpers.PermissionEnum("nothing"):
868 admin_default = True
869
870 setattr(F, "copr_builder",
871 wtforms.BooleanField(
872 default=builder_default,
873 false_values=FALSE_VALUES,
874 filters=[ValueToPermissionNumberFilter()]))
875
876 setattr(F, "copr_admin",
877 wtforms.BooleanField(
878 default=admin_default,
879 false_values=FALSE_VALUES,
880 filters=[ValueToPermissionNumberFilter()]))
881
882 return F
883
886
887 """Creates a dynamic form for given set of copr permissions"""
888 @staticmethod
892
893 for perm in permissions:
894 builder_choices = helpers.PermissionEnum.choices_list()
895 admin_choices = helpers.PermissionEnum.choices_list()
896
897 builder_default = perm.copr_builder
898 admin_default = perm.copr_admin
899
900 setattr(F, "copr_builder_{0}".format(perm.user.id),
901 wtforms.SelectField(
902 choices=builder_choices,
903 default=builder_default,
904 coerce=int))
905
906 setattr(F, "copr_admin_{0}".format(perm.user.id),
907 wtforms.SelectField(
908 choices=admin_choices,
909 default=admin_default,
910 coerce=int))
911
912 return F
913
916 description = wtforms.TextAreaField('Description',
917 validators=[wtforms.validators.Optional()])
918
919 instructions = wtforms.TextAreaField('Instructions',
920 validators=[wtforms.validators.Optional()])
921
922 chroots = wtforms.TextAreaField('Chroots',
923 validators=[wtforms.validators.Optional(), ChrootsValidator()])
924
925 repos = wtforms.TextAreaField('Repos',
926 validators=[UrlRepoListValidator(),
927 wtforms.validators.Optional()],
928 filters=[StringListFilter()])
929
930 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
931 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
932 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
933 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
934 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
935
936 # Deprecated, use `enable_net` instead
937 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
938 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)
939
942 @staticmethod
944 class F(FlaskForm):
945 source = wtforms.StringField(
946 "Source",
947 default=copr.full_name)
948
949 owner = wtforms.SelectField(
950 "Fork owner",
951 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups],
952 default=user.name,
953 validators=[wtforms.validators.DataRequired()])
954
955 name = wtforms.StringField(
956 "Fork name",
957 default=copr.name,
958 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()])
959
960 confirm = wtforms.BooleanField(
961 "Confirm",
962 false_values=FALSE_VALUES,
963 default=False)
964 return F
965
968 buildroot_pkgs = wtforms.TextField('Additional packages to be always present in minimal buildroot')
969 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot',
970 validators=[UrlRepoListValidator(),
971 wtforms.validators.Optional()],
972 filters=[StringListFilter()])
973 comps = None
974 upload_comps = FileField("Upload comps.xml")
975 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)
976
979
982 project = wtforms.TextField("Project")
983
986
988 if not message:
989 message = "Group with the alias '{}' already exists."
990 self.message = message
991
993 if UsersLogic.group_alias_exists(field.data):
994 raise wtforms.ValidationError(self.message.format(field.data))
995
998
999 name = wtforms.StringField(
1000 validators=[
1001 wtforms.validators.Regexp(
1002 re.compile(r"^[\w.-]+$"),
1003 message="Name must contain only letters,"
1004 "digits, underscores, dashes and dots."),
1005 GroupUniqueNameValidator()
1006 ]
1007 )
1008
1011 builds = wtforms.FieldList(wtforms.StringField("Builds ID list"))
1012 packages = wtforms.FieldList(wtforms.StringField("Packages list"))
1013 filter = wtforms.FieldList(wtforms.StringField("Package Filter"))
1014 api = wtforms.FieldList(wtforms.StringField("Module API"))
1015 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2)
1016 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2)
1017
1021
1023 if not FlaskForm.validate(self):
1024 return False
1025
1026 # Profile names should be unique
1027 names = [x for x in self.profile_names.data if x]
1028 if len(set(names)) < len(names):
1029 self.errors["profiles"] = ["Profile names must be unique"]
1030 return False
1031
1032 # WORKAROUND
1033 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and
1034 # profile_pkgs in seconds box, it is sorted and validated correctly
1035 for i in range(0, len(self.profile_names.data)):
1036 # If profile name is not set, then there should not be any packages in this profile
1037 if not flask.request.form["profile_names-{}".format(i)]:
1038 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]:
1039 self.errors["profiles"] = ["Missing profile name"]
1040 return False
1041 return True
1042
1045 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()])
1046 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()])
1047 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()])
1048 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()])
1049 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()])
1050 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])
1051
| Trees | Indices | Help |
|---|
| Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |