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 spec_template = wtforms.SelectField( 477 "Spec template", 478 choices=[ 479 ("", "default"), 480 ("fedora", "fedora"), 481 ("epel7", "epel7"), 482 ("mageia", "mageia"), 483 ("pld", "pld"), 484 ], default="") 485 486 python_versions = MultiCheckboxField( 487 'Build for Python', 488 choices=[ 489 ('3', 'python3'), 490 ('2', 'python2') 491 ], 492 default=['3', '2']) 493 494 @property502496 return json.dumps({ 497 "pypi_package_name": self.pypi_package_name.data, 498 "pypi_package_version": self.pypi_package_version.data, 499 "spec_template": self.spec_template.data, 500 "python_versions": self.python_versions.data 501 })505 gem_name = wtforms.StringField( 506 "Gem Name", 507 validators=[wtforms.validators.DataRequired()]) 508 509 @property514517 """ 518 @deprecated 519 """ 520 git_url = wtforms.StringField( 521 "Git URL", 522 validators=[ 523 wtforms.validators.DataRequired(), 524 wtforms.validators.URL()]) 525 526 git_directory = wtforms.StringField( 527 "Git Directory", 528 validators=[ 529 wtforms.validators.Optional()]) 530 531 git_branch = wtforms.StringField( 532 "Git Branch", 533 validators=[ 534 wtforms.validators.Optional()]) 535 536 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 537 538 @property548540 return json.dumps({ 541 "type": 'git', 542 "clone_url": self.git_url.data, 543 "committish": self.git_branch.data, 544 "subdirectory": self.git_directory.data, 545 "spec": '', 546 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito', 547 })551 """ 552 @deprecated 553 """ 554 scm_type = wtforms.SelectField( 555 "SCM Type", 556 choices=[("git", "Git"), ("svn", "SVN")]) 557 558 scm_url = wtforms.StringField( 559 "SCM URL", 560 validators=[ 561 wtforms.validators.DataRequired(), 562 wtforms.validators.URL()]) 563 564 scm_branch = wtforms.StringField( 565 "Git Branch", 566 validators=[ 567 wtforms.validators.Optional()]) 568 569 scm_subdir = wtforms.StringField( 570 "Subdirectory", 571 validators=[ 572 wtforms.validators.Optional()]) 573 574 spec = wtforms.StringField( 575 "Spec File", 576 validators=[ 577 wtforms.validators.Optional(), 578 wtforms.validators.Regexp( 579 r"^.+\.spec$", 580 message="RPM spec file must end with .spec")]) 581 582 @property592595 """ 596 @deprecated 597 """ 598 clone_url = wtforms.StringField( 599 "Clone Url", 600 validators=[wtforms.validators.DataRequired()]) 601 602 branch = wtforms.StringField( 603 "Branch", 604 validators=[wtforms.validators.Optional()]) 605 606 @property616619 if not string: 620 return string 621 622 if string.split('\n')[0].endswith('\r'): 623 # This script is most probably coming from the web-UI, where 624 # web-browsers mistakenly put '\r\n' as EOL; and that would just 625 # mean that the script is not executable (any line can mean 626 # syntax error, but namely shebang would cause 100% fail) 627 string = string.replace('\r\n', '\n') 628 629 # And append newline to have a valid unix file. 630 if not string.endswith('\n'): 631 string += '\n' 632 633 return string634637 script = wtforms.TextAreaField( 638 "Script", 639 validators=[ 640 wtforms.validators.DataRequired(), 641 wtforms.validators.Length( 642 max=4096, 643 message="Maximum script size is 4kB"), 644 ], 645 filters=[cleanup_script], 646 ) 647 648 builddeps = wtforms.StringField( 649 "Build dependencies", 650 validators=[wtforms.validators.Optional()]) 651 652 chroot = wtforms.SelectField( 653 'Mock chroot', 654 choices=[], 655 default='fedora-latest-x86_64', 656 ) 657 658 resultdir = wtforms.StringField( 659 "Result directory", 660 validators=[wtforms.validators.Optional()]) 661689663 super(PackageFormCustom, self).__init__(*args, **kwargs) 664 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all() 665 666 chroots = [c.name for c in chroot_objects] 667 chroots.sort() 668 chroots = [(name, name) for name in chroots] 669 670 arches = set() 671 for ch in chroot_objects: 672 if ch.os_release == 'fedora': 673 arches.add(ch.arch) 674 675 self.chroot.choices = [] 676 if arches: 677 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches] 678 679 self.chroot.choices += chroots680 681 @property700693 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm) 694 form_cls.packages = MultiCheckboxField( 695 "Packages", 696 choices=[(name, name) for name in package_names], 697 default=package_names, 698 validators=[wtforms.validators.DataRequired()]) 699 return form_cls712 713 F.memory_reqs = wtforms.IntegerField( 714 "Memory requirements", 715 validators=[ 716 wtforms.validators.Optional(), 717 wtforms.validators.NumberRange( 718 min=constants.MIN_BUILD_MEMORY, 719 max=constants.MAX_BUILD_MEMORY)], 720 default=constants.DEFAULT_BUILD_MEMORY) 721 722 F.timeout = wtforms.IntegerField( 723 "Timeout", 724 validators=[ 725 wtforms.validators.Optional(), 726 wtforms.validators.NumberRange( 727 min=constants.MIN_BUILD_TIMEOUT, 728 max=constants.MAX_BUILD_TIMEOUT)], 729 default=constants.DEFAULT_BUILD_TIMEOUT) 730 731 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 732 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 733 734 # overrides BasePackageForm.package_name and is unused for building 735 F.package_name = wtforms.StringField() 736 737 F.chroots_list = list(map(lambda x: x.name, active_chroots)) 738 F.chroots_list.sort() 739 F.chroots_sets = {} 740 for ch in F.chroots_list: 741 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES)) 742 if ch[0] in F.chroots_sets: 743 F.chroots_sets[ch[0]].append(ch) 744 else: 745 F.chroots_sets[ch[0]] = [ch] 746 return F 747 752 760 768 773 778 783704 class F(form): 705 @property 706 def selected_chroots(self): 707 selected = [] 708 for ch in self.chroots_list: 709 if getattr(self, ch).data: 710 selected.append(ch) 711 return selected792 797787 form = BaseBuildFormFactory(active_chroots, FlaskForm) 788 form.pkgs = FileField('srpm', validators=[ 789 FileRequired(), 790 SrpmValidator()]) 791 return form810801 form = BaseBuildFormFactory(active_chroots, FlaskForm) 802 form.pkgs = wtforms.TextAreaField( 803 "Pkgs", 804 validators=[ 805 wtforms.validators.DataRequired(message="URLs to packages are required"), 806 UrlListValidator(), 807 UrlSrpmListValidator()], 808 filters=[StringListFilter()]) 809 return form813 modulemd = FileField("modulemd", validators=[ 814 FileRequired(), 815 # @TODO Validate modulemd.yaml file 816 ]) 817 818 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES) 819 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)820823 modulemd = FileField("modulemd") 824 scmurl = wtforms.StringField() 825 branch = wtforms.StringField()826829 repo_url = wtforms.StringField("repo_url", default='') 830 api_key = wtforms.StringField("api_key", default='') 831838841 842 """ 843 Validator for editing chroots in project 844 (adding packages to minimal chroot) 845 """ 846 847 buildroot_pkgs = wtforms.TextField("Packages") 848 849 repos = wtforms.TextAreaField('Repos', 850 validators=[UrlRepoListValidator(), 851 wtforms.validators.Optional()], 852 filters=[StringListFilter()]) 853 854 module_md = FileField("module_md") 855 856 comps = FileField("comps_xml") 857 858 with_opts = wtforms.TextField("With options") 859 without_opts = wtforms.TextField("Without options")860862 comment = wtforms.TextAreaField("Comment")863866 867 @staticmethod 871 872 builder_default = False 873 admin_default = False 874 875 if permission: 876 if permission.copr_builder != helpers.PermissionEnum("nothing"): 877 builder_default = True 878 if permission.copr_admin != helpers.PermissionEnum("nothing"): 879 admin_default = True 880 881 setattr(F, "copr_builder", 882 wtforms.BooleanField( 883 default=builder_default, 884 false_values=FALSE_VALUES, 885 filters=[ValueToPermissionNumberFilter()])) 886 887 setattr(F, "copr_admin", 888 wtforms.BooleanField( 889 default=admin_default, 890 false_values=FALSE_VALUES, 891 filters=[ValueToPermissionNumberFilter()])) 892 893 return F894897 898 """Creates a dynamic form for given set of copr permissions""" 899 @staticmethod 903 904 for perm in permissions: 905 builder_choices = helpers.PermissionEnum.choices_list() 906 admin_choices = helpers.PermissionEnum.choices_list() 907 908 builder_default = perm.copr_builder 909 admin_default = perm.copr_admin 910 911 setattr(F, "copr_builder_{0}".format(perm.user.id), 912 wtforms.SelectField( 913 choices=builder_choices, 914 default=builder_default, 915 coerce=int)) 916 917 setattr(F, "copr_admin_{0}".format(perm.user.id), 918 wtforms.SelectField( 919 choices=admin_choices, 920 default=admin_default, 921 coerce=int)) 922 923 return F924927 description = wtforms.TextAreaField('Description', 928 validators=[wtforms.validators.Optional()]) 929 930 instructions = wtforms.TextAreaField('Instructions', 931 validators=[wtforms.validators.Optional()]) 932 933 chroots = wtforms.TextAreaField('Chroots', 934 validators=[wtforms.validators.Optional(), ChrootsValidator()]) 935 936 repos = wtforms.TextAreaField('Repos', 937 validators=[UrlRepoListValidator(), 938 wtforms.validators.Optional()], 939 filters=[StringListFilter()]) 940 941 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 942 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 943 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 944 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 945 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 946 947 # Deprecated, use `enable_net` instead 948 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 949 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)950953 @staticmethod976955 class F(FlaskForm): 956 source = wtforms.StringField( 957 "Source", 958 default=copr.full_name) 959 960 owner = wtforms.SelectField( 961 "Fork owner", 962 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups], 963 default=user.name, 964 validators=[wtforms.validators.DataRequired()]) 965 966 name = wtforms.StringField( 967 "Fork name", 968 default=copr.name, 969 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()]) 970 971 confirm = wtforms.BooleanField( 972 "Confirm", 973 false_values=FALSE_VALUES, 974 default=False)975 return F979 buildroot_pkgs = wtforms.TextField('Additional packages to be always present in minimal buildroot') 980 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot', 981 validators=[UrlRepoListValidator(), 982 wtforms.validators.Optional()], 983 filters=[StringListFilter()]) 984 comps = None 985 upload_comps = FileField("Upload comps.xml") 986 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)987 990993 project = wtforms.TextField("Project")9949971006999 if not message: 1000 message = "Group with the alias '{}' already exists." 1001 self.message = message10021004 if UsersLogic.group_alias_exists(field.data): 1005 raise wtforms.ValidationError(self.message.format(field.data))1009 1010 name = wtforms.StringField( 1011 validators=[ 1012 wtforms.validators.Regexp( 1013 re.compile(r"^[\w.-]+$"), 1014 message="Name must contain only letters," 1015 "digits, underscores, dashes and dots."), 1016 GroupUniqueNameValidator() 1017 ] 1018 )10191022 builds = wtforms.FieldList(wtforms.StringField("Builds ID list")) 1023 packages = wtforms.FieldList(wtforms.StringField("Packages list")) 1024 filter = wtforms.FieldList(wtforms.StringField("Package Filter")) 1025 api = wtforms.FieldList(wtforms.StringField("Module API")) 1026 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2) 1027 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2) 1028 103210531034 if not FlaskForm.validate(self): 1035 return False 1036 1037 # Profile names should be unique 1038 names = [x for x in self.profile_names.data if x] 1039 if len(set(names)) < len(names): 1040 self.errors["profiles"] = ["Profile names must be unique"] 1041 return False 1042 1043 # WORKAROUND 1044 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and 1045 # profile_pkgs in seconds box, it is sorted and validated correctly 1046 for i in range(0, len(self.profile_names.data)): 1047 # If profile name is not set, then there should not be any packages in this profile 1048 if not flask.request.form["profile_names-{}".format(i)]: 1049 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]: 1050 self.errors["profiles"] = ["Missing profile name"] 1051 return False 1052 return True1056 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()]) 1057 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()]) 1058 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()]) 1059 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()]) 1060 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()]) 1061 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])1062
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |