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")5659 widget = wtforms.widgets.ListWidget(prefix_label=False) 60 option_widget = wtforms.widgets.CheckboxInput()61648466 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 = message7072 urls = field.data.split() 73 for u in urls: 74 if not self.is_url(u): 75 raise wtforms.ValidationError(self.message.format(u))7687 """ Allows also `repo://` schema"""10389 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 True117107 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)111129121 if not message: 122 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files" 123 self.message = message124132155134 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 = group144146 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))168159 if not message: 160 message = "Name must contain only letters, digits, underscores, dashes and dots." 161 self.message = message162184172 # 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)))181187196 213189 if not message: 190 message = "Project's name can not be just number." 191 self.message = message192216226218 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)229234231 if value: 232 return helpers.PermissionEnum("request") 233 return helpers.PermissionEnum("nothing")237 238 @staticmethod311 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 339240 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 selected302 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 True342 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 354355 356 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online 357 -class BuildFormRebuildFactory(object):358 @staticmethod387 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 399360 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 selected368 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)402 @staticmethod409404 form = BuildFormRebuildFactory.create_form_cls(active_chroots) 405 form.package_name = wtforms.StringField( 406 "Package name", 407 validators=[wtforms.validators.DataRequired()]) 408 return form412 package_name = wtforms.StringField( 413 "Package name", 414 validators=[wtforms.validators.DataRequired()]) 415 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES)416419 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 @property463455 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 })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 @property491486 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 })494 gem_name = wtforms.StringField( 495 "Gem Name", 496 validators=[wtforms.validators.DataRequired()]) 497 498 @property503506 """ 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 @property537529 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 })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 @property581584 """ 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 @property605608 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 string623626 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()]) 650678652 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 += chroots669 670 @property689682 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_cls701 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 772693 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 selected781 786776 form = BaseBuildFormFactory(active_chroots, FlaskForm) 777 form.pkgs = FileField('srpm', validators=[ 778 FileRequired(), 779 SrpmValidator()]) 780 return form799790 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 form802 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)809812 modulemd = FileField("modulemd") 813 scmurl = wtforms.StringField() 814 branch = wtforms.StringField()815818 repo_url = wtforms.StringField("repo_url", default='') 819 api_key = wtforms.StringField("api_key", default='') 820827830 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")849851 comment = wtforms.TextAreaField("Comment")852855 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 F883886 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 F913916 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)939942 @staticmethod965944 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 F968 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 979982 project = wtforms.TextField("Project")983986995988 if not message: 989 message = "Group with the alias '{}' already exists." 990 self.message = message991993 if UsersLogic.group_alias_exists(field.data): 994 raise wtforms.ValidationError(self.message.format(field.data))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 )10081011 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 102110421023 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 True1045 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 |