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 FileRequired, FileField 9 from fnmatch import fnmatch 10 11 try: # get rid of deprecation warning with newer flask_wtf 12 from flask_wtf import FlaskForm 13 except ImportError: 14 from flask_wtf import Form as FlaskForm 15 16 from coprs import constants 17 from coprs import helpers 18 from coprs import models 19 from coprs.logic.coprs_logic import CoprsLogic, MockChrootsLogic 20 from coprs.logic.users_logic import UsersLogic 21 from coprs import exceptions 22 23 24 FALSE_VALUES = {False, "false", ""}28 """ 29 Params 30 ------ 31 source_type_text : str 32 name of the source type (scm/pypi/rubygems/git_and_tito/mock_scm) 33 34 Returns 35 ------- 36 BasePackageForm child 37 based on source_type_text input 38 """ 39 if source_type_text == 'scm': 40 return PackageFormScm 41 elif source_type_text == 'pypi': 42 return PackageFormPyPI 43 elif source_type_text == 'rubygems': 44 return PackageFormRubyGems 45 elif source_type_text == 'git_and_tito': 46 return PackageFormTito # deprecated 47 elif source_type_text == 'mock_scm': 48 return PackageFormMock # deprecated 49 elif source_type_text == "custom": 50 return PackageFormCustom 51 else: 52 raise exceptions.UnknownSourceTypeException("Invalid source type")5356 widget = wtforms.widgets.ListWidget(prefix_label=False) 57 option_widget = wtforms.widgets.CheckboxInput()58618163 if not message: 64 message = ("A list of http[s] URLs separated by whitespace characters" 65 " is needed ('{0}' doesn't seem to be a valid URL).") 66 self.message = message6769 urls = field.data.split() 70 for u in urls: 71 if not self.is_url(u): 72 raise wtforms.ValidationError(self.message.format(u))7384 """ Allows also `repo://` schema"""10086 parsed = urlparse(url) 87 if parsed.scheme not in ["http", "https", "copr"]: 88 return False 89 if not parsed.netloc: 90 return False 91 # copr://username/projectname 92 # ^^ schema ^^ netlock ^^ path 93 if parsed.scheme == "copr": 94 # check if projectname missed 95 path_split = parsed.path.split("/") 96 if len(path_split) < 2 or path_split[1] == "": 97 return False 98 99 return True114104 if not message: 105 message = ("URLs must end with .src.rpm, .nosrc.rpm, or .spec" 106 " ('{0}' doesn't seem to be a valid URL).") 107 super(UrlSrpmListValidator, self).__init__(message)108126118 if not message: 119 message = "You can upload only .src.rpm, .nosrc.rpm, and .spec files" 120 self.message = message121129152131 if not message: 132 if group is None: 133 message = "You already have project named '{}'." 134 else: 135 message = "Group {} ".format(group) + "already have project named '{}'." 136 self.message = message 137 if not user: 138 user = flask.g.user 139 self.user = user 140 self.group = group141143 if self.group: 144 existing = CoprsLogic.exists_for_group( 145 self.group, field.data).first() 146 else: 147 existing = CoprsLogic.exists_for_user( 148 self.user, field.data).first() 149 150 if existing and str(existing.id) != form.id.data: 151 raise wtforms.ValidationError(self.message.format(field.data))165156 if not message: 157 message = "Name must contain only letters, digits, underscores, dashes and dots." 158 self.message = message159178169 # Allow it to be truly optional and has None value 170 if not field.data: 171 return 172 173 selected = set(field.data.split()) 174 enabled = set(MockChrootsLogic.active_names()) 175 176 if selected - enabled: 177 raise wtforms.ValidationError("Such chroot is not available: {}".format(", ".join(selected - enabled)))181190 207183 if not message: 184 message = "Project's name can not be just number." 185 self.message = message186210220212 if not value: 213 return '' 214 # Replace every whitespace string with one newline 215 # Formats ideally for html form filling, use replace('\n', ' ') 216 # to get space-separated values or split() to get list 217 result = value.strip() 218 regex = re.compile(r"\s+") 219 return regex.sub(lambda x: '\n', result)223228225 if value: 226 return helpers.PermissionEnum("request") 227 return helpers.PermissionEnum("nothing")231 232 @staticmethod363 364 def validate_mock_chroots_not_empty(self): 365 have_any = False 366 for c in self.chroots_list: 367 if getattr(self, c).data: 368 have_any = True 369 return have_any 370 371 F.chroots_list = MockChrootsLogic.active_names() 372 F.chroots_list.sort() 373 # sets of chroots according to how we should print them in columns 374 F.chroots_sets = {} 375 for ch in F.chroots_list: 376 checkbox_default = False 377 if mock_chroots and ch in [x.name for x in mock_chroots]: 378 checkbox_default = True 379 380 setattr(F, ch, wtforms.BooleanField(ch, default=checkbox_default, false_values=FALSE_VALUES)) 381 if ch[0] in F.chroots_sets: 382 F.chroots_sets[ch[0]].append(ch) 383 else: 384 F.chroots_sets[ch[0]] = [ch] 385 386 return F 387234 class F(FlaskForm): 235 # also use id here, to be able to find out whether user 236 # is updating a copr if so, we don't want to shout 237 # that name already exists 238 id = wtforms.HiddenField() 239 group_id = wtforms.HiddenField() 240 241 name = wtforms.StringField( 242 "Name", 243 validators=[ 244 wtforms.validators.DataRequired(), 245 NameCharactersValidator(), 246 CoprUniqueNameValidator(user=user, group=group), 247 NameNotNumberValidator() 248 ]) 249 250 homepage = wtforms.StringField( 251 "Homepage", 252 validators=[ 253 wtforms.validators.Optional(), 254 wtforms.validators.URL()]) 255 256 contact = wtforms.StringField( 257 "Contact", 258 validators=[ 259 wtforms.validators.Optional(), 260 EmailOrURL()]) 261 262 description = wtforms.TextAreaField("Description") 263 264 instructions = wtforms.TextAreaField("Instructions") 265 266 delete_after_days = wtforms.IntegerField( 267 "Delete after days", 268 validators=[ 269 wtforms.validators.Optional(), 270 wtforms.validators.NumberRange(min=0, max=60), 271 ], 272 render_kw={'disabled': bool(copr and copr.persistent)}) 273 274 repos = wtforms.TextAreaField( 275 "External Repositories", 276 validators=[UrlRepoListValidator()], 277 filters=[StringListFilter()]) 278 279 initial_pkgs = wtforms.TextAreaField( 280 "Initial packages to build", 281 validators=[ 282 UrlListValidator(), 283 UrlSrpmListValidator()], 284 filters=[StringListFilter()]) 285 286 disable_createrepo = wtforms.BooleanField(default=False, 287 label="Create repositories manually", 288 description="""Repository meta data is normally refreshed 289 after each build. If you want to do this manually, turn 290 this option on.""", 291 false_values=FALSE_VALUES) 292 293 unlisted_on_hp = wtforms.BooleanField( 294 "Project will not be listed on home page", 295 default=False, 296 false_values=FALSE_VALUES) 297 298 persistent = wtforms.BooleanField( 299 "Protect project and its builds against deletion", 300 description="""Project's builds and the project itself 301 cannot be deleted by any means. This option is set once and 302 for all (this option can not be changed after project is 303 created).""", 304 render_kw={'disabled': bool(copr)}, 305 default=False, false_values=FALSE_VALUES) 306 307 auto_prune = wtforms.BooleanField( 308 "Old builds will be deleted automatically", 309 default=True, false_values=FALSE_VALUES, 310 description="""Build will be deleted only if there is a 311 newer build (with respect to package version) and it is 312 older than 14 days""") 313 314 use_bootstrap_container = wtforms.BooleanField( 315 "Enable mock's use_bootstrap_container experimental feature", 316 description="""This will make the build slower but it has an 317 advantage that the dnf _from_ the given chroot will be used 318 to setup the chroot (otherwise host system dnf and rpm is 319 used)""", 320 default=False, 321 false_values=FALSE_VALUES) 322 323 follow_fedora_branching = wtforms.BooleanField( 324 "Follow Fedora branching", 325 description="""When Fedora is branched from rawhide, the 326 respective chroots for the new branch are automatically 327 created for you (as soon as they are available) as rawhide 328 chroot forks.""", 329 default=True, 330 false_values=FALSE_VALUES) 331 332 # Deprecated, use `enable_net` instead 333 build_enable_net = wtforms.BooleanField( 334 "Enable internet access during builds", 335 default=False, false_values=FALSE_VALUES) 336 337 enable_net = wtforms.BooleanField( 338 "Enable internet access during builds", 339 default=False, false_values=FALSE_VALUES) 340 341 @property 342 def selected_chroots(self): 343 selected = [] 344 for ch in self.chroots_list: 345 if getattr(self, ch).data: 346 selected.append(ch) 347 return selected348 349 def validate(self): 350 if not super(F, self).validate(): 351 return False 352 353 if not self.validate_mock_chroots_not_empty(): 354 self.errors["chroots"] = ["At least one chroot must be selected"] 355 return False 356 357 if self.persistent.data and self.delete_after_days.data: 358 self.delete_after_days.errors.append( 359 "'delete after' can not be combined with persistent") 360 return False 361 362 return True390 verify = wtforms.TextField( 391 "Confirm deleting by typing 'yes'", 392 validators=[ 393 wtforms.validators.DataRequired(), 394 wtforms.validators.Regexp( 395 r"^yes$", 396 message="Type 'yes' - without the quotes, lowercase.") 397 ])398 402403 404 # @TODO jkadlcik - rewrite via BaseBuildFormFactory after fe-dev-cloud is back online 405 -class BuildFormRebuildFactory(object):406 @staticmethod436 437 F.chroots_list = list(map(lambda x: x.name, active_chroots)) 438 F.chroots_list.sort() 439 F.chroots_sets = {} 440 for ch in F.chroots_list: 441 setattr(F, ch, wtforms.BooleanField(ch, default=True, false_values=FALSE_VALUES)) 442 if ch[0] in F.chroots_sets: 443 F.chroots_sets[ch[0]].append(ch) 444 else: 445 F.chroots_sets[ch[0]] = [ch] 446 447 return F 448408 class F(FlaskForm): 409 @property 410 def selected_chroots(self): 411 selected = [] 412 for ch in self.chroots_list: 413 if getattr(self, ch).data: 414 selected.append(ch) 415 return selected416 417 memory_reqs = wtforms.IntegerField( 418 "Memory requirements", 419 validators=[ 420 wtforms.validators.NumberRange( 421 min=constants.MIN_BUILD_MEMORY, 422 max=constants.MAX_BUILD_MEMORY)], 423 default=constants.DEFAULT_BUILD_MEMORY) 424 425 timeout = wtforms.IntegerField( 426 "Timeout", 427 validators=[ 428 wtforms.validators.NumberRange( 429 min=constants.MIN_BUILD_TIMEOUT, 430 max=constants.MAX_BUILD_TIMEOUT)], 431 default=constants.DEFAULT_BUILD_TIMEOUT) 432 433 enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 434 background = wtforms.BooleanField(false_values=FALSE_VALUES) 435 project_dirname = wtforms.StringField(default=None)451 @staticmethod458453 form = BuildFormRebuildFactory.create_form_cls(active_chroots) 454 form.package_name = wtforms.StringField( 455 "Package name", 456 validators=[wtforms.validators.DataRequired()]) 457 return form461 if not string: 462 return string 463 fields = [x.lstrip().rstrip() for x in string.split(',')] 464 return ', '.join(fields)465468 if field.data: 469 string = field.data 470 fields = [x.lstrip().rstrip() for x in string.split(',')] 471 for field in fields: 472 pattern = r'^[a-z0-9-*]+$' 473 if not re.match(pattern, field): 474 raise wtforms.ValidationError('Pattern "{0}" does not match "{1}"'.format(field, pattern)) 475 476 matched = set() 477 all_chroots = MockChrootsLogic.active_names() 478 for chroot in all_chroots: 479 if fnmatch(chroot, field): 480 matched.add(chroot) 481 482 if not matched: 483 raise wtforms.ValidationError('no chroot matched by pattern "{0}"'.format(field)) 484 485 if matched == all_chroots: 486 raise wtforms.ValidationError('patterns are black-listing all chroots')487490 package_name = wtforms.StringField( 491 "Package name", 492 validators=[wtforms.validators.DataRequired()]) 493 webhook_rebuild = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 494 chroot_blacklist = wtforms.StringField( 495 "Chroot blacklist", 496 filters=[cleanup_chroot_blacklist], 497 validators=[ 498 wtforms.validators.Optional(), 499 validate_chroot_blacklist, 500 ], 501 ) 502 max_builds = wtforms.IntegerField( 503 "Max number of builds", 504 description="""Keep only the specified number of the newest-by-id builds 505 (garbage collector is run daily)""", 506 render_kw={'placeholder': 'Optional - integer, e.g. 10, zero/empty disables'}, 507 validators=[ 508 wtforms.validators.Optional(), 509 wtforms.validators.NumberRange(min=0, max=100)], 510 default=None, 511 )512515 scm_type = wtforms.SelectField( 516 "Type", 517 choices=[("git", "Git"), ("svn", "SVN")], 518 default="git") 519 520 clone_url = wtforms.StringField( 521 "Clone url", 522 validators=[ 523 wtforms.validators.DataRequired(), 524 wtforms.validators.URL()]) 525 526 committish = wtforms.StringField( 527 "Committish", 528 validators=[ 529 wtforms.validators.Optional()]) 530 531 subdirectory = wtforms.StringField( 532 "Subdirectory", 533 validators=[ 534 wtforms.validators.Optional()]) 535 536 spec = wtforms.StringField( 537 "Spec File", 538 validators=[ 539 wtforms.validators.Optional(), 540 wtforms.validators.Regexp( 541 r"^.+\.spec$", 542 message="RPM spec file must end with .spec")]) 543 544 srpm_build_method = wtforms.SelectField( 545 "SRPM build method", 546 choices=[(x, x) for x in ["rpkg", "tito", "tito_test", "make_srpm"]], 547 default="rpkg") 548 549 @property559551 return json.dumps({ 552 "type": self.scm_type.data, 553 "clone_url": self.clone_url.data, 554 "subdirectory": self.subdirectory.data, 555 "committish": self.committish.data, 556 "spec": self.spec.data, 557 "srpm_build_method": self.srpm_build_method.data, 558 })562 pypi_package_name = wtforms.StringField( 563 "PyPI package name", 564 validators=[wtforms.validators.DataRequired()]) 565 566 pypi_package_version = wtforms.StringField( 567 "PyPI package version", 568 validators=[ 569 wtforms.validators.Optional(), 570 ]) 571 572 spec_template = wtforms.SelectField( 573 "Spec template", 574 choices=[ 575 ("", "default"), 576 ("fedora", "fedora"), 577 ("epel7", "epel7"), 578 ("mageia", "mageia"), 579 ("pld", "pld"), 580 ], default="") 581 582 python_versions = MultiCheckboxField( 583 'Build for Python', 584 choices=[ 585 ('3', 'python3'), 586 ('2', 'python2') 587 ], 588 default=['3', '2']) 589 590 @property598592 return json.dumps({ 593 "pypi_package_name": self.pypi_package_name.data, 594 "pypi_package_version": self.pypi_package_version.data, 595 "spec_template": self.spec_template.data, 596 "python_versions": self.python_versions.data 597 })601 gem_name = wtforms.StringField( 602 "Gem Name", 603 validators=[wtforms.validators.DataRequired()]) 604 605 @property610613 """ 614 @deprecated 615 """ 616 git_url = wtforms.StringField( 617 "Git URL", 618 validators=[ 619 wtforms.validators.DataRequired(), 620 wtforms.validators.URL()]) 621 622 git_directory = wtforms.StringField( 623 "Git Directory", 624 validators=[ 625 wtforms.validators.Optional()]) 626 627 git_branch = wtforms.StringField( 628 "Git Branch", 629 validators=[ 630 wtforms.validators.Optional()]) 631 632 tito_test = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 633 634 @property644636 return json.dumps({ 637 "type": 'git', 638 "clone_url": self.git_url.data, 639 "committish": self.git_branch.data, 640 "subdirectory": self.git_directory.data, 641 "spec": '', 642 "srpm_build_method": 'tito_test' if self.tito_test.data else 'tito', 643 })647 """ 648 @deprecated 649 """ 650 scm_type = wtforms.SelectField( 651 "SCM Type", 652 choices=[("git", "Git"), ("svn", "SVN")]) 653 654 scm_url = wtforms.StringField( 655 "SCM URL", 656 validators=[ 657 wtforms.validators.DataRequired(), 658 wtforms.validators.URL()]) 659 660 scm_branch = wtforms.StringField( 661 "Git Branch", 662 validators=[ 663 wtforms.validators.Optional()]) 664 665 scm_subdir = wtforms.StringField( 666 "Subdirectory", 667 validators=[ 668 wtforms.validators.Optional()]) 669 670 spec = wtforms.StringField( 671 "Spec File", 672 validators=[ 673 wtforms.validators.Optional(), 674 wtforms.validators.Regexp( 675 r"^.+\.spec$", 676 message="RPM spec file must end with .spec")]) 677 678 @property688691 """ 692 @deprecated 693 """ 694 clone_url = wtforms.StringField( 695 "Clone Url", 696 validators=[wtforms.validators.DataRequired()]) 697 698 branch = wtforms.StringField( 699 "Branch", 700 validators=[wtforms.validators.Optional()]) 701 702 @property712715 if not string: 716 return string 717 718 if string.split('\n')[0].endswith('\r'): 719 # This script is most probably coming from the web-UI, where 720 # web-browsers mistakenly put '\r\n' as EOL; and that would just 721 # mean that the script is not executable (any line can mean 722 # syntax error, but namely shebang would cause 100% fail) 723 string = string.replace('\r\n', '\n') 724 725 # And append newline to have a valid unix file. 726 if not string.endswith('\n'): 727 string += '\n' 728 729 return string730733 script = wtforms.TextAreaField( 734 "Script", 735 validators=[ 736 wtforms.validators.DataRequired(), 737 wtforms.validators.Length( 738 max=4096, 739 message="Maximum script size is 4kB"), 740 ], 741 filters=[cleanup_script], 742 ) 743 744 builddeps = wtforms.StringField( 745 "Build dependencies", 746 validators=[wtforms.validators.Optional()]) 747 748 chroot = wtforms.SelectField( 749 'Mock chroot', 750 choices=[], 751 default='fedora-latest-x86_64', 752 ) 753 754 resultdir = wtforms.StringField( 755 "Result directory", 756 validators=[wtforms.validators.Optional()]) 757785759 super(PackageFormCustom, self).__init__(*args, **kwargs) 760 chroot_objects = models.MockChroot.query.filter(models.MockChroot.is_active).all() 761 762 chroots = [c.name for c in chroot_objects] 763 chroots.sort() 764 chroots = [(name, name) for name in chroots] 765 766 arches = set() 767 for ch in chroot_objects: 768 if ch.os_release == 'fedora': 769 arches.add(ch.arch) 770 771 self.chroot.choices = [] 772 if arches: 773 self.chroot.choices += [('fedora-latest-' + l, 'fedora-latest-' + l) for l in arches] 774 775 self.chroot.choices += chroots776 777 @property796789 form_cls = BaseBuildFormFactory(active_chroots, FlaskForm) 790 form_cls.packages = MultiCheckboxField( 791 "Packages", 792 choices=[(name, name) for name in package_names], 793 default=package_names, 794 validators=[wtforms.validators.DataRequired()]) 795 return form_cls808 809 F.memory_reqs = wtforms.IntegerField( 810 "Memory requirements", 811 validators=[ 812 wtforms.validators.Optional(), 813 wtforms.validators.NumberRange( 814 min=constants.MIN_BUILD_MEMORY, 815 max=constants.MAX_BUILD_MEMORY)], 816 default=constants.DEFAULT_BUILD_MEMORY) 817 818 F.timeout = wtforms.IntegerField( 819 "Timeout", 820 validators=[ 821 wtforms.validators.Optional(), 822 wtforms.validators.NumberRange( 823 min=constants.MIN_BUILD_TIMEOUT, 824 max=constants.MAX_BUILD_TIMEOUT)], 825 default=constants.DEFAULT_BUILD_TIMEOUT) 826 827 F.enable_net = wtforms.BooleanField(false_values=FALSE_VALUES) 828 F.background = wtforms.BooleanField(default=False, false_values=FALSE_VALUES) 829 F.project_dirname = wtforms.StringField(default=None) 830 831 # overrides BasePackageForm.package_name and is unused for building 832 F.package_name = wtforms.StringField() 833 834 # fill chroots based on project settings 835 F.chroots_list = [x.name for x in active_chroots] 836 F.chroots_list.sort() 837 F.chroots_sets = {} 838 839 package_chroots = set(F.chroots_list) 840 if package: 841 package_chroots = set([ch.name for ch in package.chroots]) 842 843 for ch in F.chroots_list: 844 default = ch in package_chroots 845 setattr(F, ch, wtforms.BooleanField(ch, default=default, false_values=FALSE_VALUES)) 846 if ch[0] in F.chroots_sets: 847 F.chroots_sets[ch[0]].append(ch) 848 else: 849 F.chroots_sets[ch[0]] = [ch] 850 return F 851 856 864 872 877 882 887800 class F(form): 801 @property 802 def selected_chroots(self): 803 selected = [] 804 for ch in self.chroots_list: 805 if getattr(self, ch).data: 806 selected.append(ch) 807 return selected896 901891 form = BaseBuildFormFactory(active_chroots, FlaskForm) 892 form.pkgs = FileField('srpm', validators=[ 893 FileRequired(), 894 SrpmValidator()]) 895 return form914905 form = BaseBuildFormFactory(active_chroots, FlaskForm) 906 form.pkgs = wtforms.TextAreaField( 907 "Pkgs", 908 validators=[ 909 wtforms.validators.DataRequired(message="URLs to packages are required"), 910 UrlListValidator(), 911 UrlSrpmListValidator()], 912 filters=[StringListFilter()]) 913 return form917 modulemd = FileField("modulemd", validators=[ 918 FileRequired(), 919 # @TODO Validate modulemd.yaml file 920 ]) 921 922 create = wtforms.BooleanField("create", default=True, false_values=FALSE_VALUES) 923 build = wtforms.BooleanField("build", default=True, false_values=FALSE_VALUES)924927 modulemd = FileField("modulemd") 928 scmurl = wtforms.StringField() 929 branch = wtforms.StringField()930933 repo_url = wtforms.StringField("repo_url", default='') 934 api_key = wtforms.StringField("api_key", default='') 935942945 946 """ 947 Validator for editing chroots in project 948 (adding packages to minimal chroot) 949 """ 950 951 buildroot_pkgs = wtforms.TextField("Packages") 952 953 repos = wtforms.TextAreaField('Repos', 954 validators=[UrlRepoListValidator(), 955 wtforms.validators.Optional()], 956 filters=[StringListFilter()]) 957 958 comps = FileField("comps_xml") 959 960 with_opts = wtforms.TextField("With options") 961 without_opts = wtforms.TextField("Without options")962 967970 comment = wtforms.TextAreaField("Comment")971974 975 @staticmethod 979 980 builder_default = False 981 admin_default = False 982 983 if permission: 984 if permission.copr_builder != helpers.PermissionEnum("nothing"): 985 builder_default = True 986 if permission.copr_admin != helpers.PermissionEnum("nothing"): 987 admin_default = True 988 989 setattr(F, "copr_builder", 990 wtforms.BooleanField( 991 default=builder_default, 992 false_values=FALSE_VALUES, 993 filters=[ValueToPermissionNumberFilter()])) 994 995 setattr(F, "copr_admin", 996 wtforms.BooleanField( 997 default=admin_default, 998 false_values=FALSE_VALUES, 999 filters=[ValueToPermissionNumberFilter()])) 1000 1001 return F10021005 1006 """Creates a dynamic form for given set of copr permissions""" 1007 @staticmethod 1011 1012 for perm in permissions: 1013 builder_choices = helpers.PermissionEnum.choices_list() 1014 admin_choices = helpers.PermissionEnum.choices_list() 1015 1016 builder_default = perm.copr_builder 1017 admin_default = perm.copr_admin 1018 1019 setattr(F, "copr_builder_{0}".format(perm.user.id), 1020 wtforms.SelectField( 1021 choices=builder_choices, 1022 default=builder_default, 1023 coerce=int)) 1024 1025 setattr(F, "copr_admin_{0}".format(perm.user.id), 1026 wtforms.SelectField( 1027 choices=admin_choices, 1028 default=admin_default, 1029 coerce=int)) 1030 1031 return F10321035 description = wtforms.TextAreaField('Description', 1036 validators=[wtforms.validators.Optional()]) 1037 1038 instructions = wtforms.TextAreaField('Instructions', 1039 validators=[wtforms.validators.Optional()]) 1040 1041 chroots = wtforms.TextAreaField('Chroots', 1042 validators=[wtforms.validators.Optional(), ChrootsValidator()]) 1043 1044 repos = wtforms.TextAreaField('Repos', 1045 validators=[UrlRepoListValidator(), 1046 wtforms.validators.Optional()], 1047 filters=[StringListFilter()]) 1048 1049 disable_createrepo = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1050 unlisted_on_hp = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1051 auto_prune = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1052 use_bootstrap_container = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1053 follow_fedora_branching = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1054 follow_fedora_branching = wtforms.BooleanField(default=True, false_values=FALSE_VALUES) 1055 delete_after_days = wtforms.IntegerField( 1056 validators=[wtforms.validators.Optional(), 1057 wtforms.validators.NumberRange(min=-1, max=60)], 1058 filters=[(lambda x : -1 if x is None else x)]) 1059 1060 # Deprecated, use `enable_net` instead 1061 build_enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES) 1062 enable_net = wtforms.BooleanField(validators=[wtforms.validators.Optional()], false_values=FALSE_VALUES)10631066 @staticmethod10891068 class F(FlaskForm): 1069 source = wtforms.StringField( 1070 "Source", 1071 default=copr.full_name) 1072 1073 owner = wtforms.SelectField( 1074 "Fork owner", 1075 choices=[(user.name, user.name)] + [(g.at_name, g.at_name) for g in groups], 1076 default=user.name, 1077 validators=[wtforms.validators.DataRequired()]) 1078 1079 name = wtforms.StringField( 1080 "Fork name", 1081 default=copr.name, 1082 validators=[wtforms.validators.DataRequired(), NameCharactersValidator()]) 1083 1084 confirm = wtforms.BooleanField( 1085 "Confirm", 1086 false_values=FALSE_VALUES, 1087 default=False)1088 return F1092 buildroot_pkgs = wtforms.TextField('Additional packages to be always present in minimal buildroot') 1093 repos = wtforms.TextAreaField('Additional repos to be used for builds in chroot', 1094 validators=[UrlRepoListValidator(), 1095 wtforms.validators.Optional()], 1096 filters=[StringListFilter()]) 1097 comps = None 1098 upload_comps = FileField("Upload comps.xml") 1099 delete_comps = wtforms.BooleanField("Delete comps.xml", false_values=FALSE_VALUES)1100 11031106 project = wtforms.TextField("Project")1107111011191112 if not message: 1113 message = "Group with the alias '{}' already exists." 1114 self.message = message11151117 if UsersLogic.group_alias_exists(field.data): 1118 raise wtforms.ValidationError(self.message.format(field.data))1122 1123 name = wtforms.StringField( 1124 validators=[ 1125 wtforms.validators.Regexp( 1126 re.compile(r"^[\w.-]+$"), 1127 message="Name must contain only letters," 1128 "digits, underscores, dashes and dots."), 1129 GroupUniqueNameValidator() 1130 ] 1131 )11321135 builds = wtforms.FieldList(wtforms.StringField("Builds ID list")) 1136 packages = wtforms.FieldList(wtforms.StringField("Packages list")) 1137 filter = wtforms.FieldList(wtforms.StringField("Package Filter")) 1138 api = wtforms.FieldList(wtforms.StringField("Module API")) 1139 profile_names = wtforms.FieldList(wtforms.StringField("Install Profiles"), min_entries=2) 1140 profile_pkgs = wtforms.FieldList(wtforms.FieldList(wtforms.StringField("Install Profiles")), min_entries=2) 1141 114511661147 if not FlaskForm.validate(self): 1148 return False 1149 1150 # Profile names should be unique 1151 names = [x for x in self.profile_names.data if x] 1152 if len(set(names)) < len(names): 1153 self.errors["profiles"] = ["Profile names must be unique"] 1154 return False 1155 1156 # WORKAROUND 1157 # profile_pkgs are somehow sorted so if I fill profile_name in the first box and 1158 # profile_pkgs in seconds box, it is sorted and validated correctly 1159 for i in range(0, len(self.profile_names.data)): 1160 # If profile name is not set, then there should not be any packages in this profile 1161 if not flask.request.form["profile_names-{}".format(i)]: 1162 if [j for j in range(0, len(self.profile_names)) if "profile_pkgs-{}-{}".format(i, j) in flask.request.form]: 1163 self.errors["profiles"] = ["Missing profile name"] 1164 return False 1165 return True1169 owner = wtforms.StringField("Owner Name", validators=[wtforms.validators.DataRequired()]) 1170 copr = wtforms.StringField("Copr Name", validators=[wtforms.validators.DataRequired()]) 1171 name = wtforms.StringField("Name", validators=[wtforms.validators.DataRequired()]) 1172 stream = wtforms.StringField("Stream", validators=[wtforms.validators.DataRequired()]) 1173 version = wtforms.IntegerField("Version", validators=[wtforms.validators.DataRequired()]) 1174 arch = wtforms.StringField("Arch", validators=[wtforms.validators.DataRequired()])1175
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |